Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/anholt/drm-intel
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/anholt/drm-intel:
drm/i915: fix page flip finish vs. prepare on plane B
drm/i915: change default panel fitting mode to preserve aspect ratio
drm/i915: fix uninitialized variable warning in i915_setup_compression()
drm/i915: take struct_mutex in i915_dma_cleanup()
drm/i915: Fix CRT hotplug regression in 2.6.35-rc1
i915: fix ironlake edp panel setup (v4)
drm/i915: don't access FW_BLC_SELF on 965G
drm/i915: Account for space on the ring buffer consumed whilst wrapping.
drm/i915: gen3 page flipping fixes
drm/i915: don't queue flips during a flip pending event
drm/i915: Fix incorrect intel_ring_begin size in BSD ringbuffer.
drm/i915: Turn on 945 self-refresh only if single CRTC is active
drm/i915/gen4: Fix interrupt setup ordering
drm/i915: Use RSEN instead of HTPLG for tfp410 monitor detection.
drm/i915: Move non-phys cursors into the GTT
Revert "drm/i915: Don't enable pipe/plane/VCO early (wait for DPMS on)."
(Included the "fix page flip finish vs. prepare on plane B" patch from
Jesse on top of the pull request from Eric. -- Linus)
diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci
index 428676c..25be325 100644
--- a/Documentation/ABI/testing/sysfs-bus-pci
+++ b/Documentation/ABI/testing/sysfs-bus-pci
@@ -133,46 +133,6 @@
The symbolic link points to the PCI device sysfs entry of the
Physical Function this device associates with.
-
-What: /sys/bus/pci/slots/...
-Date: April 2005 (possibly older)
-KernelVersion: 2.6.12 (possibly older)
-Contact: linux-pci@vger.kernel.org
-Description:
- When the appropriate driver is loaded, it will create a
- directory per claimed physical PCI slot in
- /sys/bus/pci/slots/. The names of these directories are
- specific to the driver, which in turn, are specific to the
- platform, but in general, should match the label on the
- machine's physical chassis.
-
- The drivers that can create slot directories include the
- PCI hotplug drivers, and as of 2.6.27, the pci_slot driver.
-
- The slot directories contain, at a minimum, a file named
- 'address' which contains the PCI bus:device:function tuple.
- Other files may appear as well, but are specific to the
- driver.
-
-What: /sys/bus/pci/slots/.../function[0-7]
-Date: March 2010
-KernelVersion: 2.6.35
-Contact: linux-pci@vger.kernel.org
-Description:
- If PCI slot directories (as described above) are created,
- and the physical slot is actually populated with a device,
- symbolic links in the slot directory pointing to the
- device's PCI functions are created as well.
-
-What: /sys/bus/pci/devices/.../slot
-Date: March 2010
-KernelVersion: 2.6.35
-Contact: linux-pci@vger.kernel.org
-Description:
- If PCI slot directories (as described above) are created,
- a symbolic link pointing to the slot directory will be
- created as well.
-
What: /sys/bus/pci/slots/.../module
Date: June 2009
Contact: linux-pci@vger.kernel.org
diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl
index 7583dc7..910c923 100644
--- a/Documentation/DocBook/drm.tmpl
+++ b/Documentation/DocBook/drm.tmpl
@@ -389,7 +389,7 @@
</para>
<para>
If your driver supports memory management (it should!), you'll
- need to set that up at load time as well. How you intialize
+ need to set that up at load time as well. How you initialize
it depends on which memory manager you're using, TTM or GEM.
</para>
<sect3>
@@ -399,7 +399,7 @@
aperture space for graphics devices. TTM supports both UMA devices
and devices with dedicated video RAM (VRAM), i.e. most discrete
graphics devices. If your device has dedicated RAM, supporting
- TTM is desireable. TTM also integrates tightly with your
+ TTM is desirable. TTM also integrates tightly with your
driver specific buffer execution function. See the radeon
driver for examples.
</para>
@@ -443,7 +443,7 @@
likely eventually calling ttm_bo_global_init and
ttm_bo_global_release, respectively. Also like the previous
object, ttm_global_item_ref is used to create an initial reference
- count for the TTM, which will call your initalization function.
+ count for the TTM, which will call your initialization function.
</para>
</sect3>
<sect3>
@@ -557,7 +557,7 @@
CRT connector and encoder combination is created. A device
specific i2c bus is also created, for fetching EDID data and
performing monitor detection. Once the process is complete,
- the new connector is regsitered with sysfs, to make its
+ the new connector is registered with sysfs, to make its
properties available to applications.
</para>
<sect4>
@@ -581,12 +581,12 @@
<para>
For each encoder, CRTC and connector, several functions must
be provided, depending on the object type. Encoder objects
- need should provide a DPMS (basically on/off) function, mode fixup
+ need to provide a DPMS (basically on/off) function, mode fixup
(for converting requested modes into native hardware timings),
and prepare, set and commit functions for use by the core DRM
helper functions. Connector helpers need to provide mode fetch and
validity functions as well as an encoder matching function for
- returing an ideal encoder for a given connector. The core
+ returning an ideal encoder for a given connector. The core
connector functions include a DPMS callback, (deprecated)
save/restore routines, detection, mode probing, property handling,
and cleanup functions.
diff --git a/Documentation/DocBook/v4l/v4l2.xml b/Documentation/DocBook/v4l/v4l2.xml
index 9737243..7c3c098 100644
--- a/Documentation/DocBook/v4l/v4l2.xml
+++ b/Documentation/DocBook/v4l/v4l2.xml
@@ -58,7 +58,7 @@
</contrib>
<affiliation>
<address>
- <email>awalls@radix.net</email>
+ <email>awalls@md.metrocast.net</email>
</address>
</affiliation>
</author>
diff --git a/Documentation/DocBook/v4l/vidioc-query-dv-preset.xml b/Documentation/DocBook/v4l/vidioc-query-dv-preset.xml
index 87e4f0f..402229e 100644
--- a/Documentation/DocBook/v4l/vidioc-query-dv-preset.xml
+++ b/Documentation/DocBook/v4l/vidioc-query-dv-preset.xml
@@ -53,8 +53,10 @@
automatically, similar to sensing the video standard. To do so, applications
call <constant> VIDIOC_QUERY_DV_PRESET</constant> with a pointer to a
&v4l2-dv-preset; type. Once the hardware detects a preset, that preset is
-returned in the preset field of &v4l2-dv-preset;. When detection is not
-possible or fails, the value V4L2_DV_INVALID is returned.</para>
+returned in the preset field of &v4l2-dv-preset;. If the preset could not be
+detected because there was no signal, or the signal was unreliable, or the
+signal did not map to a supported preset, then the value V4L2_DV_INVALID is
+returned.</para>
</refsect1>
<refsect1>
diff --git a/Documentation/edac.txt b/Documentation/edac.txt
index 79c5332..0b875e8 100644
--- a/Documentation/edac.txt
+++ b/Documentation/edac.txt
@@ -6,6 +6,8 @@
7 Dec 2005
17 Jul 2007 Updated
+(c) Mauro Carvalho Chehab <mchehab@redhat.com>
+05 Aug 2009 Nehalem interface
EDAC is maintained and written by:
@@ -717,3 +719,153 @@
The 'test_device_edac' sample driver is located at the
bluesmoke.sourceforge.net project site for EDAC.
+=======================================================================
+NEHALEM USAGE OF EDAC APIs
+
+This chapter documents some EXPERIMENTAL mappings for EDAC API to handle
+Nehalem EDAC driver. They will likely be changed on future versions
+of the driver.
+
+Due to the way Nehalem exports Memory Controller data, some adjustments
+were done at i7core_edac driver. This chapter will cover those differences
+
+1) On Nehalem, there are one Memory Controller per Quick Patch Interconnect
+ (QPI). At the driver, the term "socket" means one QPI. This is
+ associated with a physical CPU socket.
+
+ Each MC have 3 physical read channels, 3 physical write channels and
+ 3 logic channels. The driver currenty sees it as just 3 channels.
+ Each channel can have up to 3 DIMMs.
+
+ The minimum known unity is DIMMs. There are no information about csrows.
+ As EDAC API maps the minimum unity is csrows, the driver sequencially
+ maps channel/dimm into different csrows.
+
+ For example, suposing the following layout:
+ Ch0 phy rd0, wr0 (0x063f4031): 2 ranks, UDIMMs
+ dimm 0 1024 Mb offset: 0, bank: 8, rank: 1, row: 0x4000, col: 0x400
+ dimm 1 1024 Mb offset: 4, bank: 8, rank: 1, row: 0x4000, col: 0x400
+ Ch1 phy rd1, wr1 (0x063f4031): 2 ranks, UDIMMs
+ dimm 0 1024 Mb offset: 0, bank: 8, rank: 1, row: 0x4000, col: 0x400
+ Ch2 phy rd3, wr3 (0x063f4031): 2 ranks, UDIMMs
+ dimm 0 1024 Mb offset: 0, bank: 8, rank: 1, row: 0x4000, col: 0x400
+ The driver will map it as:
+ csrow0: channel 0, dimm0
+ csrow1: channel 0, dimm1
+ csrow2: channel 1, dimm0
+ csrow3: channel 2, dimm0
+
+exports one
+ DIMM per csrow.
+
+ Each QPI is exported as a different memory controller.
+
+2) Nehalem MC has the hability to generate errors. The driver implements this
+ functionality via some error injection nodes:
+
+ For injecting a memory error, there are some sysfs nodes, under
+ /sys/devices/system/edac/mc/mc?/:
+
+ inject_addrmatch/*:
+ Controls the error injection mask register. It is possible to specify
+ several characteristics of the address to match an error code:
+ dimm = the affected dimm. Numbers are relative to a channel;
+ rank = the memory rank;
+ channel = the channel that will generate an error;
+ bank = the affected bank;
+ page = the page address;
+ column (or col) = the address column.
+ each of the above values can be set to "any" to match any valid value.
+
+ At driver init, all values are set to any.
+
+ For example, to generate an error at rank 1 of dimm 2, for any channel,
+ any bank, any page, any column:
+ echo 2 >/sys/devices/system/edac/mc/mc0/inject_addrmatch/dimm
+ echo 1 >/sys/devices/system/edac/mc/mc0/inject_addrmatch/rank
+
+ To return to the default behaviour of matching any, you can do:
+ echo any >/sys/devices/system/edac/mc/mc0/inject_addrmatch/dimm
+ echo any >/sys/devices/system/edac/mc/mc0/inject_addrmatch/rank
+
+ inject_eccmask:
+ specifies what bits will have troubles,
+
+ inject_section:
+ specifies what ECC cache section will get the error:
+ 3 for both
+ 2 for the highest
+ 1 for the lowest
+
+ inject_type:
+ specifies the type of error, being a combination of the following bits:
+ bit 0 - repeat
+ bit 1 - ecc
+ bit 2 - parity
+
+ inject_enable starts the error generation when something different
+ than 0 is written.
+
+ All inject vars can be read. root permission is needed for write.
+
+ Datasheet states that the error will only be generated after a write on an
+ address that matches inject_addrmatch. It seems, however, that reading will
+ also produce an error.
+
+ For example, the following code will generate an error for any write access
+ at socket 0, on any DIMM/address on channel 2:
+
+ echo 2 >/sys/devices/system/edac/mc/mc0/inject_addrmatch/channel
+ echo 2 >/sys/devices/system/edac/mc/mc0/inject_type
+ echo 64 >/sys/devices/system/edac/mc/mc0/inject_eccmask
+ echo 3 >/sys/devices/system/edac/mc/mc0/inject_section
+ echo 1 >/sys/devices/system/edac/mc/mc0/inject_enable
+ dd if=/dev/mem of=/dev/null seek=16k bs=4k count=1 >& /dev/null
+
+ For socket 1, it is needed to replace "mc0" by "mc1" at the above
+ commands.
+
+ The generated error message will look like:
+
+ EDAC MC0: UE row 0, channel-a= 0 channel-b= 0 labels "-": NON_FATAL (addr = 0x0075b980, socket=0, Dimm=0, Channel=2, syndrome=0x00000040, count=1, Err=8c0000400001009f:4000080482 (read error: read ECC error))
+
+3) Nehalem specific Corrected Error memory counters
+
+ Nehalem have some registers to count memory errors. The driver uses those
+ registers to report Corrected Errors on devices with Registered Dimms.
+
+ However, those counters don't work with Unregistered Dimms. As the chipset
+ offers some counters that also work with UDIMMS (but with a worse level of
+ granularity than the default ones), the driver exposes those registers for
+ UDIMM memories.
+
+ They can be read by looking at the contents of all_channel_counts/
+
+ $ for i in /sys/devices/system/edac/mc/mc0/all_channel_counts/*; do echo $i; cat $i; done
+ /sys/devices/system/edac/mc/mc0/all_channel_counts/udimm0
+ 0
+ /sys/devices/system/edac/mc/mc0/all_channel_counts/udimm1
+ 0
+ /sys/devices/system/edac/mc/mc0/all_channel_counts/udimm2
+ 0
+
+ What happens here is that errors on different csrows, but at the same
+ dimm number will increment the same counter.
+ So, in this memory mapping:
+ csrow0: channel 0, dimm0
+ csrow1: channel 0, dimm1
+ csrow2: channel 1, dimm0
+ csrow3: channel 2, dimm0
+ The hardware will increment udimm0 for an error at the first dimm at either
+ csrow0, csrow2 or csrow3;
+ The hardware will increment udimm1 for an error at the second dimm at either
+ csrow0, csrow2 or csrow3;
+ The hardware will increment udimm2 for an error at the third dimm at either
+ csrow0, csrow2 or csrow3;
+
+4) Standard error counters
+
+ The standard error counters are generated when an mcelog error is received
+ by the driver. Since, with udimm, this is counted by software, it is
+ possible that some errors could be lost. With rdimm's, they displays the
+ contents of the registers
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 672be01..c268783 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -578,15 +578,6 @@
----------------------------
-What: "acpi=ht" boot option
-When: 2.6.35
-Why: Useful in 2003, implementation is a hack.
- Generally invoked by accident today.
- Seen as doing more harm than good.
-Who: Len Brown <len.brown@intel.com>
-
-----------------------------
-
What: iwlwifi 50XX module parameters
When: 2.6.40
Why: The "..50" modules parameters were used to configure 5000 series and
diff --git a/Documentation/filesystems/xfs-delayed-logging-design.txt b/Documentation/filesystems/xfs-delayed-logging-design.txt
index d8119e9..96d0df2 100644
--- a/Documentation/filesystems/xfs-delayed-logging-design.txt
+++ b/Documentation/filesystems/xfs-delayed-logging-design.txt
@@ -794,11 +794,6 @@
Roadmap:
-2.6.35 Inclusion in mainline as an experimental mount option
- => approximately 2-3 months to merge window
- => needs to be in xfs-dev tree in 4-6 weeks
- => code is nearing readiness for review
-
2.6.37 Remove experimental tag from mount option
=> should be roughly 6 months after initial merge
=> enough time to:
diff --git a/Documentation/i2c/busses/i2c-ali1535 b/Documentation/i2c/busses/i2c-ali1535
index 0db3b4c..acbc65a 100644
--- a/Documentation/i2c/busses/i2c-ali1535
+++ b/Documentation/i2c/busses/i2c-ali1535
@@ -6,12 +6,12 @@
http://www.ali.com.tw/eng/support/datasheet_request.php
Authors:
- Frodo Looijaard <frodol@dds.nl>,
+ Frodo Looijaard <frodol@dds.nl>,
Philip Edelbrock <phil@netroedge.com>,
Mark D. Studebaker <mdsxyz123@yahoo.com>,
Dan Eaton <dan.eaton@rocketlogix.com>,
Stephen Rousset<stephen.rousset@rocketlogix.com>
-
+
Description
-----------
diff --git a/Documentation/i2c/busses/i2c-ali1563 b/Documentation/i2c/busses/i2c-ali1563
index 99ad4b9..5469169 100644
--- a/Documentation/i2c/busses/i2c-ali1563
+++ b/Documentation/i2c/busses/i2c-ali1563
@@ -18,7 +18,7 @@
The M1563 southbridge is deceptively similar to the M1533, with a few
notable exceptions. One of those happens to be the fact they upgraded the
i2c core to be SMBus 2.0 compliant, and happens to be almost identical to
-the i2c controller found in the Intel 801 south bridges.
+the i2c controller found in the Intel 801 south bridges.
Features
--------
diff --git a/Documentation/i2c/busses/i2c-ali15x3 b/Documentation/i2c/busses/i2c-ali15x3
index ff28d38..600da90 100644
--- a/Documentation/i2c/busses/i2c-ali15x3
+++ b/Documentation/i2c/busses/i2c-ali15x3
@@ -6,8 +6,8 @@
http://www.ali.com.tw/eng/support/datasheet_request.php
Authors:
- Frodo Looijaard <frodol@dds.nl>,
- Philip Edelbrock <phil@netroedge.com>,
+ Frodo Looijaard <frodol@dds.nl>,
+ Philip Edelbrock <phil@netroedge.com>,
Mark D. Studebaker <mdsxyz123@yahoo.com>
Module Parameters
@@ -40,10 +40,10 @@
The M1543C is a South bridge for desktop systems.
The M1541 is a South bridge for portable systems.
They are part of the following ALI chipsets:
-
- * "Aladdin Pro 2" includes the M1621 Slot 1 North bridge with AGP and
+
+ * "Aladdin Pro 2" includes the M1621 Slot 1 North bridge with AGP and
100MHz CPU Front Side bus
- * "Aladdin V" includes the M1541 Socket 7 North bridge with AGP and 100MHz
+ * "Aladdin V" includes the M1541 Socket 7 North bridge with AGP and 100MHz
CPU Front Side bus
Some Aladdin V motherboards:
Asus P5A
@@ -77,7 +77,7 @@
** then run lspci.
** If you see the 1533 and 5229 devices but NOT the 7101 device,
** then you must enable ACPI, the PMU, SMB, or something similar
-** in the BIOS.
+** in the BIOS.
** The driver won't work if it can't find the M7101 device.
The SMB controller is part of the M7101 device, which is an ACPI-compliant
@@ -87,8 +87,8 @@
just enable the SMB alone. The SMB and the ACPI have separate I/O spaces.
We make sure that the SMB is enabled. We leave the ACPI alone.
-Features
---------
+Features
+--------
This driver controls the SMB Host only. The SMB Slave
controller on the M15X3 is not enabled. This driver does not use
diff --git a/Documentation/i2c/busses/i2c-pca-isa b/Documentation/i2c/busses/i2c-pca-isa
index 6fc8f4c..b044e52 100644
--- a/Documentation/i2c/busses/i2c-pca-isa
+++ b/Documentation/i2c/busses/i2c-pca-isa
@@ -1,10 +1,10 @@
Kernel driver i2c-pca-isa
Supported adapters:
-This driver supports ISA boards using the Philips PCA 9564
-Parallel bus to I2C bus controller
+This driver supports ISA boards using the Philips PCA 9564
+Parallel bus to I2C bus controller
-Author: Ian Campbell <icampbell@arcom.com>, Arcom Control Systems
+Author: Ian Campbell <icampbell@arcom.com>, Arcom Control Systems
Module Parameters
-----------------
@@ -12,12 +12,12 @@
* base int
I/O base address
* irq int
- IRQ interrupt
-* clock int
+ IRQ interrupt
+* clock int
Clock rate as described in table 1 of PCA9564 datasheet
Description
-----------
-This driver supports ISA boards using the Philips PCA 9564
-Parallel bus to I2C bus controller
+This driver supports ISA boards using the Philips PCA 9564
+Parallel bus to I2C bus controller
diff --git a/Documentation/i2c/busses/i2c-sis5595 b/Documentation/i2c/busses/i2c-sis5595
index cc47db7..ecd21fb 100644
--- a/Documentation/i2c/busses/i2c-sis5595
+++ b/Documentation/i2c/busses/i2c-sis5595
@@ -1,41 +1,41 @@
Kernel driver i2c-sis5595
-Authors:
+Authors:
Frodo Looijaard <frodol@dds.nl>,
Mark D. Studebaker <mdsxyz123@yahoo.com>,
- Philip Edelbrock <phil@netroedge.com>
+ Philip Edelbrock <phil@netroedge.com>
Supported adapters:
* Silicon Integrated Systems Corp. SiS5595 Southbridge
Datasheet: Publicly available at the Silicon Integrated Systems Corp. site.
-Note: all have mfr. ID 0x1039.
+Note: all have mfr. ID 0x1039.
- SUPPORTED PCI ID
- 5595 0008
-
- Note: these chips contain a 0008 device which is incompatible with the
- 5595. We recognize these by the presence of the listed
- "blacklist" PCI ID and refuse to load.
-
- NOT SUPPORTED PCI ID BLACKLIST PCI ID
- 540 0008 0540
- 550 0008 0550
- 5513 0008 5511
- 5581 0008 5597
- 5582 0008 5597
- 5597 0008 5597
- 5598 0008 5597/5598
- 630 0008 0630
- 645 0008 0645
- 646 0008 0646
- 648 0008 0648
- 650 0008 0650
- 651 0008 0651
- 730 0008 0730
- 735 0008 0735
- 745 0008 0745
- 746 0008 0746
+ SUPPORTED PCI ID
+ 5595 0008
+
+ Note: these chips contain a 0008 device which is incompatible with the
+ 5595. We recognize these by the presence of the listed
+ "blacklist" PCI ID and refuse to load.
+
+ NOT SUPPORTED PCI ID BLACKLIST PCI ID
+ 540 0008 0540
+ 550 0008 0550
+ 5513 0008 5511
+ 5581 0008 5597
+ 5582 0008 5597
+ 5597 0008 5597
+ 5598 0008 5597/5598
+ 630 0008 0630
+ 645 0008 0645
+ 646 0008 0646
+ 648 0008 0648
+ 650 0008 0650
+ 651 0008 0651
+ 730 0008 0730
+ 735 0008 0735
+ 745 0008 0745
+ 746 0008 0746
Module Parameters
-----------------
diff --git a/Documentation/i2c/busses/i2c-sis630 b/Documentation/i2c/busses/i2c-sis630
index 9aca688..629ea2c3 100644
--- a/Documentation/i2c/busses/i2c-sis630
+++ b/Documentation/i2c/busses/i2c-sis630
@@ -14,9 +14,9 @@
* force = [1|0] Forcibly enable the SIS630. DANGEROUS!
This can be interesting for chipsets not named
above to check if it works for you chipset, but DANGEROUS!
-
-* high_clock = [1|0] Forcibly set Host Master Clock to 56KHz (default,
- what your BIOS use). DANGEROUS! This should be a bit
+
+* high_clock = [1|0] Forcibly set Host Master Clock to 56KHz (default,
+ what your BIOS use). DANGEROUS! This should be a bit
faster, but freeze some systems (i.e. my Laptop).
@@ -44,6 +44,6 @@
- testing SiS730 support
Mark M. Hoffman <mhoffman@lightlink.com>
- bug fixes
-
+
To anyone else which I forgot here ;), thanks!
diff --git a/Documentation/i2c/ten-bit-addresses b/Documentation/i2c/ten-bit-addresses
index 200074f..e989070 100644
--- a/Documentation/i2c/ten-bit-addresses
+++ b/Documentation/i2c/ten-bit-addresses
@@ -1,17 +1,17 @@
-The I2C protocol knows about two kinds of device addresses: normal 7 bit
+The I2C protocol knows about two kinds of device addresses: normal 7 bit
addresses, and an extended set of 10 bit addresses. The sets of addresses
do not intersect: the 7 bit address 0x10 is not the same as the 10 bit
address 0x10 (though a single device could respond to both of them). You
select a 10 bit address by adding an extra byte after the address
byte:
- S Addr7 Rd/Wr ....
+ S Addr7 Rd/Wr ....
becomes
S 11110 Addr10 Rd/Wr
S is the start bit, Rd/Wr the read/write bit, and if you count the number
of bits, you will see the there are 8 after the S bit for 7 bit addresses,
and 16 after the S bit for 10 bit addresses.
-WARNING! The current 10 bit address support is EXPERIMENTAL. There are
+WARNING! The current 10 bit address support is EXPERIMENTAL. There are
several places in the code that will cause SEVERE PROBLEMS with 10 bit
addresses, even though there is some basic handling and hooks. Also,
almost no supported adapter handles the 10 bit addresses correctly.
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 1808f11..82d6aeb 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -2048,7 +2048,9 @@
WARNING: Forcing ASPM on may cause system lockups.
pcie_pme= [PCIE,PM] Native PCIe PME signaling options:
- off Do not use native PCIe PME signaling.
+ Format: {auto|force}[,nomsi]
+ auto Use native PCIe PME signaling if the BIOS allows the
+ kernel to control PCIe config registers of root ports.
force Use native PCIe PME signaling even if the BIOS refuses
to allow the kernel to control the relevant PCIe config
registers.
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134
index 070f257..1387a69 100644
--- a/Documentation/video4linux/CARDLIST.saa7134
+++ b/Documentation/video4linux/CARDLIST.saa7134
@@ -176,5 +176,6 @@
175 -> Leadtek Winfast DTV1000S [107d:6655]
176 -> Beholder BeholdTV 505 RDS [0000:5051]
177 -> Hawell HW-404M7
-179 -> Beholder BeholdTV H7 [5ace:7190]
-180 -> Beholder BeholdTV A7 [5ace:7090]
+178 -> Beholder BeholdTV H7 [5ace:7190]
+179 -> Beholder BeholdTV A7 [5ace:7090]
+180 -> Avermedia M733A [1461:4155,1461:4255]
diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt
index 8f3f5d3..f13eb03 100644
--- a/Documentation/video4linux/gspca.txt
+++ b/Documentation/video4linux/gspca.txt
@@ -290,6 +290,7 @@
sonixj 0c45:6040 Speed NVC 350K
sonixj 0c45:607c Sonix sn9c102p Hv7131R
sonixj 0c45:60c0 Sangha Sn535
+sonixj 0c45:60ce USB-PC-Camera-168 (TALK-5067)
sonixj 0c45:60ec SN9C105+MO4000
sonixj 0c45:60fb Surfer NoName
sonixj 0c45:60fc LG-LIC300
diff --git a/Documentation/watchdog/watchdog-parameters.txt b/Documentation/watchdog/watchdog-parameters.txt
index 41c95cc..17ddd82 100644
--- a/Documentation/watchdog/watchdog-parameters.txt
+++ b/Documentation/watchdog/watchdog-parameters.txt
@@ -125,6 +125,11 @@
nowayout: Watchdog cannot be stopped once started
(default=kernel config parameter)
-------------------------------------------------
+imx2_wdt:
+timeout: Watchdog timeout in seconds (default 60 s)
+nowayout: Watchdog cannot be stopped once started
+ (default=kernel config parameter)
+-------------------------------------------------
indydog:
nowayout: Watchdog cannot be stopped once started
(default=kernel config parameter)
diff --git a/MAINTAINERS b/MAINTAINERS
index 2652ebc5..7642365 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -896,11 +896,13 @@
ARM/SAMSUNG ARM ARCHITECTURES
M: Ben Dooks <ben-linux@fluff.org>
+M: Kukjin Kim <kgene.kim@samsung.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
W: http://www.fluff.org/ben/linux/
S: Maintained
-F: arch/arm/plat-s3c/
+F: arch/arm/plat-samsung/
F: arch/arm/plat-s3c24xx/
+F: arch/arm/plat-s5p/
ARM/S3C2410 ARM ARCHITECTURE
M: Ben Dooks <ben-linux@fluff.org>
@@ -1148,7 +1150,7 @@
F: drivers/mmc/host/atmel-mci-regs.h
ATMEL AT91 / AT32 SERIAL DRIVER
-M: Haavard Skinnemoen <hskinnemoen@atmel.com>
+M: Nicolas Ferre <nicolas.ferre@atmel.com>
S: Supported
F: drivers/serial/atmel_serial.c
@@ -1160,18 +1162,18 @@
F: include/video/atmel_lcdc.h
ATMEL MACB ETHERNET DRIVER
-M: Haavard Skinnemoen <hskinnemoen@atmel.com>
+M: Nicolas Ferre <nicolas.ferre@atmel.com>
S: Supported
F: drivers/net/macb.*
ATMEL SPI DRIVER
-M: Haavard Skinnemoen <hskinnemoen@atmel.com>
+M: Nicolas Ferre <nicolas.ferre@atmel.com>
S: Supported
F: drivers/spi/atmel_spi.*
ATMEL USBA UDC DRIVER
-M: Haavard Skinnemoen <hskinnemoen@atmel.com>
-L: kernel@avr32linux.org
+M: Nicolas Ferre <nicolas.ferre@atmel.com>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
W: http://avr32linux.org/twiki/bin/view/Main/AtmelUsbDeviceDriver
S: Supported
F: drivers/usb/gadget/atmel_usba_udc.*
@@ -1581,7 +1583,7 @@
COMMON INTERNET FILE SYSTEM (CIFS)
M: Steve French <sfrench@samba.org>
-L: linux-cifs-client@lists.samba.org (moderated for non-subscribers)
+L: linux-cifs@vger.kernel.org
L: samba-technical@lists.samba.org (moderated for non-subscribers)
W: http://linux-cifs.samba.org/
Q: http://patchwork.ozlabs.org/project/linux-cifs-client/list/
@@ -1731,7 +1733,7 @@
F: sound/pci/cs5535audio/
CX18 VIDEO4LINUX DRIVER
-M: Andy Walls <awalls@radix.net>
+M: Andy Walls <awalls@md.metrocast.net>
L: ivtv-devel@ivtvdriver.org (moderated for non-subscribers)
L: linux-media@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
@@ -2887,6 +2889,13 @@
S: Maintained
F: drivers/input/
+INPUT MULTITOUCH (MT) PROTOCOL
+M: Henrik Rydberg <rydberg@euromail.se>
+L: linux-input@vger.kernel.org
+S: Maintained
+F: Documentation/input/multi-touch-protocol.txt
+K: \b(ABS|SYN)_MT_
+
INTEL IDLE DRIVER
M: Len Brown <lenb@kernel.org>
L: linux-pm@lists.linux-foundation.org
@@ -2978,22 +2987,14 @@
F: drivers/net/ixgbe/
INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT
-M: Zhu Yi <yi.zhu@intel.com>
-M: Reinette Chatre <reinette.chatre@intel.com>
-M: Intel Linux Wireless <ilw@linux.intel.com>
L: linux-wireless@vger.kernel.org
-W: http://ipw2100.sourceforge.net
-S: Odd Fixes
+S: Orphan
F: Documentation/networking/README.ipw2100
F: drivers/net/wireless/ipw2x00/ipw2100.*
INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT
-M: Zhu Yi <yi.zhu@intel.com>
-M: Reinette Chatre <reinette.chatre@intel.com>
-M: Intel Linux Wireless <ilw@linux.intel.com>
L: linux-wireless@vger.kernel.org
-W: http://ipw2200.sourceforge.net
-S: Odd Fixes
+S: Orphan
F: Documentation/networking/README.ipw2200
F: drivers/net/wireless/ipw2x00/ipw2200.*
@@ -3019,8 +3020,8 @@
F: include/linux/wimax/i2400m.h
INTEL WIRELESS WIFI LINK (iwlwifi)
-M: Zhu Yi <yi.zhu@intel.com>
M: Reinette Chatre <reinette.chatre@intel.com>
+M: Wey-Yi Guy <wey-yi.w.guy@intel.com>
M: Intel Linux Wireless <ilw@linux.intel.com>
L: linux-wireless@vger.kernel.org
W: http://intellinuxwireless.org
@@ -3030,7 +3031,6 @@
INTEL WIRELESS MULTICOMM 3200 WIFI (iwmc3200wifi)
M: Samuel Ortiz <samuel.ortiz@intel.com>
-M: Zhu Yi <yi.zhu@intel.com>
M: Intel Linux Wireless <ilw@linux.intel.com>
L: linux-wireless@vger.kernel.org
S: Supported
@@ -3165,7 +3165,7 @@
F: drivers/hwmon/it87.c
IVTV VIDEO4LINUX DRIVER
-M: Andy Walls <awalls@radix.net>
+M: Andy Walls <awalls@md.metrocast.net>
L: ivtv-devel@ivtvdriver.org (moderated for non-subscribers)
L: linux-media@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
@@ -3382,7 +3382,7 @@
M: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
M: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
M: "David S. Miller" <davem@davemloft.net>
-M: Masami Hiramatsu <mhiramat@redhat.com>
+M: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
S: Maintained
F: Documentation/kprobes.txt
F: include/linux/kprobes.h
@@ -3503,9 +3503,8 @@
LINUX FOR POWERPC PA SEMI PWRFICIENT
M: Olof Johansson <olof@lixom.net>
-W: http://www.pasemi.com/
L: linuxppc-dev@ozlabs.org
-S: Supported
+S: Maintained
F: arch/powerpc/platforms/pasemi/
F: drivers/*/*pasemi*
F: drivers/*/*/*pasemi*
@@ -4216,6 +4215,7 @@
M: Grant Likely <grant.likely@secretlab.ca>
L: devicetree-discuss@lists.ozlabs.org
W: http://fdt.secretlab.ca
+T: git git://git.secretlab.ca/git/linux-2.6.git
S: Maintained
F: drivers/of
F: include/linux/of*.h
@@ -4630,6 +4630,12 @@
L: rtc-linux@googlegroups.com
S: Maintained
+QLOGIC QLA1280 SCSI DRIVER
+M: Michael Reed <mdr@sgi.com>
+L: linux-scsi@vger.kernel.org
+S: Maintained
+F: drivers/scsi/qla1280.[ch]
+
QLOGIC QLA2XXX FC-SCSI DRIVER
M: Andrew Vasquez <andrew.vasquez@qlogic.com>
M: linux-driver@qlogic.com
@@ -5388,6 +5394,7 @@
M: Grant Likely <grant.likely@secretlab.ca>
L: spi-devel-general@lists.sourceforge.net
Q: http://patchwork.kernel.org/project/spi-devel-general/list/
+T: git git://git.secretlab.ca/git/linux-2.6.git
S: Maintained
F: Documentation/spi/
F: drivers/spi/
diff --git a/Makefile b/Makefile
index efdc3d0..662e820 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 35
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc3
NAME = Sheep on Meth
# *DOCUMENTATION*
@@ -944,7 +944,7 @@
localver-extra = $(scm-identifier)
else
ifneq ($(scm-identifier),)
- ifeq ($(LOCALVERSION),)
+ ifeq ("$(origin LOCALVERSION)", "undefined")
localver-extra = +
endif
endif
@@ -1095,7 +1095,7 @@
# using awk while concatenating to the final file.
PHONY += modules
-modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux)
+modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin
$(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order
@$(kecho) ' Building modules, stage 2.';
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
@@ -1117,7 +1117,7 @@
modules_install: _modinst_ _modinst_post
PHONY += _modinst_
-_modinst_: modules.builtin
+_modinst_:
@if [ -z "`$(DEPMOD) -V 2>/dev/null | grep module-init-tools`" ]; then \
echo "Warning: you may need to install module-init-tools"; \
echo "See http://www.codemonkey.org.uk/docs/post-halloween-2.6.txt";\
diff --git a/arch/alpha/include/asm/bitops.h b/arch/alpha/include/asm/bitops.h
index 1dce24b..adfab8a 100644
--- a/arch/alpha/include/asm/bitops.h
+++ b/arch/alpha/include/asm/bitops.h
@@ -410,7 +410,7 @@
return __kernel_ctpop(w);
}
-static inline unsigned int __arch_weight32(unsigned int w)
+static inline unsigned int __arch_hweight32(unsigned int w)
{
return __arch_hweight64(w);
}
diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile
index 7739a62..5a62fb4 100644
--- a/arch/alpha/kernel/Makefile
+++ b/arch/alpha/kernel/Makefile
@@ -35,7 +35,7 @@
obj-y += irq_pyxis.o irq_i8259.o irq_srm.o
obj-y += err_ev6.o
-obj-y += es1888.o smc37c669.o smc37c93x.o ns87312.o gct.o
+obj-y += es1888.o smc37c669.o smc37c93x.o pc873xx.o gct.o
obj-y += srmcons.o
else
@@ -63,11 +63,11 @@
# Board support
obj-$(CONFIG_ALPHA_ALCOR) += sys_alcor.o irq_i8259.o irq_srm.o
obj-$(CONFIG_ALPHA_CABRIOLET) += sys_cabriolet.o irq_i8259.o irq_srm.o \
- ns87312.o
+ pc873xx.o
obj-$(CONFIG_ALPHA_EB164) += sys_cabriolet.o irq_i8259.o irq_srm.o \
- ns87312.o
+ pc873xx.o
obj-$(CONFIG_ALPHA_EB66P) += sys_cabriolet.o irq_i8259.o irq_srm.o \
- ns87312.o
+ pc873xx.o
obj-$(CONFIG_ALPHA_LX164) += sys_cabriolet.o irq_i8259.o irq_srm.o \
smc37c93x.o
obj-$(CONFIG_ALPHA_PC164) += sys_cabriolet.o irq_i8259.o irq_srm.o \
@@ -90,14 +90,14 @@
obj-$(CONFIG_ALPHA_RX164) += sys_rx164.o irq_i8259.o
obj-$(CONFIG_ALPHA_SABLE) += sys_sable.o
obj-$(CONFIG_ALPHA_LYNX) += sys_sable.o
-obj-$(CONFIG_ALPHA_BOOK1) += sys_sio.o irq_i8259.o irq_srm.o ns87312.o
-obj-$(CONFIG_ALPHA_AVANTI) += sys_sio.o irq_i8259.o irq_srm.o ns87312.o
-obj-$(CONFIG_ALPHA_NONAME) += sys_sio.o irq_i8259.o irq_srm.o ns87312.o
-obj-$(CONFIG_ALPHA_P2K) += sys_sio.o irq_i8259.o irq_srm.o ns87312.o
-obj-$(CONFIG_ALPHA_XL) += sys_sio.o irq_i8259.o irq_srm.o ns87312.o
+obj-$(CONFIG_ALPHA_BOOK1) += sys_sio.o irq_i8259.o irq_srm.o pc873xx.o
+obj-$(CONFIG_ALPHA_AVANTI) += sys_sio.o irq_i8259.o irq_srm.o pc873xx.o
+obj-$(CONFIG_ALPHA_NONAME) += sys_sio.o irq_i8259.o irq_srm.o pc873xx.o
+obj-$(CONFIG_ALPHA_P2K) += sys_sio.o irq_i8259.o irq_srm.o pc873xx.o
+obj-$(CONFIG_ALPHA_XL) += sys_sio.o irq_i8259.o irq_srm.o pc873xx.o
obj-$(CONFIG_ALPHA_SX164) += sys_sx164.o irq_pyxis.o irq_i8259.o \
irq_srm.o smc37c669.o
-obj-$(CONFIG_ALPHA_TAKARA) += sys_takara.o irq_i8259.o ns87312.o
+obj-$(CONFIG_ALPHA_TAKARA) += sys_takara.o irq_i8259.o pc873xx.o
obj-$(CONFIG_ALPHA_WILDFIRE) += sys_wildfire.o irq_i8259.o
# Error support
diff --git a/arch/alpha/kernel/ns87312.c b/arch/alpha/kernel/ns87312.c
deleted file mode 100644
index 342b56d..0000000
--- a/arch/alpha/kernel/ns87312.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * linux/arch/alpha/kernel/ns87312.c
- */
-
-#include <linux/init.h>
-#include <asm/io.h>
-#include "proto.h"
-
-
-/*
- * The SRM console *disables* the IDE interface, this code ensures it's
- * enabled.
- *
- * This code bangs on a control register of the 87312 Super I/O chip
- * that implements parallel port/serial ports/IDE/FDI. Depending on
- * the motherboard, the Super I/O chip can be configured through a
- * pair of registers that are located either at I/O ports 0x26e/0x26f
- * or 0x398/0x399. Unfortunately, autodetecting which base address is
- * in use works only once (right after a reset). The Super I/O chip
- * has the additional quirk that configuration register data must be
- * written twice (I believe this is a safety feature to prevent
- * accidental modification---fun, isn't it?).
- */
-
-void __init
-ns87312_enable_ide(long ide_base)
-{
- int data;
- unsigned long flags;
-
- local_irq_save(flags);
- outb(0, ide_base); /* set the index register for reg #0 */
- data = inb(ide_base+1); /* read the current contents */
- outb(0, ide_base); /* set the index register for reg #0 */
- outb(data | 0x40, ide_base+1); /* turn on IDE */
- outb(data | 0x40, ide_base+1); /* turn on IDE, really! */
- local_irq_restore(flags);
-}
diff --git a/arch/alpha/kernel/pc873xx.c b/arch/alpha/kernel/pc873xx.c
new file mode 100644
index 0000000..27dcbff
--- /dev/null
+++ b/arch/alpha/kernel/pc873xx.c
@@ -0,0 +1,88 @@
+#include <linux/ioport.h>
+#include <asm/io.h>
+
+#include "pc873xx.h"
+
+static unsigned pc873xx_probelist[] = {0x398, 0x26e, 0};
+
+static char *pc873xx_names[] = {
+ "PC87303", "PC87306", "PC87312", "PC87332", "PC87334"
+};
+
+static unsigned int base, model;
+
+
+unsigned int __init pc873xx_get_base()
+{
+ return base;
+}
+
+char *__init pc873xx_get_model()
+{
+ return pc873xx_names[model];
+}
+
+static unsigned char __init pc873xx_read(unsigned int base, int reg)
+{
+ outb(reg, base);
+ return inb(base + 1);
+}
+
+static void __init pc873xx_write(unsigned int base, int reg, unsigned char data)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ outb(reg, base);
+ outb(data, base + 1);
+ outb(data, base + 1); /* Must be written twice */
+ local_irq_restore(flags);
+}
+
+int __init pc873xx_probe(void)
+{
+ int val, index = 0;
+
+ while ((base = pc873xx_probelist[index++])) {
+
+ if (request_region(base, 2, "Super IO PC873xx") == NULL)
+ continue;
+
+ val = pc873xx_read(base, REG_SID);
+ if ((val & 0xf0) == 0x10) {
+ model = PC87332;
+ break;
+ } else if ((val & 0xf8) == 0x70) {
+ model = PC87306;
+ break;
+ } else if ((val & 0xf8) == 0x50) {
+ model = PC87334;
+ break;
+ } else if ((val & 0xf8) == 0x40) {
+ model = PC87303;
+ break;
+ }
+
+ release_region(base, 2);
+ }
+
+ return (base == 0) ? -1 : 1;
+}
+
+void __init pc873xx_enable_epp19(void)
+{
+ unsigned char data;
+
+ printk(KERN_INFO "PC873xx enabling EPP v1.9\n");
+ data = pc873xx_read(base, REG_PCR);
+ pc873xx_write(base, REG_PCR, (data & 0xFC) | 0x02);
+}
+
+void __init pc873xx_enable_ide(void)
+{
+ unsigned char data;
+
+ printk(KERN_INFO "PC873xx enabling IDE interrupt\n");
+ data = pc873xx_read(base, REG_FER);
+ pc873xx_write(base, REG_FER, data | 0x40);
+}
diff --git a/arch/alpha/kernel/pc873xx.h b/arch/alpha/kernel/pc873xx.h
new file mode 100644
index 0000000..25e1695
--- /dev/null
+++ b/arch/alpha/kernel/pc873xx.h
@@ -0,0 +1,35 @@
+
+#ifndef _PC873xx_H_
+#define _PC873xx_H_
+
+/*
+ * Control Register Values
+ */
+#define REG_FER 0x00
+#define REG_FAR 0x01
+#define REG_PTR 0x02
+#define REG_FCR 0x03
+#define REG_PCR 0x04
+#define REG_KRR 0x05
+#define REG_PMC 0x06
+#define REG_TUP 0x07
+#define REG_SID 0x08
+#define REG_ASC 0x09
+#define REG_IRC 0x0e
+
+/*
+ * Model numbers
+ */
+#define PC87303 0
+#define PC87306 1
+#define PC87312 2
+#define PC87332 3
+#define PC87334 4
+
+int pc873xx_probe(void);
+unsigned int pc873xx_get_base(void);
+char *pc873xx_get_model(void);
+void pc873xx_enable_epp19(void);
+void pc873xx_enable_ide(void);
+
+#endif
diff --git a/arch/alpha/kernel/pci-sysfs.c b/arch/alpha/kernel/pci-sysfs.c
index a5fffc8..738fc82 100644
--- a/arch/alpha/kernel/pci-sysfs.c
+++ b/arch/alpha/kernel/pci-sysfs.c
@@ -53,7 +53,6 @@
/**
* pci_mmap_resource - map a PCI resource into user memory space
- * @filp: open sysfs file
* @kobj: kobject for mapping
* @attr: struct bin_attribute for the file being mapped
* @vma: struct vm_area_struct passed into the mmap
@@ -61,7 +60,7 @@
*
* Use the bus mapping routines to map a PCI resource into userspace.
*/
-static int pci_mmap_resource(struct file *filp, struct kobject *kobj,
+static int pci_mmap_resource(struct kobject *kobj,
struct bin_attribute *attr,
struct vm_area_struct *vma, int sparse)
{
diff --git a/arch/alpha/kernel/sys_sio.c b/arch/alpha/kernel/sys_sio.c
index d4327e4..85b4aea 100644
--- a/arch/alpha/kernel/sys_sio.c
+++ b/arch/alpha/kernel/sys_sio.c
@@ -34,6 +34,7 @@
#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"
+#include "pc873xx.h"
#if defined(ALPHA_RESTORE_SRM_SETUP)
/* Save LCA configuration data as the console had it set up. */
@@ -208,7 +209,27 @@
common_init_pci();
sio_pci_route();
sio_fixup_irq_levels(sio_collect_irq_levels());
- ns87312_enable_ide(0x26e);
+
+ if (pc873xx_probe() == -1) {
+ printk(KERN_ERR "Probing for PC873xx Super IO chip failed.\n");
+ } else {
+ printk(KERN_INFO "Found %s Super IO chip at 0x%x\n",
+ pc873xx_get_model(), pc873xx_get_base());
+
+ /* Enabling things in the Super IO chip doesn't actually
+ * configure and enable things, the legacy drivers still
+ * need to do the actual configuration and enabling.
+ * This only unblocks them.
+ */
+
+#if !defined(CONFIG_ALPHA_AVANTI)
+ /* Don't bother on the Avanti family.
+ * None of them had on-board IDE.
+ */
+ pc873xx_enable_ide();
+#endif
+ pc873xx_enable_epp19();
+ }
}
static inline void __init
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index a52a27c..6f80665 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -951,8 +951,6 @@
if (!save)
return 0;
- spin_lock_irqsave(&sachip->lock, flags);
-
/*
* Ensure that the SA1111 is still here.
* FIXME: shouldn't do this here.
@@ -969,6 +967,13 @@
* First of all, wake up the chip.
*/
sa1111_wake(sachip);
+
+ /*
+ * Only lock for write ops. Also, sa1111_wake must be called with
+ * released spinlock!
+ */
+ spin_lock_irqsave(&sachip->lock, flags);
+
sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN0);
sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN1);
diff --git a/arch/arm/mach-msm/dma.c b/arch/arm/mach-msm/dma.c
index d029d1f..02cae5e 100644
--- a/arch/arm/mach-msm/dma.c
+++ b/arch/arm/mach-msm/dma.c
@@ -17,6 +17,7 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/interrupt.h>
+#include <linux/completion.h>
#include <mach/dma.h>
#define MSM_DMOV_CHANNEL_COUNT 16
diff --git a/arch/arm/mach-nomadik/clock.c b/arch/arm/mach-nomadik/clock.c
index 2c471fc..f035f41 100644
--- a/arch/arm/mach-nomadik/clock.c
+++ b/arch/arm/mach-nomadik/clock.c
@@ -32,7 +32,10 @@
}
EXPORT_SYMBOL(clk_disable);
-/* We have a fixed clock alone, for now */
+static struct clk clk_24 = {
+ .rate = 2400000,
+};
+
static struct clk clk_48 = {
.rate = 48 * 1000 * 1000,
};
@@ -50,6 +53,8 @@
}
static struct clk_lookup lookups[] = {
+ CLK(&clk_24, "mtu0"),
+ CLK(&clk_24, "mtu1"),
CLK(&clk_48, "uart0"),
CLK(&clk_48, "uart1"),
CLK(&clk_default, "gpio.0"),
@@ -59,10 +64,8 @@
CLK(&clk_default, "rng"),
};
-static int __init clk_init(void)
+int __init clk_init(void)
{
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
return 0;
}
-
-arch_initcall(clk_init);
diff --git a/arch/arm/mach-nomadik/clock.h b/arch/arm/mach-nomadik/clock.h
index 5563985..78da2e7 100644
--- a/arch/arm/mach-nomadik/clock.h
+++ b/arch/arm/mach-nomadik/clock.h
@@ -11,3 +11,5 @@
struct clk {
unsigned long rate;
};
+
+int __init clk_init(void);
diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c
index 91c3c90..ac58e3b 100644
--- a/arch/arm/mach-nomadik/cpu-8815.c
+++ b/arch/arm/mach-nomadik/cpu-8815.c
@@ -31,6 +31,8 @@
#include <asm/cacheflush.h>
#include <asm/hardware/cache-l2x0.h>
+#include "clock.h"
+
#define __MEM_4K_RESOURCE(x) \
.res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM}
@@ -143,6 +145,12 @@
/* This modified VIC cell has two register blocks, at 0 and 0x20 */
vic_init(io_p2v(NOMADIK_IC_BASE + 0x00), IRQ_VIC_START + 0, ~0, 0);
vic_init(io_p2v(NOMADIK_IC_BASE + 0x20), IRQ_VIC_START + 32, ~0, 0);
+
+ /*
+ * Init clocks here so that they are available for system timer
+ * initialization.
+ */
+ clk_init();
}
/*
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index f848ba8..a04cffd 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -538,9 +538,7 @@
printk(KERN_ERR "can't get ads7846 pen down GPIO\n");
gpio_direction_input(OMAP3_STALKER_TS_GPIO);
-
- omap_set_gpio_debounce(OMAP3_STALKER_TS_GPIO, 1);
- omap_set_gpio_debounce_time(OMAP3_STALKER_TS_GPIO, 0xa);
+ gpio_set_debounce(OMAP3_STALKER_TS_GPIO, 310);
}
static int ads7846_get_pendown_state(void)
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index 0280422..e10db7a 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -1369,6 +1369,7 @@
.ops = &clkops_omap2_dflt,
.enable_reg = OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL,
.enable_bit = OMAP4430_MODULEMODE_HWCTRL,
+ .flags = ENABLE_ON_INIT,
.clkdm_name = "l3_emif_clkdm",
.parent = &ddrphy_ck,
.recalc = &followparent_recalc,
@@ -1379,6 +1380,7 @@
.ops = &clkops_omap2_dflt,
.enable_reg = OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL,
.enable_bit = OMAP4430_MODULEMODE_HWCTRL,
+ .flags = ENABLE_ON_INIT,
.clkdm_name = "l3_emif_clkdm",
.parent = &ddrphy_ck,
.recalc = &followparent_recalc,
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 95c9a5f..b7a4133 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -409,10 +409,11 @@
return 0;
oh->_clk = omap_clk_get_by_name(oh->main_clk);
- if (!oh->_clk)
+ if (!oh->_clk) {
pr_warning("omap_hwmod: %s: cannot clk_get main_clk %s\n",
oh->name, oh->main_clk);
return -EINVAL;
+ }
if (!oh->_clk->clkdm)
pr_warning("omap_hwmod: %s: missing clockdomain for %s.\n",
@@ -444,10 +445,11 @@
continue;
c = omap_clk_get_by_name(os->clk);
- if (!c)
+ if (!c) {
pr_warning("omap_hwmod: %s: cannot clk_get interface_clk %s\n",
oh->name, os->clk);
ret = -EINVAL;
+ }
os->_clk = c;
}
@@ -470,10 +472,11 @@
for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++) {
c = omap_clk_get_by_name(oc->clk);
- if (!c)
+ if (!c) {
pr_warning("omap_hwmod: %s: cannot clk_get opt_clk %s\n",
oh->name, oc->clk);
ret = -EINVAL;
+ }
oc->_clk = c;
}
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 2e96771..b88737f 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -99,7 +99,7 @@
/* Do a readback to assure write has been done */
prm_read_mod_reg(WKUP_MOD, PM_WKEN);
- while (!(prm_read_mod_reg(WKUP_MOD, PM_WKST) &
+ while (!(prm_read_mod_reg(WKUP_MOD, PM_WKEN) &
OMAP3430_ST_IO_CHAIN_MASK)) {
timeout++;
if (timeout > 1000) {
@@ -108,7 +108,7 @@
return;
}
prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK,
- WKUP_MOD, PM_WKST);
+ WKUP_MOD, PM_WKEN);
}
}
}
diff --git a/arch/arm/mach-omap2/usb-ehci.c b/arch/arm/mach-omap2/usb-ehci.c
index c68f799..d72d1ac 100644
--- a/arch/arm/mach-omap2/usb-ehci.c
+++ b/arch/arm/mach-omap2/usb-ehci.c
@@ -20,6 +20,8 @@
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+
#include <asm/io.h>
#include <plat/mux.h>
diff --git a/arch/arm/mach-pxa/palmtc.c b/arch/arm/mach-pxa/palmtc.c
index 033b567..ce1104d 100644
--- a/arch/arm/mach-pxa/palmtc.c
+++ b/arch/arm/mach-pxa/palmtc.c
@@ -263,11 +263,11 @@
.keymap_size = ARRAY_SIZE(palmtc_matrix_keys),
};
-const static unsigned int palmtc_keypad_row_gpios[] = {
+static const unsigned int palmtc_keypad_row_gpios[] = {
0, 9, 10, 11
};
-const static unsigned int palmtc_keypad_col_gpios[] = {
+static const unsigned int palmtc_keypad_col_gpios[] = {
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 79, 80
};
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 4d2413e..c1048a3 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -818,6 +818,9 @@
.type = "max7310",
.addr = 0x18,
.platform_data = &akita_ioexp,
+ }, {
+ .type = "wm8750",
+ .addr = 0x1b,
},
};
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile
index c7bc419..4556aea 100644
--- a/arch/arm/mach-ux500/Makefile
+++ b/arch/arm/mach-ux500/Makefile
@@ -7,4 +7,5 @@
obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o
obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o
obj-$(CONFIG_MACH_U5500) += board-u5500.o
-obj-$(CONFIG_SMP) += platsmp.o headsmp.o localtimer.o
+obj-$(CONFIG_SMP) += platsmp.o headsmp.o
+obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c
index 6544855..fe84b90 100644
--- a/arch/arm/mach-ux500/clock.c
+++ b/arch/arm/mach-ux500/clock.c
@@ -16,6 +16,7 @@
#include <asm/clkdev.h>
+#include <plat/mtu.h>
#include <mach/hardware.h>
#include "clock.h"
@@ -59,6 +60,9 @@
#define PRCM_DMACLK_MGT 0x074
#define PRCM_B2R2CLK_MGT 0x078
#define PRCM_TVCLK_MGT 0x07C
+#define PRCM_TCR 0x1C8
+#define PRCM_TCR_STOPPED (1 << 16)
+#define PRCM_TCR_DOZE_MODE (1 << 17)
#define PRCM_UNIPROCLK_MGT 0x278
#define PRCM_SSPCLK_MGT 0x280
#define PRCM_RNGCLK_MGT 0x284
@@ -120,10 +124,95 @@
}
EXPORT_SYMBOL(clk_disable);
+/*
+ * The MTU has a separate, rather complex muxing setup
+ * with alternative parents (peripheral cluster or
+ * ULP or fixed 32768 Hz) depending on settings
+ */
+static unsigned long clk_mtu_get_rate(struct clk *clk)
+{
+ void __iomem *addr = __io_address(U8500_PRCMU_BASE)
+ + PRCM_TCR;
+ u32 tcr = readl(addr);
+ int mtu = (int) clk->data;
+ /*
+ * One of these is selected eventually
+ * TODO: Replace the constant with a reference
+ * to the ULP source once this is modeled.
+ */
+ unsigned long clk32k = 32768;
+ unsigned long mturate;
+ unsigned long retclk;
+
+ /* Get the rate from the parent as a default */
+ if (clk->parent_periph)
+ mturate = clk_get_rate(clk->parent_periph);
+ else if (clk->parent_cluster)
+ mturate = clk_get_rate(clk->parent_cluster);
+ else
+ /* We need to be connected SOMEWHERE */
+ BUG();
+
+ /*
+ * Are we in doze mode?
+ * In this mode the parent peripheral or the fixed 32768 Hz
+ * clock is fed into the block.
+ */
+ if (!(tcr & PRCM_TCR_DOZE_MODE)) {
+ /*
+ * Here we're using the clock input from the APE ULP
+ * clock domain. But first: are the timers stopped?
+ */
+ if (tcr & PRCM_TCR_STOPPED) {
+ clk32k = 0;
+ mturate = 0;
+ } else {
+ /* Else default mode: 0 and 2.4 MHz */
+ clk32k = 0;
+ if (cpu_is_u5500())
+ /* DB5500 divides by 8 */
+ mturate /= 8;
+ else if (cpu_is_u8500ed()) {
+ /*
+ * This clocking setting must not be used
+ * in the ED chip, it is simply not
+ * connected anywhere!
+ */
+ mturate = 0;
+ BUG();
+ } else
+ /*
+ * In this mode the ulp38m4 clock is divided
+ * by a factor 16, on the DB8500 typically
+ * 38400000 / 16 ~ 2.4 MHz.
+ * TODO: Replace the constant with a reference
+ * to the ULP source once this is modeled.
+ */
+ mturate = 38400000 / 16;
+ }
+ }
+
+ /* Return the clock selected for this MTU */
+ if (tcr & (1 << mtu))
+ retclk = clk32k;
+ else
+ retclk = mturate;
+
+ pr_info("MTU%d clock rate: %lu Hz\n", mtu, retclk);
+ return retclk;
+}
+
unsigned long clk_get_rate(struct clk *clk)
{
unsigned long rate;
+ /*
+ * If there is a custom getrate callback for this clock,
+ * it will take precedence.
+ */
+ if (clk->get_rate)
+ return clk->get_rate(clk);
+
if (clk->ops && clk->ops->get_rate)
return clk->ops->get_rate(clk);
@@ -341,8 +430,9 @@
/* Peripheral Cluster #6 */
-static DEFINE_PRCC_CLK(6, mtu1_v1, 8, -1, NULL);
-static DEFINE_PRCC_CLK(6, mtu0_v1, 7, -1, NULL);
+/* MTU ID in data */
+static DEFINE_PRCC_CLK_CUSTOM(6, mtu1_v1, 8, -1, NULL, clk_mtu_get_rate, 1);
+static DEFINE_PRCC_CLK_CUSTOM(6, mtu0_v1, 7, -1, NULL, clk_mtu_get_rate, 0);
static DEFINE_PRCC_CLK(6, cfgreg_v1, 6, 6, NULL);
static DEFINE_PRCC_CLK(6, dmc_ed, 6, 6, NULL);
static DEFINE_PRCC_CLK(6, hash1, 5, -1, NULL);
@@ -357,8 +447,9 @@
/* Peripheral Cluster #7 */
static DEFINE_PRCC_CLK(7, tzpc0_ed, 4, -1, NULL);
-static DEFINE_PRCC_CLK(7, mtu1_ed, 3, -1, NULL);
-static DEFINE_PRCC_CLK(7, mtu0_ed, 2, -1, NULL);
+/* MTU ID in data */
+static DEFINE_PRCC_CLK_CUSTOM(7, mtu1_ed, 3, -1, NULL, clk_mtu_get_rate, 1);
+static DEFINE_PRCC_CLK_CUSTOM(7, mtu0_ed, 2, -1, NULL, clk_mtu_get_rate, 0);
static DEFINE_PRCC_CLK(7, wdg_ed, 1, -1, NULL);
static DEFINE_PRCC_CLK(7, cfgreg_ed, 0, -1, NULL);
@@ -503,15 +594,17 @@
CLK(uiccclk, "uicc", NULL),
};
-static int __init clk_init(void)
+int __init clk_init(void)
{
if (cpu_is_u8500ed()) {
clk_prcmu_ops.enable = clk_prcmu_ed_enable;
clk_prcmu_ops.disable = clk_prcmu_ed_disable;
+ clk_per6clk.rate = 100000000;
} else if (cpu_is_u5500()) {
/* Clock tree for U5500 not implemented yet */
clk_prcc_ops.enable = clk_prcc_ops.disable = NULL;
clk_prcmu_ops.enable = clk_prcmu_ops.disable = NULL;
+ clk_per6clk.rate = 26000000;
}
clkdev_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks));
@@ -522,4 +615,3 @@
return 0;
}
-arch_initcall(clk_init);
diff --git a/arch/arm/mach-ux500/clock.h b/arch/arm/mach-ux500/clock.h
index e4f99b6..a058025 100644
--- a/arch/arm/mach-ux500/clock.h
+++ b/arch/arm/mach-ux500/clock.h
@@ -28,6 +28,9 @@
* @ops: pointer to clkops struct used to control this clock
* @name: name, for debugging
* @enabled: refcount. positive if enabled, zero if disabled
+ * @get_rate: custom callback for getting the clock rate
+ * @data: custom per-clock data for example for the get_rate
+ * callback
* @rate: fixed rate for clocks which don't implement
* ops->getrate
* @prcmu_cg_off: address offset of the combined enable/disable register
@@ -67,6 +70,8 @@
const struct clkops *ops;
const char *name;
unsigned int enabled;
+ unsigned long (*get_rate)(struct clk *);
+ void *data;
unsigned long rate;
struct list_head list;
@@ -117,9 +122,26 @@
.parent_periph = _kernclk \
}
+#define DEFINE_PRCC_CLK_CUSTOM(_pclust, _name, _bus_en, _kernel_en, _kernclk, _callback, _data) \
+struct clk clk_##_name = { \
+ .name = #_name, \
+ .ops = &clk_prcc_ops, \
+ .cluster = _pclust, \
+ .prcc_bus = _bus_en, \
+ .prcc_kernel = _kernel_en, \
+ .parent_cluster = &clk_per##_pclust##clk, \
+ .parent_periph = _kernclk, \
+ .get_rate = _callback, \
+ .data = (void *) _data \
+ }
+
+
#define CLK(_clk, _devname, _conname) \
{ \
.clk = &clk_##_clk, \
.dev_id = _devname, \
.con_id = _conname, \
}
+
+int __init clk_db8500_ed_fixup(void);
+int __init clk_init(void);
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index d81ad02..e0fd747 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -62,6 +62,12 @@
{
gic_dist_init(0, __io_address(UX500_GIC_DIST_BASE), 29);
gic_cpu_init(0, __io_address(UX500_GIC_CPU_BASE));
+
+ /*
+ * Init clocks here so that they are available for system timer
+ * initialization.
+ */
+ clk_init();
}
#ifdef CONFIG_CACHE_L2X0
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
index e6f7303..9b11eed 100644
--- a/arch/arm/mach-vexpress/ct-ca9x4.c
+++ b/arch/arm/mach-vexpress/ct-ca9x4.c
@@ -2,6 +2,7 @@
* Versatile Express Core Tile Cortex A9x4 Support
*/
#include <linux/init.h>
+#include <linux/gfp.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
diff --git a/arch/arm/mm/copypage-feroceon.c b/arch/arm/mm/copypage-feroceon.c
index 5eb4fd9..ac163de 100644
--- a/arch/arm/mm/copypage-feroceon.c
+++ b/arch/arm/mm/copypage-feroceon.c
@@ -18,7 +18,7 @@
{
asm("\
stmfd sp!, {r4-r9, lr} \n\
- mov ip, %0 \n\
+ mov ip, %2 \n\
1: mov lr, r1 \n\
ldmia r1!, {r2 - r9} \n\
pld [lr, #32] \n\
@@ -64,7 +64,7 @@
mcr p15, 0, ip, c7, c10, 4 @ drain WB\n\
ldmfd sp!, {r4-r9, pc}"
:
- : "I" (PAGE_SIZE));
+ : "r" (kto), "r" (kfrom), "I" (PAGE_SIZE));
}
void feroceon_copy_user_highpage(struct page *to, struct page *from,
diff --git a/arch/arm/mm/copypage-v4wb.c b/arch/arm/mm/copypage-v4wb.c
index 7c2eb55..cb589cb 100644
--- a/arch/arm/mm/copypage-v4wb.c
+++ b/arch/arm/mm/copypage-v4wb.c
@@ -27,7 +27,7 @@
{
asm("\
stmfd sp!, {r4, lr} @ 2\n\
- mov r2, %0 @ 1\n\
+ mov r2, %2 @ 1\n\
ldmia r1!, {r3, r4, ip, lr} @ 4\n\
1: mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line\n\
stmia r0!, {r3, r4, ip, lr} @ 4\n\
@@ -44,7 +44,7 @@
mcr p15, 0, r1, c7, c10, 4 @ 1 drain WB\n\
ldmfd sp!, {r4, pc} @ 3"
:
- : "I" (PAGE_SIZE / 64));
+ : "r" (kto), "r" (kfrom), "I" (PAGE_SIZE / 64));
}
void v4wb_copy_user_highpage(struct page *to, struct page *from,
diff --git a/arch/arm/mm/copypage-v4wt.c b/arch/arm/mm/copypage-v4wt.c
index 172e6a5..30c7d04 100644
--- a/arch/arm/mm/copypage-v4wt.c
+++ b/arch/arm/mm/copypage-v4wt.c
@@ -25,7 +25,7 @@
{
asm("\
stmfd sp!, {r4, lr} @ 2\n\
- mov r2, %0 @ 1\n\
+ mov r2, %2 @ 1\n\
ldmia r1!, {r3, r4, ip, lr} @ 4\n\
1: stmia r0!, {r3, r4, ip, lr} @ 4\n\
ldmia r1!, {r3, r4, ip, lr} @ 4+1\n\
@@ -40,7 +40,7 @@
mcr p15, 0, r2, c7, c7, 0 @ flush ID cache\n\
ldmfd sp!, {r4, pc} @ 3"
:
- : "I" (PAGE_SIZE / 64));
+ : "r" (kto), "r" (kfrom), "I" (PAGE_SIZE / 64));
}
void v4wt_copy_user_highpage(struct page *to, struct page *from,
diff --git a/arch/arm/mm/copypage-xsc3.c b/arch/arm/mm/copypage-xsc3.c
index 747ad41..f9cde07 100644
--- a/arch/arm/mm/copypage-xsc3.c
+++ b/arch/arm/mm/copypage-xsc3.c
@@ -34,7 +34,7 @@
{
asm("\
stmfd sp!, {r4, r5, lr} \n\
- mov lr, %0 \n\
+ mov lr, %2 \n\
\n\
pld [r1, #0] \n\
pld [r1, #32] \n\
@@ -67,7 +67,7 @@
\n\
ldmfd sp!, {r4, r5, pc}"
:
- : "I" (PAGE_SIZE / 64 - 1));
+ : "r" (kto), "r" (kfrom), "I" (PAGE_SIZE / 64 - 1));
}
void xsc3_mc_copy_user_highpage(struct page *to, struct page *from,
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 92f5801..cbfb2ed 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -393,6 +393,9 @@
if (addr < TASK_SIZE)
return do_page_fault(addr, fsr, regs);
+ if (user_mode(regs))
+ goto bad_area;
+
index = pgd_index(addr);
/*
diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c
index 77b030f..086816b 100644
--- a/arch/arm/mm/highmem.c
+++ b/arch/arm/mm/highmem.c
@@ -48,7 +48,16 @@
debug_kmap_atomic(type);
- kmap = kmap_high_get(page);
+#ifdef CONFIG_DEBUG_HIGHMEM
+ /*
+ * There is no cache coherency issue when non VIVT, so force the
+ * dedicated kmap usage for better debugging purposes in that case.
+ */
+ if (!cache_is_vivt())
+ kmap = NULL;
+ else
+#endif
+ kmap = kmap_high_get(page);
if (kmap)
return kmap;
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 1ba6cf5..f6a9994 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -678,10 +678,10 @@
void free_initmem(void)
{
#ifdef CONFIG_HAVE_TCM
- extern char *__tcm_start, *__tcm_end;
+ extern char __tcm_start, __tcm_end;
- totalram_pages += free_area(__phys_to_pfn(__pa(__tcm_start)),
- __phys_to_pfn(__pa(__tcm_end)),
+ totalram_pages += free_area(__phys_to_pfn(__pa(&__tcm_start)),
+ __phys_to_pfn(__pa(&__tcm_end)),
"TCM link");
#endif
diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c
index 0ff3798..08aaa4a 100644
--- a/arch/arm/plat-nomadik/timer.c
+++ b/arch/arm/plat-nomadik/timer.c
@@ -13,7 +13,9 @@
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/clockchips.h>
+#include <linux/clk.h>
#include <linux/jiffies.h>
+#include <linux/err.h>
#include <asm/mach/time.h>
#include <plat/mtu.h>
@@ -124,13 +126,25 @@
void __init nmdk_timer_init(void)
{
unsigned long rate;
- u32 cr = MTU_CRn_32BITS;;
+ struct clk *clk0;
+ struct clk *clk1;
+ u32 cr;
+
+ clk0 = clk_get_sys("mtu0", NULL);
+ BUG_ON(IS_ERR(clk0));
+
+ clk1 = clk_get_sys("mtu1", NULL);
+ BUG_ON(IS_ERR(clk1));
+
+ clk_enable(clk0);
+ clk_enable(clk1);
/*
* Tick rate is 2.4MHz for Nomadik and 110MHz for ux500:
* use a divide-by-16 counter if it's more than 16MHz
*/
- rate = CLOCK_TICK_RATE;
+ cr = MTU_CRn_32BITS;;
+ rate = clk_get_rate(clk0);
if (rate > 16 << 20) {
rate /= 16;
cr |= MTU_CRn_PRESCALE_16;
@@ -153,6 +167,14 @@
nmdk_clksrc.name);
/* Timer 1 is used for events, fix according to rate */
+ cr = MTU_CRn_32BITS;
+ rate = clk_get_rate(clk1);
+ if (rate > 16 << 20) {
+ rate /= 16;
+ cr |= MTU_CRn_PRESCALE_16;
+ } else {
+ cr |= MTU_CRn_PRESCALE_1;
+ }
writel(cr | MTU_CRn_ONESHOT, mtu_base + MTU_CR(1)); /* off, currently */
nmdk_clkevt.mult = div_sc(rate, NSEC_PER_SEC, nmdk_clkevt.shift);
nmdk_clkevt.max_delta_ns =
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index c64875f..44bafda 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -541,11 +541,11 @@
* timer is stopped
*/
udelay(3500000 / clk_get_rate(timer->fclk) + 1);
- /* Ack possibly pending interrupt */
- omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG,
- OMAP_TIMER_INT_OVERFLOW);
#endif
}
+ /* Ack possibly pending interrupt */
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG,
+ OMAP_TIMER_INT_OVERFLOW);
}
EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index 393e921..9b7e354 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -673,6 +673,7 @@
if (cpu_is_omap34xx() || cpu_is_omap44xx())
clk_disable(bank->dbck);
}
+ bank->dbck_enable_mask = val;
__raw_writel(val, reg);
}
diff --git a/arch/arm/plat-omap/iovmm.c b/arch/arm/plat-omap/iovmm.c
index e43983b..8ce0de2 100644
--- a/arch/arm/plat-omap/iovmm.c
+++ b/arch/arm/plat-omap/iovmm.c
@@ -140,8 +140,10 @@
return ERR_PTR(-ENOMEM);
err = sg_alloc_table(sgt, nr_entries, GFP_KERNEL);
- if (err)
+ if (err) {
+ kfree(sgt);
return ERR_PTR(err);
+ }
pr_debug("%s: sgt:%p(%d entries)\n", __func__, sgt, nr_entries);
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
index 66dc2d0..d66cead 100644
--- a/arch/arm/vfp/vfphw.S
+++ b/arch/arm/vfp/vfphw.S
@@ -277,7 +277,7 @@
#ifdef CONFIG_VFPv3
@ d16 - d31 registers
.irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
-1: mcrr p11, 3, r1, r2, c\dr @ fmdrr r1, r2, d\dr
+1: mcrr p11, 3, r0, r1, c\dr @ fmdrr r0, r1, d\dr
mov pc, lr
.org 1b + 8
.endr
diff --git a/arch/frv/kernel/gdb-stub.c b/arch/frv/kernel/gdb-stub.c
index 84d103c3..a4dba6b 100644
--- a/arch/frv/kernel/gdb-stub.c
+++ b/arch/frv/kernel/gdb-stub.c
@@ -1789,6 +1789,12 @@
flush_cache = 1;
break;
+ /* pNN: Read value of reg N and return it */
+ case 'p':
+ /* return no value, indicating that we don't support
+ * this command and that gdb should use 'g' instead */
+ break;
+
/* PNN,=RRRRRRRR: Write value R to reg N return OK */
case 'P':
ptr = &input_buffer[1];
diff --git a/arch/frv/mm/fault.c b/arch/frv/mm/fault.c
index 30f5d10..a325d57 100644
--- a/arch/frv/mm/fault.c
+++ b/arch/frv/mm/fault.c
@@ -257,10 +257,10 @@
*/
out_of_memory:
up_read(&mm->mmap_sem);
- printk("VM: killing process %s\n", current->comm);
- if (user_mode(__frame))
- do_group_exit(SIGKILL);
- goto no_context;
+ if (!user_mode(__frame))
+ goto no_context;
+ pagefault_out_of_memory();
+ return;
do_sigbus:
up_read(&mm->mmap_sem);
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index d5f4e91..21b70137 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -144,6 +144,7 @@
VP_INIT_ENV : VP_INIT_ENV_INITALIZE,
__pa(kvm_vm_buffer), KVM_VM_BUFFER_BASE, &tmp_base);
if (status != 0) {
+ spin_unlock(&vp_lock);
printk(KERN_WARNING"kvm: Failed to Enable VT Support!!!!\n");
return -EINVAL;
}
diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
index 5dfd916..7b3cdc6 100644
--- a/arch/ia64/mm/tlb.c
+++ b/arch/ia64/mm/tlb.c
@@ -121,7 +121,7 @@
ia64_invala();
for (;;) {
- asm volatile ("ld4.c.nc %0=[%1]" : "=r"(serve) : "r"(&ss->serve) : "memory");
+ asm volatile ("ld8.c.nc %0=[%1]" : "=r"(serve) : "r"(&ss->serve) : "memory");
if (time_before(t, serve))
return;
cpu_relax();
diff --git a/arch/m32r/mm/fault.c b/arch/m32r/mm/fault.c
index 28ee389..b8ec002 100644
--- a/arch/m32r/mm/fault.c
+++ b/arch/m32r/mm/fault.c
@@ -188,7 +188,6 @@
if ((error_code & ACE_INSTRUCTION) && !(vma->vm_flags & VM_EXEC))
goto bad_area;
-survive:
/*
* If for any reason at all we couldn't handle the fault,
* make sure we exit gracefully rather than endlessly redo
@@ -271,15 +270,10 @@
*/
out_of_memory:
up_read(&mm->mmap_sem);
- if (is_global_init(tsk)) {
- yield();
- down_read(&mm->mmap_sem);
- goto survive;
- }
- printk("VM: killing process %s\n", tsk->comm);
- if (error_code & ACE_USERMODE)
- do_group_exit(SIGKILL);
- goto no_context;
+ if (!(error_code & ACE_USERMODE))
+ goto no_context;
+ pagefault_out_of_memory();
+ return;
do_sigbus:
up_read(&mm->mmap_sem);
diff --git a/arch/microblaze/include/asm/page.h b/arch/microblaze/include/asm/page.h
index de493f8..464ff32 100644
--- a/arch/microblaze/include/asm/page.h
+++ b/arch/microblaze/include/asm/page.h
@@ -34,6 +34,8 @@
/* MS be sure that SLAB allocates aligned objects */
#define ARCH_KMALLOC_MINALIGN L1_CACHE_BYTES
+#define ARCH_SLAB_MINALIGN L1_CACHE_BYTES
+
#define PAGE_UP(addr) (((addr)+((PAGE_SIZE)-1))&(~((PAGE_SIZE)-1)))
#define PAGE_DOWN(addr) ((addr)&(~((PAGE_SIZE)-1)))
diff --git a/arch/microblaze/kernel/dma.c b/arch/microblaze/kernel/dma.c
index 9dcd90b..79c7465 100644
--- a/arch/microblaze/kernel/dma.c
+++ b/arch/microblaze/kernel/dma.c
@@ -90,7 +90,6 @@
/* FIXME this part of code is untested */
for_each_sg(sgl, sg, nents, i) {
sg->dma_address = sg_phys(sg) + get_dma_direct_offset(dev);
- sg->dma_length = sg->length;
__dma_sync_page(page_to_phys(sg_page(sg)), sg->offset,
sg->length, direction);
}
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index 9cb782b..23be25f 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -1277,6 +1277,7 @@
printk(KERN_WARNING "PCI: Cannot allocate resource region "
"%d of PCI bridge %d, will remap\n", i, bus->number);
clear_resource:
+ res->start = res->end = 0;
res->flags = 0;
}
diff --git a/arch/mn10300/mm/fault.c b/arch/mn10300/mm/fault.c
index 53bb17d..81f153f 100644
--- a/arch/mn10300/mm/fault.c
+++ b/arch/mn10300/mm/fault.c
@@ -338,11 +338,10 @@
*/
out_of_memory:
up_read(&mm->mmap_sem);
- monitor_signal(regs);
- printk(KERN_ALERT "VM: killing process %s\n", tsk->comm);
- if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR)
- do_exit(SIGKILL);
- goto no_context;
+ if ((fault_code & MMUFCR_xFC_ACCESS) != MMUFCR_xFC_ACCESS_USR)
+ goto no_context;
+ pagefault_out_of_memory();
+ return;
do_sigbus:
up_read(&mm->mmap_sem);
diff --git a/arch/mn10300/unit-asb2305/pci-asb2305.c b/arch/mn10300/unit-asb2305/pci-asb2305.c
index d6119b8..45b40ac 100644
--- a/arch/mn10300/unit-asb2305/pci-asb2305.c
+++ b/arch/mn10300/unit-asb2305/pci-asb2305.c
@@ -117,6 +117,7 @@
* Invalidate the resource to prevent
* child resource allocations in this
* range. */
+ r->start = r->end = 0;
r->flags = 0;
}
}
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 53696da..2d38a50 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -135,13 +135,6 @@
depends on KGDB || XMON
default y
-config IRQSTACKS
- bool "Use separate kernel stacks when processing interrupts"
- help
- If you say Y here the kernel will use separate kernel stacks
- for handling hard and soft interrupts. This can help avoid
- overflowing the process kernel stacks.
-
config VIRQ_DEBUG
bool "Expose hardware/virtual IRQ mapping via debugfs"
depends on DEBUG_FS
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index ad0df7d..fae8192 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -141,7 +141,7 @@
$(obj)/wrapper.a: $(obj-wlib) FORCE
$(call if_changed,bootar)
-hostprogs-y := addnote addRamDisk hack-coff mktree
+hostprogs-y := addnote hack-coff mktree
targets += $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a)
extra-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \
diff --git a/arch/powerpc/boot/addRamDisk.c b/arch/powerpc/boot/addRamDisk.c
deleted file mode 100644
index 893f446..0000000
--- a/arch/powerpc/boot/addRamDisk.c
+++ /dev/null
@@ -1,311 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <netinet/in.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <string.h>
-#include <elf.h>
-
-#define ElfHeaderSize (64 * 1024)
-#define ElfPages (ElfHeaderSize / 4096)
-#define KERNELBASE (0xc000000000000000)
-#define _ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1)))
-
-struct addr_range {
- unsigned long long addr;
- unsigned long memsize;
- unsigned long offset;
-};
-
-static int check_elf64(void *p, int size, struct addr_range *r)
-{
- Elf64_Ehdr *elf64 = p;
- Elf64_Phdr *elf64ph;
-
- if (elf64->e_ident[EI_MAG0] != ELFMAG0 ||
- elf64->e_ident[EI_MAG1] != ELFMAG1 ||
- elf64->e_ident[EI_MAG2] != ELFMAG2 ||
- elf64->e_ident[EI_MAG3] != ELFMAG3 ||
- elf64->e_ident[EI_CLASS] != ELFCLASS64 ||
- elf64->e_ident[EI_DATA] != ELFDATA2MSB ||
- elf64->e_type != ET_EXEC || elf64->e_machine != EM_PPC64)
- return 0;
-
- if ((elf64->e_phoff + sizeof(Elf64_Phdr)) > size)
- return 0;
-
- elf64ph = (Elf64_Phdr *) ((unsigned long)elf64 +
- (unsigned long)elf64->e_phoff);
-
- r->memsize = (unsigned long)elf64ph->p_memsz;
- r->offset = (unsigned long)elf64ph->p_offset;
- r->addr = (unsigned long long)elf64ph->p_vaddr;
-
-#ifdef DEBUG
- printf("PPC64 ELF file, ph:\n");
- printf("p_type 0x%08x\n", elf64ph->p_type);
- printf("p_flags 0x%08x\n", elf64ph->p_flags);
- printf("p_offset 0x%016llx\n", elf64ph->p_offset);
- printf("p_vaddr 0x%016llx\n", elf64ph->p_vaddr);
- printf("p_paddr 0x%016llx\n", elf64ph->p_paddr);
- printf("p_filesz 0x%016llx\n", elf64ph->p_filesz);
- printf("p_memsz 0x%016llx\n", elf64ph->p_memsz);
- printf("p_align 0x%016llx\n", elf64ph->p_align);
- printf("... skipping 0x%08lx bytes of ELF header\n",
- (unsigned long)elf64ph->p_offset);
-#endif
-
- return 64;
-}
-static void get4k(FILE *file, char *buf )
-{
- unsigned j;
- unsigned num = fread(buf, 1, 4096, file);
- for ( j=num; j<4096; ++j )
- buf[j] = 0;
-}
-
-static void put4k(FILE *file, char *buf )
-{
- fwrite(buf, 1, 4096, file);
-}
-
-static void death(const char *msg, FILE *fdesc, const char *fname)
-{
- fprintf(stderr, msg);
- fclose(fdesc);
- unlink(fname);
- exit(1);
-}
-
-int main(int argc, char **argv)
-{
- char inbuf[4096];
- struct addr_range vmlinux;
- FILE *ramDisk;
- FILE *inputVmlinux;
- FILE *outputVmlinux;
-
- char *rd_name, *lx_name, *out_name;
-
- size_t i;
- unsigned long ramFileLen;
- unsigned long ramLen;
- unsigned long roundR;
- unsigned long offset_end;
-
- unsigned long kernelLen;
- unsigned long actualKernelLen;
- unsigned long round;
- unsigned long roundedKernelLen;
- unsigned long ramStartOffs;
- unsigned long ramPages;
- unsigned long roundedKernelPages;
- unsigned long hvReleaseData;
- u_int32_t eyeCatcher = 0xc8a5d9c4;
- unsigned long naca;
- unsigned long xRamDisk;
- unsigned long xRamDiskSize;
- long padPages;
-
-
- if (argc < 2) {
- fprintf(stderr, "Name of RAM disk file missing.\n");
- exit(1);
- }
- rd_name = argv[1];
-
- if (argc < 3) {
- fprintf(stderr, "Name of vmlinux file missing.\n");
- exit(1);
- }
- lx_name = argv[2];
-
- if (argc < 4) {
- fprintf(stderr, "Name of vmlinux output file missing.\n");
- exit(1);
- }
- out_name = argv[3];
-
-
- ramDisk = fopen(rd_name, "r");
- if ( ! ramDisk ) {
- fprintf(stderr, "RAM disk file \"%s\" failed to open.\n", rd_name);
- exit(1);
- }
-
- inputVmlinux = fopen(lx_name, "r");
- if ( ! inputVmlinux ) {
- fprintf(stderr, "vmlinux file \"%s\" failed to open.\n", lx_name);
- exit(1);
- }
-
- outputVmlinux = fopen(out_name, "w+");
- if ( ! outputVmlinux ) {
- fprintf(stderr, "output vmlinux file \"%s\" failed to open.\n", out_name);
- exit(1);
- }
-
- i = fread(inbuf, 1, sizeof(inbuf), inputVmlinux);
- if (i != sizeof(inbuf)) {
- fprintf(stderr, "can not read vmlinux file %s: %u\n", lx_name, i);
- exit(1);
- }
-
- i = check_elf64(inbuf, sizeof(inbuf), &vmlinux);
- if (i == 0) {
- fprintf(stderr, "You must have a linux kernel specified as argv[2]\n");
- exit(1);
- }
-
- /* Input Vmlinux file */
- fseek(inputVmlinux, 0, SEEK_END);
- kernelLen = ftell(inputVmlinux);
- fseek(inputVmlinux, 0, SEEK_SET);
- printf("kernel file size = %lu\n", kernelLen);
-
- actualKernelLen = kernelLen - ElfHeaderSize;
-
- printf("actual kernel length (minus ELF header) = %lu\n", actualKernelLen);
-
- round = actualKernelLen % 4096;
- roundedKernelLen = actualKernelLen;
- if ( round )
- roundedKernelLen += (4096 - round);
- printf("Vmlinux length rounded up to a 4k multiple = %ld/0x%lx \n", roundedKernelLen, roundedKernelLen);
- roundedKernelPages = roundedKernelLen / 4096;
- printf("Vmlinux pages to copy = %ld/0x%lx \n", roundedKernelPages, roundedKernelPages);
-
- offset_end = _ALIGN_UP(vmlinux.memsize, 4096);
- /* calc how many pages we need to insert between the vmlinux and the start of the ram disk */
- padPages = offset_end/4096 - roundedKernelPages;
-
- /* Check and see if the vmlinux is already larger than _end in System.map */
- if (padPages < 0) {
- /* vmlinux is larger than _end - adjust the offset to the start of the embedded ram disk */
- offset_end = roundedKernelLen;
- printf("vmlinux is larger than _end indicates it needs to be - offset_end = %lx \n", offset_end);
- padPages = 0;
- printf("will insert %lx pages between the vmlinux and the start of the ram disk \n", padPages);
- }
- else {
- /* _end is larger than vmlinux - use the offset to _end that we calculated from the system map */
- printf("vmlinux is smaller than _end indicates is needed - offset_end = %lx \n", offset_end);
- printf("will insert %lx pages between the vmlinux and the start of the ram disk \n", padPages);
- }
-
-
-
- /* Input Ram Disk file */
- // Set the offset that the ram disk will be started at.
- ramStartOffs = offset_end; /* determined from the input vmlinux file and the system map */
- printf("Ram Disk will start at offset = 0x%lx \n", ramStartOffs);
-
- fseek(ramDisk, 0, SEEK_END);
- ramFileLen = ftell(ramDisk);
- fseek(ramDisk, 0, SEEK_SET);
- printf("%s file size = %ld/0x%lx \n", rd_name, ramFileLen, ramFileLen);
-
- ramLen = ramFileLen;
-
- roundR = 4096 - (ramLen % 4096);
- if ( roundR ) {
- printf("Rounding RAM disk file up to a multiple of 4096, adding %ld/0x%lx \n", roundR, roundR);
- ramLen += roundR;
- }
-
- printf("Rounded RAM disk size is %ld/0x%lx \n", ramLen, ramLen);
- ramPages = ramLen / 4096;
- printf("RAM disk pages to copy = %ld/0x%lx\n", ramPages, ramPages);
-
-
-
- // Copy 64K ELF header
- for (i=0; i<(ElfPages); ++i) {
- get4k( inputVmlinux, inbuf );
- put4k( outputVmlinux, inbuf );
- }
-
- /* Copy the vmlinux (as full pages). */
- fseek(inputVmlinux, ElfHeaderSize, SEEK_SET);
- for ( i=0; i<roundedKernelPages; ++i ) {
- get4k( inputVmlinux, inbuf );
- put4k( outputVmlinux, inbuf );
- }
-
- /* Insert pad pages (if appropriate) that are needed between */
- /* | the end of the vmlinux and the ram disk. */
- for (i=0; i<padPages; ++i) {
- memset(inbuf, 0, 4096);
- put4k(outputVmlinux, inbuf);
- }
-
- /* Copy the ram disk (as full pages). */
- for ( i=0; i<ramPages; ++i ) {
- get4k( ramDisk, inbuf );
- put4k( outputVmlinux, inbuf );
- }
-
- /* Close the input files */
- fclose(ramDisk);
- fclose(inputVmlinux);
- /* And flush the written output file */
- fflush(outputVmlinux);
-
-
-
- /* Fixup the new vmlinux to contain the ram disk starting offset (xRamDisk) and the ram disk size (xRamDiskSize) */
- /* fseek to the hvReleaseData pointer */
- fseek(outputVmlinux, ElfHeaderSize + 0x24, SEEK_SET);
- if (fread(&hvReleaseData, 4, 1, outputVmlinux) != 1) {
- death("Could not read hvReleaseData pointer\n", outputVmlinux, out_name);
- }
- hvReleaseData = ntohl(hvReleaseData); /* Convert to native int */
- printf("hvReleaseData is at %08lx\n", hvReleaseData);
-
- /* fseek to the hvReleaseData */
- fseek(outputVmlinux, ElfHeaderSize + hvReleaseData, SEEK_SET);
- if (fread(inbuf, 0x40, 1, outputVmlinux) != 1) {
- death("Could not read hvReleaseData\n", outputVmlinux, out_name);
- }
- /* Check hvReleaseData sanity */
- if (memcmp(inbuf, &eyeCatcher, 4) != 0) {
- death("hvReleaseData is invalid\n", outputVmlinux, out_name);
- }
- /* Get the naca pointer */
- naca = ntohl(*((u_int32_t*) &inbuf[0x0C])) - KERNELBASE;
- printf("Naca is at offset 0x%lx \n", naca);
-
- /* fseek to the naca */
- fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET);
- if (fread(inbuf, 0x18, 1, outputVmlinux) != 1) {
- death("Could not read naca\n", outputVmlinux, out_name);
- }
- xRamDisk = ntohl(*((u_int32_t *) &inbuf[0x0c]));
- xRamDiskSize = ntohl(*((u_int32_t *) &inbuf[0x14]));
- /* Make sure a RAM disk isn't already present */
- if ((xRamDisk != 0) || (xRamDiskSize != 0)) {
- death("RAM disk is already attached to this kernel\n", outputVmlinux, out_name);
- }
- /* Fill in the values */
- *((u_int32_t *) &inbuf[0x0c]) = htonl(ramStartOffs);
- *((u_int32_t *) &inbuf[0x14]) = htonl(ramPages);
-
- /* Write out the new naca */
- fflush(outputVmlinux);
- fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET);
- if (fwrite(inbuf, 0x18, 1, outputVmlinux) != 1) {
- death("Could not write naca\n", outputVmlinux, out_name);
- }
- printf("Ram Disk of 0x%lx pages is attached to the kernel at offset 0x%08lx\n",
- ramPages, ramStartOffs);
-
- /* Done */
- fclose(outputVmlinux);
- /* Set permission to executable */
- chmod(out_name, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
-
- return 0;
-}
-
diff --git a/arch/powerpc/boot/dts/lite5200.dts b/arch/powerpc/boot/dts/lite5200.dts
index 82ff2b1..179a178 100644
--- a/arch/powerpc/boot/dts/lite5200.dts
+++ b/arch/powerpc/boot/dts/lite5200.dts
@@ -134,12 +134,16 @@
compatible = "fsl,mpc5200-gpio";
reg = <0xb00 0x40>;
interrupts = <1 7 0>;
+ gpio-controller;
+ #gpio-cells = <2>;
};
gpio@c00 {
compatible = "fsl,mpc5200-gpio-wkup";
reg = <0xc00 0x40>;
interrupts = <1 8 0 0 3 0>;
+ gpio-controller;
+ #gpio-cells = <2>;
};
spi@f00 {
@@ -230,8 +234,8 @@
reg = <0x3000 0x400>; // fec range, since we need to setup fec interrupts
interrupts = <2 5 0>; // these are for "mii command finished", not link changes & co.
- phy0: ethernet-phy@1 {
- reg = <1>;
+ phy0: ethernet-phy@0 {
+ reg = <0>;
};
};
@@ -255,7 +259,13 @@
compatible = "fsl,mpc5200-i2c","fsl-i2c";
reg = <0x3d40 0x40>;
interrupts = <2 16 0>;
+
+ eeprom@50 {
+ compatible = "atmel,24c02";
+ reg = <0x50>;
+ };
};
+
sram@8000 {
compatible = "fsl,mpc5200-sram";
reg = <0x8000 0x4000>;
@@ -281,4 +291,18 @@
0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;
};
+
+ localbus {
+ compatible = "fsl,mpc5200-lpb","simple-bus";
+ #address-cells = <2>;
+ #size-cells = <1>;
+
+ ranges = <0 0 0xff000000 0x01000000>;
+
+ flash@0,0 {
+ compatible = "amd,am29lv652d", "cfi-flash";
+ reg = <0 0 0x01000000>;
+ bank-width = <1>;
+ };
+ };
};
diff --git a/arch/powerpc/boot/dts/lite5200b.dts b/arch/powerpc/boot/dts/lite5200b.dts
index e45a63b..59702ac 100644
--- a/arch/powerpc/boot/dts/lite5200b.dts
+++ b/arch/powerpc/boot/dts/lite5200b.dts
@@ -259,6 +259,11 @@
compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
reg = <0x3d40 0x40>;
interrupts = <2 16 0>;
+
+ eeprom@50 {
+ compatible = "atmel,24c02";
+ reg = <0x50>;
+ };
};
sram@8000 {
diff --git a/arch/powerpc/configs/40x/acadia_defconfig b/arch/powerpc/configs/40x/acadia_defconfig
index 8e95f8d..4aa17b6 100644
--- a/arch/powerpc/configs/40x/acadia_defconfig
+++ b/arch/powerpc/configs/40x/acadia_defconfig
@@ -98,8 +98,7 @@
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/40x/ep405_defconfig b/arch/powerpc/configs/40x/ep405_defconfig
index 918f23f..9a5f1ab 100644
--- a/arch/powerpc/configs/40x/ep405_defconfig
+++ b/arch/powerpc/configs/40x/ep405_defconfig
@@ -98,8 +98,7 @@
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/40x/hcu4_defconfig b/arch/powerpc/configs/40x/hcu4_defconfig
index f87ef03..0b45213 100644
--- a/arch/powerpc/configs/40x/hcu4_defconfig
+++ b/arch/powerpc/configs/40x/hcu4_defconfig
@@ -98,8 +98,7 @@
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/40x/kilauea_defconfig b/arch/powerpc/configs/40x/kilauea_defconfig
index 19fbcb0..4d2de0b 100644
--- a/arch/powerpc/configs/40x/kilauea_defconfig
+++ b/arch/powerpc/configs/40x/kilauea_defconfig
@@ -98,8 +98,7 @@
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/40x/makalu_defconfig b/arch/powerpc/configs/40x/makalu_defconfig
index eb41cd6..a1f3f50 100644
--- a/arch/powerpc/configs/40x/makalu_defconfig
+++ b/arch/powerpc/configs/40x/makalu_defconfig
@@ -98,8 +98,7 @@
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/40x/virtex_defconfig b/arch/powerpc/configs/40x/virtex_defconfig
index 416e79a..c763135 100644
--- a/arch/powerpc/configs/40x/virtex_defconfig
+++ b/arch/powerpc/configs/40x/virtex_defconfig
@@ -77,8 +77,7 @@
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_GROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
diff --git a/arch/powerpc/configs/40x/walnut_defconfig b/arch/powerpc/configs/40x/walnut_defconfig
index bfff0ea..6597b2f 100644
--- a/arch/powerpc/configs/40x/walnut_defconfig
+++ b/arch/powerpc/configs/40x/walnut_defconfig
@@ -98,8 +98,7 @@
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/44x/arches_defconfig b/arch/powerpc/configs/44x/arches_defconfig
index 1f6d049..2d3dfb5 100644
--- a/arch/powerpc/configs/44x/arches_defconfig
+++ b/arch/powerpc/configs/44x/arches_defconfig
@@ -98,8 +98,7 @@
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_GROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/44x/bamboo_defconfig b/arch/powerpc/configs/44x/bamboo_defconfig
index 788faac..51a00c4 100644
--- a/arch/powerpc/configs/44x/bamboo_defconfig
+++ b/arch/powerpc/configs/44x/bamboo_defconfig
@@ -102,8 +102,7 @@
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/44x/canyonlands_defconfig b/arch/powerpc/configs/44x/canyonlands_defconfig
index 4ef8bca..1028b1b 100644
--- a/arch/powerpc/configs/44x/canyonlands_defconfig
+++ b/arch/powerpc/configs/44x/canyonlands_defconfig
@@ -98,8 +98,7 @@
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_GROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/44x/ebony_defconfig b/arch/powerpc/configs/44x/ebony_defconfig
index ca17b14..69f5633 100644
--- a/arch/powerpc/configs/44x/ebony_defconfig
+++ b/arch/powerpc/configs/44x/ebony_defconfig
@@ -101,8 +101,7 @@
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/44x/eiger_defconfig b/arch/powerpc/configs/44x/eiger_defconfig
index e3149ba..dcd859c 100644
--- a/arch/powerpc/configs/44x/eiger_defconfig
+++ b/arch/powerpc/configs/44x/eiger_defconfig
@@ -98,8 +98,7 @@
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_GROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/44x/katmai_defconfig b/arch/powerpc/configs/44x/katmai_defconfig
index af244e1..a2c24d1 100644
--- a/arch/powerpc/configs/44x/katmai_defconfig
+++ b/arch/powerpc/configs/44x/katmai_defconfig
@@ -97,8 +97,7 @@
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_GROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/44x/rainier_defconfig b/arch/powerpc/configs/44x/rainier_defconfig
index 8fed3b2..3bb55b5 100644
--- a/arch/powerpc/configs/44x/rainier_defconfig
+++ b/arch/powerpc/configs/44x/rainier_defconfig
@@ -101,8 +101,7 @@
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/44x/redwood_defconfig b/arch/powerpc/configs/44x/redwood_defconfig
index a67ec91..684f40d 100644
--- a/arch/powerpc/configs/44x/redwood_defconfig
+++ b/arch/powerpc/configs/44x/redwood_defconfig
@@ -98,8 +98,7 @@
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_GROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/44x/sam440ep_defconfig b/arch/powerpc/configs/44x/sam440ep_defconfig
index 886cb6a..e202924 100644
--- a/arch/powerpc/configs/44x/sam440ep_defconfig
+++ b/arch/powerpc/configs/44x/sam440ep_defconfig
@@ -103,8 +103,7 @@
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/44x/sequoia_defconfig b/arch/powerpc/configs/44x/sequoia_defconfig
index 1b2f41d..c348a46 100644
--- a/arch/powerpc/configs/44x/sequoia_defconfig
+++ b/arch/powerpc/configs/44x/sequoia_defconfig
@@ -102,8 +102,7 @@
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/44x/taishan_defconfig b/arch/powerpc/configs/44x/taishan_defconfig
index 12041d3..f4cb7e8 100644
--- a/arch/powerpc/configs/44x/taishan_defconfig
+++ b/arch/powerpc/configs/44x/taishan_defconfig
@@ -101,8 +101,7 @@
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/44x/virtex5_defconfig b/arch/powerpc/configs/44x/virtex5_defconfig
index 2518b85..c7ead0e 100644
--- a/arch/powerpc/configs/44x/virtex5_defconfig
+++ b/arch/powerpc/configs/44x/virtex5_defconfig
@@ -80,8 +80,7 @@
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_GROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
diff --git a/arch/powerpc/configs/52xx/cm5200_defconfig b/arch/powerpc/configs/52xx/cm5200_defconfig
index 218d49b..7664c83 100644
--- a/arch/powerpc/configs/52xx/cm5200_defconfig
+++ b/arch/powerpc/configs/52xx/cm5200_defconfig
@@ -95,8 +95,7 @@
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/52xx/lite5200b_defconfig b/arch/powerpc/configs/52xx/lite5200b_defconfig
index 90492ff2..eac7c17 100644
--- a/arch/powerpc/configs/52xx/lite5200b_defconfig
+++ b/arch/powerpc/configs/52xx/lite5200b_defconfig
@@ -96,8 +96,7 @@
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/52xx/motionpro_defconfig b/arch/powerpc/configs/52xx/motionpro_defconfig
index dffc8ca..27afb6e 100644
--- a/arch/powerpc/configs/52xx/motionpro_defconfig
+++ b/arch/powerpc/configs/52xx/motionpro_defconfig
@@ -95,8 +95,7 @@
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/52xx/pcm030_defconfig b/arch/powerpc/configs/52xx/pcm030_defconfig
index 3cb2a52..5fe39dd 100644
--- a/arch/powerpc/configs/52xx/pcm030_defconfig
+++ b/arch/powerpc/configs/52xx/pcm030_defconfig
@@ -98,8 +98,7 @@
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
# CONFIG_BLK_DEV_INITRD is not set
diff --git a/arch/powerpc/configs/52xx/tqm5200_defconfig b/arch/powerpc/configs/52xx/tqm5200_defconfig
index 96181c6..a108b84 100644
--- a/arch/powerpc/configs/52xx/tqm5200_defconfig
+++ b/arch/powerpc/configs/52xx/tqm5200_defconfig
@@ -95,8 +95,7 @@
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/86xx/gef_ppc9a_defconfig b/arch/powerpc/configs/86xx/gef_ppc9a_defconfig
index 183c59c..b728a7d 100644
--- a/arch/powerpc/configs/86xx/gef_ppc9a_defconfig
+++ b/arch/powerpc/configs/86xx/gef_ppc9a_defconfig
@@ -103,8 +103,7 @@
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
CONFIG_RELAY=y
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/86xx/gef_sbc310_defconfig b/arch/powerpc/configs/86xx/gef_sbc310_defconfig
index 1524d94..8e738de 100644
--- a/arch/powerpc/configs/86xx/gef_sbc310_defconfig
+++ b/arch/powerpc/configs/86xx/gef_sbc310_defconfig
@@ -103,8 +103,7 @@
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
CONFIG_RELAY=y
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/86xx/gef_sbc610_defconfig b/arch/powerpc/configs/86xx/gef_sbc610_defconfig
index 767c204..59bf9e2 100644
--- a/arch/powerpc/configs/86xx/gef_sbc610_defconfig
+++ b/arch/powerpc/configs/86xx/gef_sbc610_defconfig
@@ -103,8 +103,7 @@
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
CONFIG_RELAY=y
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
index 55b9e4e..4e8b01e 100644
--- a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
+++ b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
@@ -98,8 +98,7 @@
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig b/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig
index 1be38eb..20fde63 100644
--- a/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig
+++ b/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig
@@ -103,8 +103,7 @@
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/86xx/sbc8641d_defconfig b/arch/powerpc/configs/86xx/sbc8641d_defconfig
index a630094..74f714d 100644
--- a/arch/powerpc/configs/86xx/sbc8641d_defconfig
+++ b/arch/powerpc/configs/86xx/sbc8641d_defconfig
@@ -102,8 +102,7 @@
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
CONFIG_RELAY=y
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/adder875_defconfig b/arch/powerpc/configs/adder875_defconfig
index 9f89d5c..a670cee 100644
--- a/arch/powerpc/configs/adder875_defconfig
+++ b/arch/powerpc/configs/adder875_defconfig
@@ -92,8 +92,7 @@
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
# CONFIG_BLK_DEV_INITRD is not set
diff --git a/arch/powerpc/configs/amigaone_defconfig b/arch/powerpc/configs/amigaone_defconfig
index b63cc38..851287e 100644
--- a/arch/powerpc/configs/amigaone_defconfig
+++ b/arch/powerpc/configs/amigaone_defconfig
@@ -87,8 +87,7 @@
CONFIG_LOG_BUF_SHIFT=15
# CONFIG_GROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
diff --git a/arch/powerpc/configs/c2k_defconfig b/arch/powerpc/configs/c2k_defconfig
index 4ab6074..b429a65 100644
--- a/arch/powerpc/configs/c2k_defconfig
+++ b/arch/powerpc/configs/c2k_defconfig
@@ -102,8 +102,7 @@
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=17
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig
index c6d2baa..9433719 100644
--- a/arch/powerpc/configs/cell_defconfig
+++ b/arch/powerpc/configs/cell_defconfig
@@ -83,8 +83,7 @@
# CONFIG_CGROUP_SCHED is not set
# CONFIG_CGROUP_CPUACCT is not set
# CONFIG_RESOURCE_COUNTERS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
CONFIG_PROC_PID_CPUSET=y
# CONFIG_RELAY is not set
CONFIG_NAMESPACES=y
diff --git a/arch/powerpc/configs/celleb_defconfig b/arch/powerpc/configs/celleb_defconfig
index d212377..6be6c09 100644
--- a/arch/powerpc/configs/celleb_defconfig
+++ b/arch/powerpc/configs/celleb_defconfig
@@ -78,8 +78,7 @@
# CONFIG_GROUP_SCHED is not set
# CONFIG_USER_SCHED is not set
# CONFIG_CGROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
diff --git a/arch/powerpc/configs/chrp32_defconfig b/arch/powerpc/configs/chrp32_defconfig
index 5094a65..2fdab66 100644
--- a/arch/powerpc/configs/chrp32_defconfig
+++ b/arch/powerpc/configs/chrp32_defconfig
@@ -77,8 +77,7 @@
CONFIG_LOG_BUF_SHIFT=15
# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
diff --git a/arch/powerpc/configs/ep8248e_defconfig b/arch/powerpc/configs/ep8248e_defconfig
index 81e904e..6b70839 100644
--- a/arch/powerpc/configs/ep8248e_defconfig
+++ b/arch/powerpc/configs/ep8248e_defconfig
@@ -96,8 +96,7 @@
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
# CONFIG_BLK_DEV_INITRD is not set
diff --git a/arch/powerpc/configs/ep88xc_defconfig b/arch/powerpc/configs/ep88xc_defconfig
index c5af46e..1cee889 100644
--- a/arch/powerpc/configs/ep88xc_defconfig
+++ b/arch/powerpc/configs/ep88xc_defconfig
@@ -91,8 +91,7 @@
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
# CONFIG_BLK_DEV_INITRD is not set
diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig
index 826a65d..57d3ffa 100644
--- a/arch/powerpc/configs/g5_defconfig
+++ b/arch/powerpc/configs/g5_defconfig
@@ -82,8 +82,7 @@
CONFIG_LOG_BUF_SHIFT=17
# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
diff --git a/arch/powerpc/configs/gamecube_defconfig b/arch/powerpc/configs/gamecube_defconfig
index 942e119..1c2dbf0 100644
--- a/arch/powerpc/configs/gamecube_defconfig
+++ b/arch/powerpc/configs/gamecube_defconfig
@@ -101,8 +101,7 @@
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/holly_defconfig b/arch/powerpc/configs/holly_defconfig
index a211a79..a60d61b 100644
--- a/arch/powerpc/configs/holly_defconfig
+++ b/arch/powerpc/configs/holly_defconfig
@@ -73,7 +73,6 @@
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
# CONFIG_FAIR_GROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
diff --git a/arch/powerpc/configs/iseries_defconfig b/arch/powerpc/configs/iseries_defconfig
index 76982c5..151c8e1 100644
--- a/arch/powerpc/configs/iseries_defconfig
+++ b/arch/powerpc/configs/iseries_defconfig
@@ -81,8 +81,7 @@
CONFIG_LOG_BUF_SHIFT=17
# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
diff --git a/arch/powerpc/configs/linkstation_defconfig b/arch/powerpc/configs/linkstation_defconfig
index 588a2ad..8ecacf7 100644
--- a/arch/powerpc/configs/linkstation_defconfig
+++ b/arch/powerpc/configs/linkstation_defconfig
@@ -97,8 +97,7 @@
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig
index 8b24400..dc50eec 100644
--- a/arch/powerpc/configs/maple_defconfig
+++ b/arch/powerpc/configs/maple_defconfig
@@ -78,8 +78,7 @@
CONFIG_LOG_BUF_SHIFT=17
# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
diff --git a/arch/powerpc/configs/mgcoge_defconfig b/arch/powerpc/configs/mgcoge_defconfig
index 0cbd56f..b36ebb7 100644
--- a/arch/powerpc/configs/mgcoge_defconfig
+++ b/arch/powerpc/configs/mgcoge_defconfig
@@ -96,8 +96,7 @@
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/mgsuvd_defconfig b/arch/powerpc/configs/mgsuvd_defconfig
index c1be261..0dd5015 100644
--- a/arch/powerpc/configs/mgsuvd_defconfig
+++ b/arch/powerpc/configs/mgsuvd_defconfig
@@ -90,8 +90,7 @@
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=17
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/mpc512x_defconfig b/arch/powerpc/configs/mpc512x_defconfig
index a047272..aa2654e 100644
--- a/arch/powerpc/configs/mpc512x_defconfig
+++ b/arch/powerpc/configs/mpc512x_defconfig
@@ -97,8 +97,7 @@
CONFIG_LOG_BUF_SHIFT=16
# CONFIG_GROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
diff --git a/arch/powerpc/configs/mpc5200_defconfig b/arch/powerpc/configs/mpc5200_defconfig
index 7012ac0..f875ec2 100644
--- a/arch/powerpc/configs/mpc5200_defconfig
+++ b/arch/powerpc/configs/mpc5200_defconfig
@@ -97,8 +97,7 @@
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
diff --git a/arch/powerpc/configs/mpc7448_hpc2_defconfig b/arch/powerpc/configs/mpc7448_hpc2_defconfig
index 27c63ce..b1e88fe 100644
--- a/arch/powerpc/configs/mpc7448_hpc2_defconfig
+++ b/arch/powerpc/configs/mpc7448_hpc2_defconfig
@@ -95,8 +95,7 @@
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/pasemi_defconfig b/arch/powerpc/configs/pasemi_defconfig
index 20ba0cf..74a7216 100644
--- a/arch/powerpc/configs/pasemi_defconfig
+++ b/arch/powerpc/configs/pasemi_defconfig
@@ -98,8 +98,7 @@
CONFIG_LOG_BUF_SHIFT=17
# CONFIG_GROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig
index ea8870a..753bb791 100644
--- a/arch/powerpc/configs/pmac32_defconfig
+++ b/arch/powerpc/configs/pmac32_defconfig
@@ -93,8 +93,7 @@
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_GROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
diff --git a/arch/powerpc/configs/ppc40x_defconfig b/arch/powerpc/configs/ppc40x_defconfig
index 35b6068..afb4d1b 100644
--- a/arch/powerpc/configs/ppc40x_defconfig
+++ b/arch/powerpc/configs/ppc40x_defconfig
@@ -99,8 +99,7 @@
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/ppc44x_defconfig b/arch/powerpc/configs/ppc44x_defconfig
index 46f5c47..bd3d23f 100644
--- a/arch/powerpc/configs/ppc44x_defconfig
+++ b/arch/powerpc/configs/ppc44x_defconfig
@@ -103,8 +103,7 @@
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index dad617e..369f4e0 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -93,8 +93,7 @@
# CONFIG_GROUP_SCHED is not set
# CONFIG_CGROUP_CPUACCT is not set
# CONFIG_RESOURCE_COUNTERS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
CONFIG_PROC_PID_CPUSET=y
CONFIG_RELAY=y
CONFIG_NAMESPACES=y
diff --git a/arch/powerpc/configs/ppc64e_defconfig b/arch/powerpc/configs/ppc64e_defconfig
index 8195f16..403e82e 100644
--- a/arch/powerpc/configs/ppc64e_defconfig
+++ b/arch/powerpc/configs/ppc64e_defconfig
@@ -107,8 +107,7 @@
CONFIG_PROC_PID_CPUSET=y
# CONFIG_CGROUP_CPUACCT is not set
# CONFIG_RESOURCE_COUNTERS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
CONFIG_RELAY=y
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
diff --git a/arch/powerpc/configs/pq2fads_defconfig b/arch/powerpc/configs/pq2fads_defconfig
index 68c175e..12c8ee8 100644
--- a/arch/powerpc/configs/pq2fads_defconfig
+++ b/arch/powerpc/configs/pq2fads_defconfig
@@ -96,8 +96,7 @@
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/configs/prpmc2800_defconfig b/arch/powerpc/configs/prpmc2800_defconfig
index 93f4505..a18f597 100644
--- a/arch/powerpc/configs/prpmc2800_defconfig
+++ b/arch/powerpc/configs/prpmc2800_defconfig
@@ -98,8 +98,7 @@
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index 16a1458..16ae717 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -92,8 +92,7 @@
# CONFIG_GROUP_SCHED is not set
CONFIG_CGROUP_CPUACCT=y
# CONFIG_RESOURCE_COUNTERS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
CONFIG_PROC_PID_CPUSET=y
CONFIG_RELAY=y
CONFIG_NAMESPACES=y
diff --git a/arch/powerpc/configs/storcenter_defconfig b/arch/powerpc/configs/storcenter_defconfig
index b162580..01be0e2 100644
--- a/arch/powerpc/configs/storcenter_defconfig
+++ b/arch/powerpc/configs/storcenter_defconfig
@@ -95,8 +95,7 @@
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
# CONFIG_BLK_DEV_INITRD is not set
diff --git a/arch/powerpc/configs/wii_defconfig b/arch/powerpc/configs/wii_defconfig
index c386828..ee054f8 100644
--- a/arch/powerpc/configs/wii_defconfig
+++ b/arch/powerpc/configs/wii_defconfig
@@ -102,8 +102,7 @@
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
CONFIG_RELAY=y
# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h
index e054bae..ecba37a 100644
--- a/arch/powerpc/include/asm/irq.h
+++ b/arch/powerpc/include/asm/irq.h
@@ -358,7 +358,6 @@
#define exc_lvl_ctx_init()
#endif
-#ifdef CONFIG_IRQSTACKS
/*
* Per-cpu stacks for handling hard and soft interrupts.
*/
@@ -369,11 +368,6 @@
extern void call_do_softirq(struct thread_info *tp);
extern int call_handle_irq(int irq, void *p1,
struct thread_info *tp, void *func);
-#else
-#define irq_ctx_init()
-
-#endif /* CONFIG_IRQSTACKS */
-
extern void do_IRQ(struct pt_regs *regs);
#endif /* _ASM_IRQ_H */
diff --git a/arch/powerpc/include/asm/kdump.h b/arch/powerpc/include/asm/kdump.h
index 5ebfe5d..6857af5 100644
--- a/arch/powerpc/include/asm/kdump.h
+++ b/arch/powerpc/include/asm/kdump.h
@@ -3,8 +3,17 @@
#include <asm/page.h>
-/* Kdump kernel runs at 32 MB, change at your peril. */
+/*
+ * If CONFIG_RELOCATABLE is enabled we can place the kdump kernel anywhere.
+ * To keep enough space in the RMO for the first stage kernel on 64bit, we
+ * place it at 64MB. If CONFIG_RELOCATABLE is not enabled we must place
+ * the second stage at 32MB.
+ */
+#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_PPC64)
+#define KDUMP_KERNELBASE 0x4000000
+#else
#define KDUMP_KERNELBASE 0x2000000
+#endif
/* How many bytes to reserve at zero for kdump. The reserve limit should
* be greater or equal to the trampoline's end address.
diff --git a/arch/powerpc/include/asm/macio.h b/arch/powerpc/include/asm/macio.h
index 19a661b..675e159 100644
--- a/arch/powerpc/include/asm/macio.h
+++ b/arch/powerpc/include/asm/macio.h
@@ -123,10 +123,6 @@
*/
struct macio_driver
{
- char *name;
- struct of_device_id *match_table;
- struct module *owner;
-
int (*probe)(struct macio_dev* dev, const struct of_device_id *match);
int (*remove)(struct macio_dev* dev);
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 30817d9..3333bbd 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -317,7 +317,6 @@
}
#endif
-#ifdef CONFIG_IRQSTACKS
static inline void handle_one_irq(unsigned int irq)
{
struct thread_info *curtp, *irqtp;
@@ -358,12 +357,6 @@
if (irqtp->flags)
set_bits(irqtp->flags, &curtp->flags);
}
-#else
-static inline void handle_one_irq(unsigned int irq)
-{
- generic_handle_irq(irq);
-}
-#endif
static inline void check_stack_overflow(void)
{
@@ -455,7 +448,6 @@
}
#endif
-#ifdef CONFIG_IRQSTACKS
struct thread_info *softirq_ctx[NR_CPUS] __read_mostly;
struct thread_info *hardirq_ctx[NR_CPUS] __read_mostly;
@@ -492,10 +484,6 @@
irqtp->task = NULL;
}
-#else
-#define do_softirq_onstack() __do_softirq()
-#endif /* CONFIG_IRQSTACKS */
-
void do_softirq(void)
{
unsigned long flags;
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index c533525..bc47352 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -378,17 +378,6 @@
* single-stepped a copy of the instruction. The address of this
* copy is p->ainsn.insn.
*/
-static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
-{
- int ret;
- unsigned int insn = *p->ainsn.insn;
-
- regs->nip = (unsigned long)p->addr;
- ret = emulate_step(regs, insn);
- if (ret == 0)
- regs->nip = (unsigned long)p->addr + 4;
-}
-
static int __kprobes post_kprobe_handler(struct pt_regs *regs)
{
struct kprobe *cur = kprobe_running();
@@ -406,7 +395,8 @@
cur->post_handler(cur, regs, 0);
}
- resume_execution(cur, regs);
+ /* Adjust nip to after the single-stepped instruction */
+ regs->nip = (unsigned long)cur->addr + 4;
regs->msr |= kcb->kprobe_saved_msr;
/*Restore back the original saved kprobes variables and continue. */
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c
index 26f9900..ed31a29 100644
--- a/arch/powerpc/kernel/machine_kexec_64.c
+++ b/arch/powerpc/kernel/machine_kexec_64.c
@@ -182,28 +182,12 @@
my_cpu = get_cpu();
/* Make sure each CPU has atleast made it to the state we need */
- for (i=0; i < NR_CPUS; i++) {
+ for_each_online_cpu(i) {
if (i == my_cpu)
continue;
while (paca[i].kexec_state < wait_state) {
barrier();
- if (!cpu_possible(i)) {
- printk("kexec: cpu %d hw_cpu_id %d is not"
- " possible, ignoring\n",
- i, paca[i].hw_cpu_id);
- break;
- }
- if (!cpu_online(i)) {
- /* Fixme: this can be spinning in
- * pSeries_secondary_wait with a paca
- * waiting for it to go online.
- */
- printk("kexec: cpu %d hw_cpu_id %d is not"
- " online, ignoring\n",
- i, paca[i].hw_cpu_id);
- break;
- }
if (i != notified) {
printk( "kexec: waiting for cpu %d (physical"
" %d) to enter %i state\n",
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index dc66d52..6bbd7a6 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -33,7 +33,6 @@
.text
-#ifdef CONFIG_IRQSTACKS
_GLOBAL(call_do_softirq)
mflr r0
stw r0,4(r1)
@@ -56,7 +55,6 @@
lwz r0,4(r1)
mtlr r0
blr
-#endif /* CONFIG_IRQSTACKS */
/*
* This returns the high 64 bits of the product of two 64-bit numbers.
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index a2b18df..e514490 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -28,7 +28,6 @@
.text
-#ifdef CONFIG_IRQSTACKS
_GLOBAL(call_do_softirq)
mflr r0
std r0,16(r1)
@@ -52,7 +51,6 @@
ld r0,16(r1)
mtlr r0
blr
-#endif /* CONFIG_IRQSTACKS */
.section ".toc","aw"
PPC64_CACHES:
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 6646005..5b38f6a 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -1309,6 +1309,7 @@
printk(KERN_WARNING "PCI: Cannot allocate resource region "
"%d of PCI bridge %d, will remap\n", i, bus->number);
clear_resource:
+ res->start = res->end = 0;
res->flags = 0;
}
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 9d255b4..773424d 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1005,7 +1005,6 @@
return error;
}
-#ifdef CONFIG_IRQSTACKS
static inline int valid_irq_stack(unsigned long sp, struct task_struct *p,
unsigned long nbytes)
{
@@ -1030,10 +1029,6 @@
return 0;
}
-#else
-#define valid_irq_stack(sp, p, nb) 0
-#endif /* CONFIG_IRQSTACKS */
-
int validate_sp(unsigned long sp, struct task_struct *p,
unsigned long nbytes)
{
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
index bfc2aba..67a84d8 100644
--- a/arch/powerpc/kernel/rtas_flash.c
+++ b/arch/powerpc/kernel/rtas_flash.c
@@ -94,12 +94,8 @@
struct flash_block_list *next;
struct flash_block blocks[FLASH_BLOCKS_PER_NODE];
};
-struct flash_block_list_header { /* just the header of flash_block_list */
- unsigned long num_blocks;
- struct flash_block_list *next;
-};
-static struct flash_block_list_header rtas_firmware_flash_list = {0, NULL};
+static struct flash_block_list *rtas_firmware_flash_list;
/* Use slab cache to guarantee 4k alignment */
static struct kmem_cache *flash_block_cache = NULL;
@@ -108,13 +104,14 @@
/* Local copy of the flash block list.
* We only allow one open of the flash proc file and create this
- * list as we go. This list will be put in the
- * rtas_firmware_flash_list var once it is fully read.
+ * list as we go. The rtas_firmware_flash_list varable will be
+ * set once the data is fully read.
*
* For convenience as we build the list we use virtual addrs,
* we do not fill in the version number, and the length field
* is treated as the number of entries currently in the block
- * (i.e. not a byte count). This is all fixed on release.
+ * (i.e. not a byte count). This is all fixed when calling
+ * the flash routine.
*/
/* Status int must be first member of struct */
@@ -201,16 +198,16 @@
if (uf->flist) {
/* File was opened in write mode for a new flash attempt */
/* Clear saved list */
- if (rtas_firmware_flash_list.next) {
- free_flash_list(rtas_firmware_flash_list.next);
- rtas_firmware_flash_list.next = NULL;
+ if (rtas_firmware_flash_list) {
+ free_flash_list(rtas_firmware_flash_list);
+ rtas_firmware_flash_list = NULL;
}
if (uf->status != FLASH_AUTH)
uf->status = flash_list_valid(uf->flist);
if (uf->status == FLASH_IMG_READY)
- rtas_firmware_flash_list.next = uf->flist;
+ rtas_firmware_flash_list = uf->flist;
else
free_flash_list(uf->flist);
@@ -593,7 +590,7 @@
unsigned long rtas_block_list;
int i, status, update_token;
- if (rtas_firmware_flash_list.next == NULL)
+ if (rtas_firmware_flash_list == NULL)
return; /* nothing to do */
if (reboot_type != SYS_RESTART) {
@@ -610,20 +607,25 @@
return;
}
- /* NOTE: the "first" block list is a global var with no data
- * blocks in the kernel data segment. We do this because
- * we want to ensure this block_list addr is under 4GB.
+ /*
+ * NOTE: the "first" block must be under 4GB, so we create
+ * an entry with no data blocks in the reserved buffer in
+ * the kernel data segment.
*/
- rtas_firmware_flash_list.num_blocks = 0;
- flist = (struct flash_block_list *)&rtas_firmware_flash_list;
+ spin_lock(&rtas_data_buf_lock);
+ flist = (struct flash_block_list *)&rtas_data_buf[0];
+ flist->num_blocks = 0;
+ flist->next = rtas_firmware_flash_list;
rtas_block_list = virt_to_abs(flist);
if (rtas_block_list >= 4UL*1024*1024*1024) {
printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n");
+ spin_unlock(&rtas_data_buf_lock);
return;
}
printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n");
/* Update the block_list in place. */
+ rtas_firmware_flash_list = NULL; /* too hard to backout on error */
image_size = 0;
for (f = flist; f; f = next) {
/* Translate data addrs to absolute */
@@ -664,6 +666,7 @@
printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status);
break;
}
+ spin_unlock(&rtas_data_buf_lock);
}
static void remove_flash_pde(struct proc_dir_entry *dp)
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 8f58986..7d84b21 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -241,7 +241,6 @@
arch_initcall(ppc_init);
-#ifdef CONFIG_IRQSTACKS
static void __init irqstack_early_init(void)
{
unsigned int i;
@@ -255,9 +254,6 @@
__va(lmb_alloc(THREAD_SIZE, THREAD_SIZE));
}
}
-#else
-#define irqstack_early_init()
-#endif
#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
static void __init exc_lvl_early_init(void)
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index f3fb5a7..643dcac 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -432,7 +432,6 @@
return 1UL << SID_SHIFT;
}
-#ifdef CONFIG_IRQSTACKS
static void __init irqstack_early_init(void)
{
u64 limit = slb0_limit();
@@ -451,9 +450,6 @@
THREAD_SIZE, limit));
}
}
-#else
-#define irqstack_early_init()
-#endif
#ifdef CONFIG_PPC_BOOK3E
static void __init exc_lvl_early_init(void)
diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c
index bc2b400..e8a00b0 100644
--- a/arch/powerpc/kvm/e500.c
+++ b/arch/powerpc/kvm/e500.c
@@ -164,7 +164,7 @@
return kvm_init(NULL, sizeof(struct kvmppc_vcpu_e500), 0, THIS_MODULE);
}
-static void __init kvmppc_e500_exit(void)
+static void __exit kvmppc_e500_exit(void)
{
kvmppc_booke_exit();
}
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index 9fc02dc..34347b2 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -115,11 +115,7 @@
{
struct page *ptepage;
-#ifdef CONFIG_HIGHPTE
- gfp_t flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_REPEAT | __GFP_ZERO;
-#else
gfp_t flags = GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO;
-#endif
ptepage = alloc_pages(flags, 0);
if (!ptepage)
diff --git a/arch/powerpc/oprofile/op_model_cell.c b/arch/powerpc/oprofile/op_model_cell.c
index 2c9e522..7fd90d0 100644
--- a/arch/powerpc/oprofile/op_model_cell.c
+++ b/arch/powerpc/oprofile/op_model_cell.c
@@ -1077,7 +1077,7 @@
index = ENTRIES-1;
/* make sure index is valid */
- if ((index > ENTRIES) || (index < 0))
+ if ((index >= ENTRIES) || (index < 0))
index = ENTRIES-1;
return initial_lfsr[index];
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pm.c b/arch/powerpc/platforms/52xx/mpc52xx_pm.c
index a55b0b6..7672253 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pm.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pm.c
@@ -64,10 +64,19 @@
{ .type = "builtin", .compatible = "mpc5200", }, /* efika */
{}
};
+ struct resource res;
/* map the whole register space */
np = of_find_matching_node(NULL, immr_ids);
- mbar = of_iomap(np, 0);
+
+ if (of_address_to_resource(np, 0, &res)) {
+ pr_err("mpc52xx_pm_prepare(): could not get IMMR address\n");
+ of_node_put(np);
+ return -ENOSYS;
+ }
+
+ mbar = ioremap(res.start, 0xc000); /* we should map whole region including SRAM */
+
of_node_put(np);
if (!mbar) {
pr_err("mpc52xx_pm_prepare(): could not map registers\n");
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index 22667a0..4326b73 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -1066,7 +1066,7 @@
fbase = _ALIGN_UP(fbase, 1 << IO_SEGMENT_SHIFT);
fsize = lmb_phys_mem_size();
- if ((fbase + fsize) <= 0x800000000)
+ if ((fbase + fsize) <= 0x800000000ul)
hbase = 0; /* use the device tree window */
else {
/* If we're over 32 GB we need to cheat. We can't map all of
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 0f5bee9..962c2d8 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -347,7 +347,7 @@
goto error_out;
}
offset = 0;
- p = of_get_property(dev->node, "msi-available-ranges", &len);
+ p = of_get_property(dev->dev.of_node, "msi-available-ranges", &len);
if (p)
offset = *p / IRQS_PER_MSI_REG;
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index cd37e49..30e1626 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -1426,7 +1426,7 @@
port->iores.flags = IORESOURCE_MEM;
port->iores.name = "rio_io_win";
- priv->pwirq = irq_of_parse_and_map(dev->node, 0);
+ priv->pwirq = irq_of_parse_and_map(dev->dev.of_node, 0);
priv->bellirq = irq_of_parse_and_map(dev->dev.of_node, 2);
priv->txirq = irq_of_parse_and_map(dev->dev.of_node, 3);
priv->rxirq = irq_of_parse_and_map(dev->dev.of_node, 4);
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 2102487..20b73c0 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -1666,7 +1666,7 @@
mpic->save_data[i].dest);
#ifdef CONFIG_MPIC_U3_HT_IRQS
- {
+ if (mpic->fixups) {
struct mpic_irq_fixup *fixup = &mpic->fixups[i];
if (fixup->base) {
diff --git a/arch/s390/appldata/appldata_os.c b/arch/s390/appldata/appldata_os.c
index 55c80ffd..92f1cb7 100644
--- a/arch/s390/appldata/appldata_os.c
+++ b/arch/s390/appldata/appldata_os.c
@@ -181,7 +181,7 @@
goto out;
}
- appldata_os_data = kzalloc(max_size, GFP_DMA);
+ appldata_os_data = kzalloc(max_size, GFP_KERNEL | GFP_DMA);
if (appldata_os_data == NULL) {
rc = -ENOMEM;
goto out;
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index bcd6884..253f158 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.34-rc3
-# Fri Apr 9 09:57:10 2010
+# Linux kernel version: 2.6.35-rc1
+# Fri Jun 4 11:32:40 2010
#
CONFIG_SCHED_MC=y
CONFIG_MMU=y
@@ -35,11 +35,13 @@
CONFIG_EXPERIMENTAL=y
CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_HAVE_KERNEL_GZIP=y
CONFIG_HAVE_KERNEL_BZIP2=y
CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_LZO=y
CONFIG_KERNEL_GZIP=y
# CONFIG_KERNEL_BZIP2 is not set
# CONFIG_KERNEL_LZMA is not set
@@ -77,6 +79,7 @@
# CONFIG_CGROUP_CPUACCT is not set
# CONFIG_RESOURCE_COUNTERS is not set
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_BLK_CGROUP is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -157,7 +160,6 @@
CONFIG_BLOCK=y
CONFIG_BLK_DEV_BSG=y
# CONFIG_BLK_DEV_INTEGRITY is not set
-# CONFIG_BLK_CGROUP is not set
CONFIG_BLOCK_COMPAT=y
#
@@ -166,7 +168,6 @@
CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
-# CONFIG_CFQ_GROUP_IOSCHED is not set
CONFIG_DEFAULT_DEADLINE=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
@@ -247,7 +248,6 @@
CONFIG_SMP=y
CONFIG_NR_CPUS=32
CONFIG_HOTPLUG_CPU=y
-# CONFIG_SCHED_BOOK is not set
CONFIG_COMPAT=y
CONFIG_SYSVIPC_COMPAT=y
CONFIG_AUDIT_ARCH=y
@@ -320,7 +320,6 @@
# CONFIG_HAVE_AOUT is not set
CONFIG_BINFMT_MISC=m
CONFIG_FORCE_MAX_ZONEORDER=9
-# CONFIG_PROCESS_DEBUG is not set
CONFIG_PFAULT=y
# CONFIG_SHARED_KERNEL is not set
# CONFIG_CMM is not set
@@ -457,6 +456,7 @@
# CONFIG_IP6_NF_IPTABLES is not set
# CONFIG_IP_DCCP is not set
CONFIG_IP_SCTP=m
+# CONFIG_NET_SCTPPROBE is not set
# CONFIG_SCTP_DBG_MSG is not set
# CONFIG_SCTP_DBG_OBJCNT is not set
# CONFIG_SCTP_HMAC_NONE is not set
@@ -465,6 +465,7 @@
# CONFIG_RDS is not set
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
# CONFIG_BRIDGE is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
@@ -525,6 +526,7 @@
# CONFIG_NET_CLS_IND is not set
CONFIG_NET_SCH_FIFO=y
# CONFIG_DCB is not set
+CONFIG_RPS=y
#
# Network testing
@@ -546,6 +548,7 @@
# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
# CONFIG_PCMCIA is not set
CONFIG_CCW=y
@@ -728,6 +731,7 @@
# Character devices
#
CONFIG_DEVKMEM=y
+# CONFIG_N_GSM is not set
CONFIG_UNIX98_PTYS=y
# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
@@ -775,6 +779,7 @@
# CONFIG_MONREADER is not set
CONFIG_MONWRITER=m
CONFIG_S390_VMUR=m
+# CONFIG_RAMOOPS is not set
#
# PPS support
@@ -788,10 +793,6 @@
# CONFIG_NEW_LEDS is not set
CONFIG_ACCESSIBILITY=y
# CONFIG_AUXDISPLAY is not set
-
-#
-# TI VLYNQ
-#
# CONFIG_STAGING is not set
#
@@ -976,6 +977,7 @@
# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y
# CONFIG_LKDTM is not set
+# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
@@ -1010,6 +1012,7 @@
CONFIG_KPROBE_EVENT=y
# CONFIG_RING_BUFFER_BENCHMARK is not set
# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
CONFIG_SAMPLES=y
# CONFIG_SAMPLE_TRACEPOINTS is not set
# CONFIG_SAMPLE_TRACE_EVENTS is not set
diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c
index 639380a..22cfd63 100644
--- a/arch/s390/kernel/module.c
+++ b/arch/s390/kernel/module.c
@@ -55,8 +55,10 @@
/* Free memory returned from module_alloc */
void module_free(struct module *mod, void *module_region)
{
- vfree(mod->arch.syminfo);
- mod->arch.syminfo = NULL;
+ if (mod) {
+ vfree(mod->arch.syminfo);
+ mod->arch.syminfo = NULL;
+ }
vfree(module_region);
}
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 8093e6f..ae37058 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -761,7 +761,7 @@
* to hold the maximum amount of facilites. On the other hand, we
* only set facilities that are known to work in KVM.
*/
- facilities = (unsigned long long *) get_zeroed_page(GFP_DMA);
+ facilities = (unsigned long long *) get_zeroed_page(GFP_KERNEL|GFP_DMA);
if (!facilities) {
kvm_exit();
return -ENOMEM;
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c
index eff3c59..702276f 100644
--- a/arch/s390/kvm/sigp.c
+++ b/arch/s390/kvm/sigp.c
@@ -113,7 +113,7 @@
{
struct kvm_s390_interrupt_info *inti;
- inti = kzalloc(sizeof(*inti), GFP_KERNEL);
+ inti = kzalloc(sizeof(*inti), GFP_ATOMIC);
if (!inti)
return -ENOMEM;
inti->type = KVM_S390_SIGP_STOP;
diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c
index 6409fd5..3cc95dd 100644
--- a/arch/s390/mm/extmem.c
+++ b/arch/s390/mm/extmem.c
@@ -105,7 +105,7 @@
dcss_set_subcodes(void)
{
#ifdef CONFIG_64BIT
- char *name = kmalloc(8 * sizeof(char), GFP_DMA);
+ char *name = kmalloc(8 * sizeof(char), GFP_KERNEL | GFP_DMA);
unsigned long rx, ry;
int rc;
@@ -252,12 +252,13 @@
static int
query_segment_type (struct dcss_segment *seg)
{
- struct qin64 *qin = kmalloc (sizeof(struct qin64), GFP_DMA);
- struct qout64 *qout = kmalloc (sizeof(struct qout64), GFP_DMA);
-
- int diag_cc, rc, i;
unsigned long dummy, vmrc;
+ int diag_cc, rc, i;
+ struct qout64 *qout;
+ struct qin64 *qin;
+ qin = kmalloc(sizeof(*qin), GFP_KERNEL | GFP_DMA);
+ qout = kmalloc(sizeof(*qout), GFP_KERNEL | GFP_DMA);
if ((qin == NULL) || (qout == NULL)) {
rc = -ENOMEM;
goto out_free;
@@ -286,7 +287,7 @@
copy data for the new format. */
if (segext_scode == DCSS_SEGEXT) {
struct qout64_old *qout_old;
- qout_old = kzalloc(sizeof(struct qout64_old), GFP_DMA);
+ qout_old = kzalloc(sizeof(*qout_old), GFP_KERNEL | GFP_DMA);
if (qout_old == NULL) {
rc = -ENOMEM;
goto out_free;
@@ -407,11 +408,11 @@
static int
__segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long *end)
{
- struct dcss_segment *seg = kmalloc(sizeof(struct dcss_segment),
- GFP_DMA);
- int rc, diag_cc;
unsigned long start_addr, end_addr, dummy;
+ struct dcss_segment *seg;
+ int rc, diag_cc;
+ seg = kmalloc(sizeof(*seg), GFP_KERNEL | GFP_DMA);
if (seg == NULL) {
rc = -ENOMEM;
goto out;
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index c5ee4ce..573fca1 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -9,7 +9,7 @@
def_bool y
select EMBEDDED
select HAVE_CLK
- select HAVE_IDE
+ select HAVE_IDE if HAS_IOPORT
select HAVE_LMB
select HAVE_OPROFILE
select HAVE_GENERIC_DMA_COHERENT
@@ -174,6 +174,9 @@
config ARCH_HAS_CPU_IDLE_WAIT
def_bool y
+config NO_IOPORT
+ bool
+
config IO_TRAPPED
bool
@@ -776,6 +779,17 @@
default "0x00010000" if PAGE_SIZE_64KB
default "0x00000000"
+config ROMIMAGE_MMCIF
+ bool "Include MMCIF loader in romImage (EXPERIMENTAL)"
+ depends on CPU_SUBTYPE_SH7724 && EXPERIMENTAL
+ help
+ Say Y here to include experimental MMCIF loading code in
+ romImage. With this enabled it is possible to write the romImage
+ kernel image to an MMC card and boot the kernel straight from
+ the reset vector. At reset the processor Mask ROM will load the
+ first part of the romImage which in turn loads the rest the kernel
+ image to RAM using the MMCIF hardware block.
+
choice
prompt "Kernel command line"
optional
diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig
index 938e87d..07b35ca 100644
--- a/arch/sh/boards/Kconfig
+++ b/arch/sh/boards/Kconfig
@@ -154,6 +154,7 @@
bool "SDK7786"
depends on CPU_SUBTYPE_SH7786
select SYS_SUPPORTS_PCI
+ select NO_IOPORT if !PCI
help
Select SDK7786 if configuring for a Renesas Technology Europe
SH7786-65nm board.
@@ -190,6 +191,7 @@
depends on CPU_SUBTYPE_SH7786
select ARCH_REQUIRE_GPIOLIB
select SYS_SUPPORTS_PCI
+ select NO_IOPORT if !PCI
config SH_MIGOR
bool "Migo-R"
@@ -286,6 +288,7 @@
config SH_X3PROTO
bool "SH-X3 Prototype board"
depends on CPU_SUBTYPE_SHX3
+ select NO_IOPORT if !PCI
config SH_MAGIC_PANEL_R2
bool "Magic Panel R2"
diff --git a/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c
index 57e37e2..3a170bd 100644
--- a/arch/sh/boards/mach-ap325rxa/setup.c
+++ b/arch/sh/boards/mach-ap325rxa/setup.c
@@ -328,7 +328,7 @@
.set_capture = camera_set_capture,
};
-struct soc_camera_link camera_link = {
+static struct soc_camera_link camera_link = {
.bus_id = 0,
.add_device = ap325rxa_camera_add,
.del_device = ap325rxa_camera_del,
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index 4971425..1d7b495 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -12,6 +12,8 @@
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/mfd/sh_mobile_sdhi.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sh_mmcif.h>
#include <linux/mtd/physmap.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
@@ -23,10 +25,8 @@
#include <linux/spi/spi.h>
#include <linux/spi/sh_msiof.h>
#include <linux/spi/mmc_spi.h>
-#include <linux/mmc/host.h>
#include <linux/input.h>
#include <linux/input/sh_keysc.h>
-#include <linux/mfd/sh_mobile_sdhi.h>
#include <video/sh_mobile_lcdc.h>
#include <sound/sh_fsi.h>
#include <media/sh_mobile_ceu.h>
@@ -139,7 +139,7 @@
},
};
-struct sh_eth_plat_data sh_eth_plat = {
+static struct sh_eth_plat_data sh_eth_plat = {
.phy = 0x1f, /* SMSC LAN8700 */
.edmac_endian = EDMAC_LITTLE_ENDIAN,
.ether_link_active_low = 1
@@ -159,7 +159,7 @@
};
/* USB0 host */
-void usb0_port_power(int port, int power)
+static void usb0_port_power(int port, int power)
{
gpio_set_value(GPIO_PTB4, power);
}
@@ -195,7 +195,7 @@
};
/* USB1 host/function */
-void usb1_port_power(int port, int power)
+static void usb1_port_power(int port, int power)
{
gpio_set_value(GPIO_PTB5, power);
}
@@ -421,7 +421,7 @@
return 0;
}
-struct tsc2007_platform_data tsc2007_info = {
+static struct tsc2007_platform_data tsc2007_info = {
.model = 2007,
.x_plate_ohms = 180,
.get_pendown_state = ts_get_pendown_state,
@@ -436,7 +436,7 @@
};
#ifdef CONFIG_MFD_SH_MOBILE_SDHI
-/* SHDI0 */
+/* SDHI0 */
static void sdhi0_set_pwr(struct platform_device *pdev, int state)
{
gpio_set_value(GPIO_PTB6, state);
@@ -474,7 +474,8 @@
},
};
-/* SHDI1 */
+#if !defined(CONFIG_MMC_SH_MMCIF)
+/* SDHI1 */
static void sdhi1_set_pwr(struct platform_device *pdev, int state)
{
gpio_set_value(GPIO_PTB7, state);
@@ -511,6 +512,7 @@
.hwblk_id = HWBLK_SDHI1,
},
};
+#endif /* CONFIG_MMC_SH_MMCIF */
#else
@@ -720,7 +722,7 @@
.rate = 0, /* unknown */
};
-struct sh_fsi_platform_info fsi_info = {
+static struct sh_fsi_platform_info fsi_info = {
.portb_flags = SH_FSI_BRS_INV |
SH_FSI_OUT_SLAVE_MODE |
SH_FSI_IN_SLAVE_MODE |
@@ -777,7 +779,7 @@
#include <media/ak881x.h>
#include <media/sh_vou.h>
-struct ak881x_pdata ak881x_pdata = {
+static struct ak881x_pdata ak881x_pdata = {
.flags = AK881X_IF_MODE_SLAVE,
};
@@ -786,7 +788,7 @@
.platform_data = &ak881x_pdata,
};
-struct sh_vou_pdata sh_vou_pdata = {
+static struct sh_vou_pdata sh_vou_pdata = {
.bus_fmt = SH_VOU_BUS_8BIT,
.flags = SH_VOU_HSYNC_LOW | SH_VOU_VSYNC_LOW,
.board_info = &ak8813,
@@ -819,6 +821,58 @@
},
};
+#if defined(CONFIG_MMC_SH_MMCIF)
+/* SH_MMCIF */
+static void mmcif_set_pwr(struct platform_device *pdev, int state)
+{
+ gpio_set_value(GPIO_PTB7, state);
+}
+
+static void mmcif_down_pwr(struct platform_device *pdev)
+{
+ gpio_set_value(GPIO_PTB7, 0);
+}
+
+static struct resource sh_mmcif_resources[] = {
+ [0] = {
+ .name = "SH_MMCIF",
+ .start = 0xA4CA0000,
+ .end = 0xA4CA00FF,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* MMC2I */
+ .start = 29,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ /* MMC3I */
+ .start = 30,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct sh_mmcif_plat_data sh_mmcif_plat = {
+ .set_pwr = mmcif_set_pwr,
+ .down_pwr = mmcif_down_pwr,
+ .sup_pclk = 0, /* SH7724: Max Pclk/2 */
+ .caps = MMC_CAP_4_BIT_DATA |
+ MMC_CAP_8_BIT_DATA |
+ MMC_CAP_NEEDS_POLL,
+ .ocr = MMC_VDD_32_33 | MMC_VDD_33_34,
+};
+
+static struct platform_device sh_mmcif_device = {
+ .name = "sh_mmcif",
+ .id = 0,
+ .dev = {
+ .platform_data = &sh_mmcif_plat,
+ },
+ .num_resources = ARRAY_SIZE(sh_mmcif_resources),
+ .resource = sh_mmcif_resources,
+};
+#endif
+
static struct platform_device *ecovec_devices[] __initdata = {
&heartbeat_device,
&nor_flash_device,
@@ -831,7 +885,9 @@
&keysc_device,
#ifdef CONFIG_MFD_SH_MOBILE_SDHI
&sdhi0_device,
+#if !defined(CONFIG_MMC_SH_MMCIF)
&sdhi1_device,
+#endif
#else
&msiof0_device,
#endif
@@ -841,6 +897,9 @@
&fsi_device,
&irda_device,
&vou_device,
+#if defined(CONFIG_MMC_SH_MMCIF)
+ &sh_mmcif_device,
+#endif
};
#ifdef CONFIG_I2C
@@ -1134,6 +1193,7 @@
gpio_request(GPIO_PTB6, NULL);
gpio_direction_output(GPIO_PTB6, 0);
+#if !defined(CONFIG_MMC_SH_MMCIF)
/* enable SDHI1 on CN12 (needs DS2.6,7 set to ON,OFF) */
gpio_request(GPIO_FN_SDHI1CD, NULL);
gpio_request(GPIO_FN_SDHI1WP, NULL);
@@ -1148,6 +1208,7 @@
/* I/O buffer drive ability is high for SDHI1 */
__raw_writew((__raw_readw(IODRIVEA) & ~0x3000) | 0x2000 , IODRIVEA);
+#endif /* CONFIG_MMC_SH_MMCIF */
#else
/* enable MSIOF0 on CN11 (needs DS2.4 set to OFF) */
gpio_request(GPIO_FN_MSIOF0_TXD, NULL);
@@ -1223,6 +1284,25 @@
gpio_request(GPIO_PTU5, NULL);
gpio_direction_output(GPIO_PTU5, 0);
+#if defined(CONFIG_MMC_SH_MMCIF)
+ /* enable MMCIF (needs DS2.6,7 set to OFF,ON) */
+ gpio_request(GPIO_FN_MMC_D7, NULL);
+ gpio_request(GPIO_FN_MMC_D6, NULL);
+ gpio_request(GPIO_FN_MMC_D5, NULL);
+ gpio_request(GPIO_FN_MMC_D4, NULL);
+ gpio_request(GPIO_FN_MMC_D3, NULL);
+ gpio_request(GPIO_FN_MMC_D2, NULL);
+ gpio_request(GPIO_FN_MMC_D1, NULL);
+ gpio_request(GPIO_FN_MMC_D0, NULL);
+ gpio_request(GPIO_FN_MMC_CLK, NULL);
+ gpio_request(GPIO_FN_MMC_CMD, NULL);
+ gpio_request(GPIO_PTB7, NULL);
+ gpio_direction_output(GPIO_PTB7, 0);
+
+ /* I/O buffer drive ability is high for MMCIF */
+ __raw_writew((__raw_readw(IODRIVEA) & ~0x3000) | 0x2000 , IODRIVEA);
+#endif
+
/* enable I2C device */
i2c_register_board_info(0, i2c0_devices,
ARRAY_SIZE(i2c0_devices));
diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
index 87185de..662debe 100644
--- a/arch/sh/boards/mach-migor/setup.c
+++ b/arch/sh/boards/mach-migor/setup.c
@@ -181,7 +181,7 @@
return gpio_get_value(GPIO_PTA1); /* NAND_RBn */
}
-struct platform_nand_data migor_nand_flash_data = {
+static struct platform_nand_data migor_nand_flash_data = {
.chip = {
.nr_chips = 1,
.partitions = migor_nand_flash_partitions,
diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c
index f9b8254..552ebd9 100644
--- a/arch/sh/boards/mach-se/7724/setup.c
+++ b/arch/sh/boards/mach-se/7724/setup.c
@@ -283,7 +283,7 @@
};
/* change J20, J21, J22 pin to 1-2 connection to use slave mode */
-struct sh_fsi_platform_info fsi_info = {
+static struct sh_fsi_platform_info fsi_info = {
.porta_flags = SH_FSI_BRS_INV |
SH_FSI_OUT_SLAVE_MODE |
SH_FSI_IN_SLAVE_MODE |
@@ -371,7 +371,7 @@
},
};
-struct sh_eth_plat_data sh_eth_plat = {
+static struct sh_eth_plat_data sh_eth_plat = {
.phy = 0x1f, /* SMSC LAN8187 */
.edmac_endian = EDMAC_LITTLE_ENDIAN,
};
@@ -535,7 +535,7 @@
#include <media/ak881x.h>
#include <media/sh_vou.h>
-struct ak881x_pdata ak881x_pdata = {
+static struct ak881x_pdata ak881x_pdata = {
.flags = AK881X_IF_MODE_SLAVE,
};
@@ -545,7 +545,7 @@
.platform_data = &ak881x_pdata,
};
-struct sh_vou_pdata sh_vou_pdata = {
+static struct sh_vou_pdata sh_vou_pdata = {
.bus_fmt = SH_VOU_BUS_8BIT,
.flags = SH_VOU_HSYNC_LOW | SH_VOU_VSYNC_LOW,
.board_info = &ak8813,
diff --git a/arch/sh/boot/romimage/Makefile b/arch/sh/boot/romimage/Makefile
index f473a24..2216ee5 100644
--- a/arch/sh/boot/romimage/Makefile
+++ b/arch/sh/boot/romimage/Makefile
@@ -1,16 +1,21 @@
#
# linux/arch/sh/boot/romimage/Makefile
#
-# create an image suitable for burning to flash from zImage
+# create an romImage file suitable for burning to flash/mmc from zImage
#
targets := vmlinux head.o zeropage.bin piggy.o
+load-y := 0
-OBJECTS = $(obj)/head.o
-LDFLAGS_vmlinux := --oformat $(ld-bfd) -Ttext 0 -e romstart \
+mmcif-load-$(CONFIG_CPU_SUBTYPE_SH7724) := 0xe5200000 # ILRAM
+mmcif-obj-$(CONFIG_CPU_SUBTYPE_SH7724) := $(obj)/mmcif-sh7724.o
+load-$(CONFIG_ROMIMAGE_MMCIF) := $(mmcif-load-y)
+obj-$(CONFIG_ROMIMAGE_MMCIF) := $(mmcif-obj-y)
+
+LDFLAGS_vmlinux := --oformat $(ld-bfd) -Ttext $(load-y) -e romstart \
-T $(obj)/../../kernel/vmlinux.lds
-$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE
+$(obj)/vmlinux: $(obj)/head.o $(obj-y) $(obj)/piggy.o FORCE
$(call if_changed,ld)
@:
diff --git a/arch/sh/boot/romimage/head.S b/arch/sh/boot/romimage/head.S
index 93e779a..4671d1b 100644
--- a/arch/sh/boot/romimage/head.S
+++ b/arch/sh/boot/romimage/head.S
@@ -12,8 +12,40 @@
/* include board specific setup code */
#include <mach/romimage.h>
+#ifdef CONFIG_ROMIMAGE_MMCIF
+ /* load the romImage to above the empty zero page */
+ mov.l empty_zero_page_dst, r4
+ mov.l empty_zero_page_dst_adj, r5
+ add r5, r4
+ mov.l bytes_to_load, r5
+ mov.l loader_function, r7
+ jsr @r7
+ mov r4, r15
+
+ mov.l empty_zero_page_dst, r4
+ mov.l empty_zero_page_dst_adj, r5
+ add r5, r4
+ mov.l loaded_code_offs, r5
+ add r5, r4
+ jmp @r4
+ nop
+
+ .balign 4
+empty_zero_page_dst_adj:
+ .long PAGE_SIZE
+bytes_to_load:
+ .long end_data - romstart
+loader_function:
+ .long mmcif_loader
+loaded_code_offs:
+ .long loaded_code - romstart
+loaded_code:
+#endif /* CONFIG_ROMIMAGE_MMCIF */
+
/* copy the empty_zero_page contents to where vmlinux expects it */
- mova empty_zero_page_src, r0
+ mova extra_data_pos, r0
+ mov.l extra_data_size, r1
+ add r1, r0
mov.l empty_zero_page_dst, r1
mov #(PAGE_SHIFT - 4), r4
mov #1, r3
@@ -37,7 +69,9 @@
mov #PAGE_SHIFT, r4
mov #1, r1
shld r4, r1
- mova empty_zero_page_src, r0
+ mova extra_data_pos, r0
+ add r1, r0
+ mov.l extra_data_size, r1
add r1, r0
jmp @r0
nop
@@ -45,4 +79,6 @@
.align 2
empty_zero_page_dst:
.long _text
-empty_zero_page_src:
+extra_data_pos:
+extra_data_size:
+ .long zero_page_pos - extra_data_pos
diff --git a/arch/sh/boot/romimage/mmcif-sh7724.c b/arch/sh/boot/romimage/mmcif-sh7724.c
new file mode 100644
index 0000000..14863d7
--- /dev/null
+++ b/arch/sh/boot/romimage/mmcif-sh7724.c
@@ -0,0 +1,72 @@
+/*
+ * sh7724 MMCIF loader
+ *
+ * Copyright (C) 2010 Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/mmc/sh_mmcif.h>
+#include <mach/romimage.h>
+
+#define MMCIF_BASE (void __iomem *)0xa4ca0000
+
+#define MSTPCR2 0xa4150038
+#define PTWCR 0xa4050146
+#define PTXCR 0xa4050148
+#define PSELA 0xa405014e
+#define PSELE 0xa4050156
+#define HIZCRC 0xa405015c
+#define DRVCRA 0xa405018a
+
+enum { MMCIF_PROGRESS_ENTER, MMCIF_PROGRESS_INIT,
+ MMCIF_PROGRESS_LOAD, MMCIF_PROGRESS_DONE };
+
+/* SH7724 specific MMCIF loader
+ *
+ * loads the romImage from an MMC card starting from block 512
+ * use the following line to write the romImage to an MMC card
+ * # dd if=arch/sh/boot/romImage of=/dev/sdx bs=512 seek=512
+ */
+asmlinkage void mmcif_loader(unsigned char *buf, unsigned long no_bytes)
+{
+ mmcif_update_progress(MMCIF_PROGRESS_ENTER);
+
+ /* enable clock to the MMCIF hardware block */
+ __raw_writel(__raw_readl(MSTPCR2) & ~0x20000000, MSTPCR2);
+
+ /* setup pins D7-D0 */
+ __raw_writew(0x0000, PTWCR);
+
+ /* setup pins MMC_CLK, MMC_CMD */
+ __raw_writew(__raw_readw(PTXCR) & ~0x000f, PTXCR);
+
+ /* select D3-D0 pin function */
+ __raw_writew(__raw_readw(PSELA) & ~0x2000, PSELA);
+
+ /* select D7-D4 pin function */
+ __raw_writew(__raw_readw(PSELE) & ~0x3000, PSELE);
+
+ /* disable Hi-Z for the MMC pins */
+ __raw_writew(__raw_readw(HIZCRC) & ~0x0620, HIZCRC);
+
+ /* high drive capability for MMC pins */
+ __raw_writew(__raw_readw(DRVCRA) | 0x3000, DRVCRA);
+
+ mmcif_update_progress(MMCIF_PROGRESS_INIT);
+
+ /* setup MMCIF hardware */
+ sh_mmcif_boot_init(MMCIF_BASE);
+
+ mmcif_update_progress(MMCIF_PROGRESS_LOAD);
+
+ /* load kernel via MMCIF interface */
+ sh_mmcif_boot_slurp(MMCIF_BASE, buf, no_bytes);
+
+ /* disable clock to the MMCIF hardware block */
+ __raw_writel(__raw_readl(MSTPCR2) | 0x20000000, MSTPCR2);
+
+ mmcif_update_progress(MMCIF_PROGRESS_DONE);
+}
diff --git a/arch/sh/boot/romimage/vmlinux.scr b/arch/sh/boot/romimage/vmlinux.scr
index 287c08f..590394e 100644
--- a/arch/sh/boot/romimage/vmlinux.scr
+++ b/arch/sh/boot/romimage/vmlinux.scr
@@ -1,6 +1,8 @@
SECTIONS
{
.text : {
+ zero_page_pos = .;
*(.data)
+ end_data = .;
}
}
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index 953af13..1e9598d 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -139,8 +139,6 @@
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
if (!dev->resource[i].start)
continue;
- if (dev->resource[i].flags & IORESOURCE_PCI_FIXED)
- continue;
if (dev->resource[i].flags & IORESOURCE_IO)
offset = hose->io_offset;
else if (dev->resource[i].flags & IORESOURCE_MEM)
diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h
index f689554..b237d52 100644
--- a/arch/sh/include/asm/io.h
+++ b/arch/sh/include/asm/io.h
@@ -39,6 +39,8 @@
#include <asm/io_generic.h>
#include <asm/io_trapped.h>
+#ifdef CONFIG_HAS_IOPORT
+
#define inb(p) sh_mv.mv_inb((p))
#define inw(p) sh_mv.mv_inw((p))
#define inl(p) sh_mv.mv_inl((p))
@@ -60,6 +62,8 @@
#define outsw(p,b,c) sh_mv.mv_outsw((p), (b), (c))
#define outsl(p,b,c) sh_mv.mv_outsl((p), (b), (c))
+#endif
+
#define __raw_writeb(v,a) (__chk_io_ptr(a), *(volatile u8 __force *)(a) = (v))
#define __raw_writew(v,a) (__chk_io_ptr(a), *(volatile u16 __force *)(a) = (v))
#define __raw_writel(v,a) (__chk_io_ptr(a), *(volatile u32 __force *)(a) = (v))
@@ -240,6 +244,8 @@
#define IO_SPACE_LIMIT 0xffffffff
+#ifdef CONFIG_HAS_IOPORT
+
/*
* This function provides a method for the generic case where a
* board-specific ioport_map simply needs to return the port + some
@@ -255,6 +261,8 @@
#define __ioport_map(p, n) sh_mv.mv_ioport_map((p), (n))
+#endif
+
/* We really want to try and get these to memcpy etc */
void memcpy_fromio(void *, const volatile void __iomem *, unsigned long);
void memcpy_toio(volatile void __iomem *, const void *, unsigned long);
diff --git a/arch/sh/include/asm/machvec.h b/arch/sh/include/asm/machvec.h
index bc0218c..a0b0cf7 100644
--- a/arch/sh/include/asm/machvec.h
+++ b/arch/sh/include/asm/machvec.h
@@ -19,6 +19,10 @@
const char *mv_name;
int mv_nr_irqs;
+ int (*mv_irq_demux)(int irq);
+ void (*mv_init_irq)(void);
+
+#ifdef CONFIG_HAS_IOPORT
u8 (*mv_inb)(unsigned long);
u16 (*mv_inw)(unsigned long);
u32 (*mv_inl)(unsigned long);
@@ -40,12 +44,9 @@
void (*mv_outsw)(unsigned long, const void *src, unsigned long count);
void (*mv_outsl)(unsigned long, const void *src, unsigned long count);
- int (*mv_irq_demux)(int irq);
-
- void (*mv_init_irq)(void);
-
void __iomem *(*mv_ioport_map)(unsigned long port, unsigned int size);
void (*mv_ioport_unmap)(void __iomem *);
+#endif
int (*mv_clk_init)(void);
int (*mv_mode_pins)(void);
diff --git a/arch/sh/include/cpu-sh4/cpu/sh7724.h b/arch/sh/include/cpu-sh4/cpu/sh7724.h
index fbbf550..4c27b68 100644
--- a/arch/sh/include/cpu-sh4/cpu/sh7724.h
+++ b/arch/sh/include/cpu-sh4/cpu/sh7724.h
@@ -9,6 +9,7 @@
* MD3: BSC - Area0 Bus Width (16/32-bit) [CS0BCR.9,10]
* MD5: BSC - Endian Mode (L: Big, H: Little) [CMNCR.3]
* MD8: Test Mode
+ * BOOT: FBR - Boot Mode (L: MMCIF, H: Area0)
*/
/* Pin Function Controller:
diff --git a/arch/sh/include/mach-common/mach/romimage.h b/arch/sh/include/mach-common/mach/romimage.h
index 267e241..08fb422 100644
--- a/arch/sh/include/mach-common/mach/romimage.h
+++ b/arch/sh/include/mach-common/mach/romimage.h
@@ -1 +1,11 @@
+#ifdef __ASSEMBLY__
+
/* do nothing here by default */
+
+#else /* __ASSEMBLY__ */
+
+extern inline void mmcif_update_progress(int nr)
+{
+}
+
+#endif /* __ASSEMBLY__ */
diff --git a/arch/sh/include/mach-ecovec24/mach/romimage.h b/arch/sh/include/mach-ecovec24/mach/romimage.h
index 1c8787e..1dcf5e6 100644
--- a/arch/sh/include/mach-ecovec24/mach/romimage.h
+++ b/arch/sh/include/mach-ecovec24/mach/romimage.h
@@ -1,3 +1,5 @@
+#ifdef __ASSEMBLY__
+
/* EcoVec board specific boot code:
* converts the "partner-jet-script.txt" script into assembly
* the assembly code is the first code to be executed in the romImage
@@ -18,3 +20,28 @@
.align 2
1 : .long 0xa8000000
2 :
+
+#else /* __ASSEMBLY__ */
+
+/* Ecovec board specific information:
+ *
+ * Set the following to enable MMCIF boot from the MMC card in CN12:
+ *
+ * DS1.5 = OFF (SH BOOT pin set to L)
+ * DS2.6 = OFF (Select MMCIF on CN12 instead of SDHI1)
+ * DS2.7 = ON (Select MMCIF on CN12 instead of SDHI1)
+ *
+ */
+#define HIZCRA 0xa4050158
+#define PGDR 0xa405012c
+
+extern inline void mmcif_update_progress(int nr)
+{
+ /* disable Hi-Z for LED pins */
+ __raw_writew(__raw_readw(HIZCRA) & ~(1 << 1), HIZCRA);
+
+ /* update progress on LED4, LED5, LED6 and LED7 */
+ __raw_writeb(1 << (nr - 1), PGDR);
+}
+
+#endif /* __ASSEMBLY__ */
diff --git a/arch/sh/include/mach-kfr2r09/mach/romimage.h b/arch/sh/include/mach-kfr2r09/mach/romimage.h
index a110823..976256a 100644
--- a/arch/sh/include/mach-kfr2r09/mach/romimage.h
+++ b/arch/sh/include/mach-kfr2r09/mach/romimage.h
@@ -1,3 +1,5 @@
+#ifdef __ASSEMBLY__
+
/* kfr2r09 board specific boot code:
* converts the "partner-jet-script.txt" script into assembly
* the assembly code is the first code to be executed in the romImage
@@ -18,3 +20,11 @@
.align 2
1: .long 0xa8000000
2:
+
+#else /* __ASSEMBLY__ */
+
+extern inline void mmcif_update_progress(int nr)
+{
+}
+
+#endif /* __ASSEMBLY__ */
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index 650b92f..e25f3c6 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -12,7 +12,7 @@
CFLAGS_REMOVE_return_address.o = -pg
obj-y := clkdev.o debugtraps.o dma-nommu.o dumpstack.o \
- idle.o io.o io_generic.o irq.o \
+ idle.o io.o irq.o \
irq_$(BITS).o machvec.o nmi_debug.o process.o \
process_$(BITS).o ptrace_$(BITS).o \
reboot.o return_address.o \
@@ -39,6 +39,7 @@
obj-$(CONFIG_HIBERNATION) += swsusp.o
obj-$(CONFIG_DWARF_UNWINDER) += dwarf.o
obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_callchain.o
+obj-$(CONFIG_HAS_IOPORT) += io_generic.o
obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += localtimer.o
diff --git a/arch/sh/kernel/dwarf.c b/arch/sh/kernel/dwarf.c
index 886d7d8..49c09c7 100644
--- a/arch/sh/kernel/dwarf.c
+++ b/arch/sh/kernel/dwarf.c
@@ -49,6 +49,8 @@
static struct dwarf_cie *cached_cie;
+static unsigned int dwarf_unwinder_ready;
+
/**
* dwarf_frame_alloc_reg - allocate memory for a DWARF register
* @frame: the DWARF frame whose list of registers we insert on
@@ -582,6 +584,13 @@
unsigned long addr;
/*
+ * If we've been called in to before initialization has
+ * completed, bail out immediately.
+ */
+ if (!dwarf_unwinder_ready)
+ return NULL;
+
+ /*
* If we're starting at the top of the stack we need get the
* contents of a physical register to get the CFA in order to
* begin the virtual unwinding of the stack.
@@ -1167,7 +1176,7 @@
*/
static int __init dwarf_unwinder_init(void)
{
- int err;
+ int err = -ENOMEM;
dwarf_frame_cachep = kmem_cache_create("dwarf_frames",
sizeof(struct dwarf_frame), 0,
@@ -1181,11 +1190,15 @@
mempool_alloc_slab,
mempool_free_slab,
dwarf_frame_cachep);
+ if (!dwarf_frame_pool)
+ goto out;
dwarf_reg_pool = mempool_create(DWARF_REG_MIN_REQ,
mempool_alloc_slab,
mempool_free_slab,
dwarf_reg_cachep);
+ if (!dwarf_reg_pool)
+ goto out;
err = dwarf_parse_section(__start_eh_frame, __stop_eh_frame, NULL);
if (err)
@@ -1195,11 +1208,13 @@
if (err)
goto out;
+ dwarf_unwinder_ready = 1;
+
return 0;
out:
printk(KERN_ERR "Failed to initialise DWARF unwinder: %d\n", err);
dwarf_unwinder_cleanup();
- return -EINVAL;
+ return err;
}
early_initcall(dwarf_unwinder_init);
diff --git a/arch/sh/kernel/io.c b/arch/sh/kernel/io.c
index 4770c24..5c51b79 100644
--- a/arch/sh/kernel/io.c
+++ b/arch/sh/kernel/io.c
@@ -112,25 +112,3 @@
}
}
EXPORT_SYMBOL(memset_io);
-
-#ifndef CONFIG_GENERIC_IOMAP
-
-void __iomem *ioport_map(unsigned long port, unsigned int nr)
-{
- void __iomem *ret;
-
- ret = __ioport_map_trapped(port, nr);
- if (ret)
- return ret;
-
- return __ioport_map(port, nr);
-}
-EXPORT_SYMBOL(ioport_map);
-
-void ioport_unmap(void __iomem *addr)
-{
- sh_mv.mv_ioport_unmap(addr);
-}
-EXPORT_SYMBOL(ioport_unmap);
-
-#endif /* CONFIG_GENERIC_IOMAP */
diff --git a/arch/sh/kernel/io_generic.c b/arch/sh/kernel/io_generic.c
index e1e1dbd..447d78f 100644
--- a/arch/sh/kernel/io_generic.c
+++ b/arch/sh/kernel/io_generic.c
@@ -158,3 +158,23 @@
void generic_ioport_unmap(void __iomem *addr)
{
}
+
+#ifndef CONFIG_GENERIC_IOMAP
+void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+ void __iomem *ret;
+
+ ret = __ioport_map_trapped(port, nr);
+ if (ret)
+ return ret;
+
+ return __ioport_map(port, nr);
+}
+EXPORT_SYMBOL(ioport_map);
+
+void ioport_unmap(void __iomem *addr)
+{
+ sh_mv.mv_ioport_unmap(addr);
+}
+EXPORT_SYMBOL(ioport_unmap);
+#endif /* CONFIG_GENERIC_IOMAP */
diff --git a/arch/sh/kernel/io_trapped.c b/arch/sh/kernel/io_trapped.c
index 4a8bb4e..2947d2b 100644
--- a/arch/sh/kernel/io_trapped.c
+++ b/arch/sh/kernel/io_trapped.c
@@ -91,10 +91,14 @@
tiop->magic = IO_TRAPPED_MAGIC;
INIT_LIST_HEAD(&tiop->list);
spin_lock_irq(&trapped_lock);
+#ifdef CONFIG_HAS_IOPORT
if (flags & IORESOURCE_IO)
list_add(&tiop->list, &trapped_io);
+#endif
+#ifdef CONFIG_HAS_IOMEM
if (flags & IORESOURCE_MEM)
list_add(&tiop->list, &trapped_mem);
+#endif
spin_unlock_irq(&trapped_lock);
return 0;
diff --git a/arch/sh/kernel/machvec.c b/arch/sh/kernel/machvec.c
index 85cfaf9..9f9bb63 100644
--- a/arch/sh/kernel/machvec.c
+++ b/arch/sh/kernel/machvec.c
@@ -118,6 +118,14 @@
sh_mv.mv_##elem = generic_##elem; \
} while (0)
+#ifdef CONFIG_HAS_IOPORT
+
+#ifdef P2SEG
+ __set_io_port_base(P2SEG);
+#else
+ __set_io_port_base(0);
+#endif
+
mv_set(inb); mv_set(inw); mv_set(inl);
mv_set(outb); mv_set(outw); mv_set(outl);
@@ -129,16 +137,13 @@
mv_set(ioport_map);
mv_set(ioport_unmap);
+
+#endif
+
mv_set(irq_demux);
mv_set(mode_pins);
mv_set(mem_init);
if (!sh_mv.mv_nr_irqs)
sh_mv.mv_nr_irqs = NR_IRQS;
-
-#ifdef P2SEG
- __set_io_port_base(P2SEG);
-#else
- __set_io_port_base(0);
-#endif
}
diff --git a/arch/sh/kernel/return_address.c b/arch/sh/kernel/return_address.c
index cbf1dd5..5124aeb 100644
--- a/arch/sh/kernel/return_address.c
+++ b/arch/sh/kernel/return_address.c
@@ -24,6 +24,8 @@
struct dwarf_frame *tmp;
tmp = dwarf_unwind_stack(ra, frame);
+ if (!tmp)
+ return NULL;
if (frame)
dwarf_free_frame(frame);
diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c
index 18623ba..6379091 100644
--- a/arch/sh/mm/pmb.c
+++ b/arch/sh/mm/pmb.c
@@ -770,7 +770,7 @@
spin_unlock_irqrestore(&pmbe->lock, flags);
}
- read_lock(&pmb_rwlock);
+ read_unlock(&pmb_rwlock);
}
#endif
diff --git a/arch/um/include/asm/arch_hweight.h b/arch/um/include/asm/arch_hweight.h
new file mode 100644
index 0000000..c656cf4
--- /dev/null
+++ b/arch/um/include/asm/arch_hweight.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_UM_HWEIGHT_H
+#define _ASM_UM_HWEIGHT_H
+
+#include <asm-generic/bitops/arch_hweight.h>
+
+#endif
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index e22c969..6966342 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -81,7 +81,7 @@
current->thread.fault_catcher = NULL;
- kunmap_atomic(page, KM_UML_USERCOPY);
+ kunmap_atomic((void *)addr, KM_UML_USERCOPY);
return n;
}
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index 93a11d7..e696144 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -10,6 +10,7 @@
#include <errno.h>
#include <fcntl.h>
#include <string.h>
+#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/param.h>
#include "init.h"
diff --git a/arch/x86/boot/video-vga.c b/arch/x86/boot/video-vga.c
index ed7aeff..45bc940 100644
--- a/arch/x86/boot/video-vga.c
+++ b/arch/x86/boot/video-vga.c
@@ -41,13 +41,12 @@
static u8 vga_set_basic_mode(void)
{
struct biosregs ireg, oreg;
- u16 ax;
u8 mode;
initregs(&ireg);
/* Query current mode */
- ax = 0x0f00;
+ ireg.ax = 0x0f00;
intcall(0x10, &ireg, &oreg);
mode = oreg.al;
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 63cb409..9cb2edb 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -183,7 +183,7 @@
u32 gsi_end;
};
extern struct mp_ioapic_gsi mp_gsi_routing[];
-extern u32 gsi_end;
+extern u32 gsi_top;
int mp_find_ioapic(u32 gsi);
int mp_find_ioapic_pin(int ioapic, u32 gsi);
void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
@@ -197,7 +197,7 @@
static inline void ioapic_init_mappings(void) { }
static inline void ioapic_insert_resources(void) { }
static inline void probe_nr_irqs_gsi(void) { }
-#define gsi_end (NR_IRQS_LEGACY - 1)
+#define gsi_top (NR_IRQS_LEGACY)
static inline int mp_find_ioapic(u32 gsi) { return 0; }
struct io_apic_irq_attr;
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index b49d8ca..8c7ae43 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -110,6 +110,7 @@
#define MSR_AMD64_PATCH_LOADER 0xc0010020
#define MSR_AMD64_OSVW_ID_LENGTH 0xc0010140
#define MSR_AMD64_OSVW_STATUS 0xc0010141
+#define MSR_AMD64_DC_CFG 0xc0011022
#define MSR_AMD64_IBSFETCHCTL 0xc0011030
#define MSR_AMD64_IBSFETCHLINAD 0xc0011031
#define MSR_AMD64_IBSFETCHPHYSAD 0xc0011032
diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h
index 8d8797e..cd2a31d 100644
--- a/arch/x86/include/asm/pci_x86.h
+++ b/arch/x86/include/asm/pci_x86.h
@@ -53,6 +53,8 @@
extern struct pci_bus *pci_root_bus;
extern struct pci_ops pci_root_ops;
+void pcibios_scan_specific_bus(int busn);
+
/* pci-irq.c */
struct irq_info {
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h
index 0797e74..cd28f9a 100644
--- a/arch/x86/include/asm/percpu.h
+++ b/arch/x86/include/asm/percpu.h
@@ -77,6 +77,7 @@
if (0) { \
pto_T__ pto_tmp__; \
pto_tmp__ = (val); \
+ (void)pto_tmp__; \
} \
switch (sizeof(var)) { \
case 1: \
@@ -115,6 +116,7 @@
if (0) { \
pao_T__ pao_tmp__; \
pao_tmp__ = (val); \
+ (void)pao_tmp__; \
} \
switch (sizeof(var)) { \
case 1: \
diff --git a/arch/x86/include/asm/pgtable_32_types.h b/arch/x86/include/asm/pgtable_32_types.h
index 5e67c15..ed5903b 100644
--- a/arch/x86/include/asm/pgtable_32_types.h
+++ b/arch/x86/include/asm/pgtable_32_types.h
@@ -26,7 +26,7 @@
*/
#define VMALLOC_OFFSET (8 * 1024 * 1024)
-#ifndef __ASSEMBLER__
+#ifndef __ASSEMBLY__
extern bool __vmalloc_start_set; /* set once high_memory is set */
#endif
diff --git a/arch/x86/include/asm/suspend_32.h b/arch/x86/include/asm/suspend_32.h
index 48dcfa6..fd921c3 100644
--- a/arch/x86/include/asm/suspend_32.h
+++ b/arch/x86/include/asm/suspend_32.h
@@ -15,6 +15,8 @@
struct saved_context {
u16 es, fs, gs, ss;
unsigned long cr0, cr2, cr3, cr4;
+ u64 misc_enable;
+ bool misc_enable_saved;
struct desc_ptr gdt;
struct desc_ptr idt;
u16 ldt;
diff --git a/arch/x86/include/asm/suspend_64.h b/arch/x86/include/asm/suspend_64.h
index 06284f4..8d942af 100644
--- a/arch/x86/include/asm/suspend_64.h
+++ b/arch/x86/include/asm/suspend_64.h
@@ -27,6 +27,8 @@
u16 ds, es, fs, gs, ss;
unsigned long gs_base, gs_kernel_base, fs_base;
unsigned long cr0, cr2, cr3, cr4, cr8;
+ u64 misc_enable;
+ bool misc_enable_saved;
unsigned long efer;
u16 gdt_pad;
u16 gdt_limit;
diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h
index b8fe48e..e7f4d33 100644
--- a/arch/x86/include/asm/system.h
+++ b/arch/x86/include/asm/system.h
@@ -451,7 +451,7 @@
*
* (Could use an alternative three way for this if there was one.)
*/
-static inline void rdtsc_barrier(void)
+static __always_inline void rdtsc_barrier(void)
{
alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 60cc405..c05872a 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -118,7 +118,7 @@
if (gsi >= NR_IRQS_LEGACY)
irq = gsi;
else
- irq = gsi_end + 1 + gsi;
+ irq = gsi_top + gsi;
return irq;
}
@@ -129,10 +129,10 @@
if (irq < NR_IRQS_LEGACY)
gsi = isa_irq_to_gsi[irq];
- else if (irq <= gsi_end)
+ else if (irq < gsi_top)
gsi = irq;
- else if (irq <= (gsi_end + NR_IRQS_LEGACY))
- gsi = irq - gsi_end;
+ else if (irq < (gsi_top + NR_IRQS_LEGACY))
+ gsi = irq - gsi_top;
else
gsi = 0xffffffff;
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index fa5a1474..0d20286 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -1487,6 +1487,7 @@
struct protection_domain *domain)
{
struct iommu_dev_data *dev_data, *alias_data;
+ int ret;
dev_data = get_dev_data(dev);
alias_data = get_dev_data(dev_data->alias);
@@ -1498,13 +1499,14 @@
spin_lock(&domain->lock);
/* Some sanity checks */
+ ret = -EBUSY;
if (alias_data->domain != NULL &&
alias_data->domain != domain)
- return -EBUSY;
+ goto out_unlock;
if (dev_data->domain != NULL &&
dev_data->domain != domain)
- return -EBUSY;
+ goto out_unlock;
/* Do real assignment */
if (dev_data->alias != dev) {
@@ -1520,10 +1522,14 @@
atomic_inc(&dev_data->bind);
+ ret = 0;
+
+out_unlock:
+
/* ready */
spin_unlock(&domain->lock);
- return 0;
+ return ret;
}
/*
@@ -2324,10 +2330,6 @@
iommu_detected = 1;
swiotlb = 0;
-#ifdef CONFIG_GART_IOMMU
- gart_iommu_aperture_disabled = 1;
- gart_iommu_aperture = 0;
-#endif
/* Make the driver finally visible to the drivers */
dma_ops = &amd_iommu_dma_ops;
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c
index 3bacb4d..3cc63e2 100644
--- a/arch/x86/kernel/amd_iommu_init.c
+++ b/arch/x86/kernel/amd_iommu_init.c
@@ -287,8 +287,12 @@
{
u8 *ret;
- if (!request_mem_region(address, MMIO_REGION_LENGTH, "amd_iommu"))
+ if (!request_mem_region(address, MMIO_REGION_LENGTH, "amd_iommu")) {
+ pr_err("AMD-Vi: Can not reserve memory region %llx for mmio\n",
+ address);
+ pr_err("AMD-Vi: This is a BIOS bug. Please contact your hardware vendor\n");
return NULL;
+ }
ret = ioremap_nocache(address, MMIO_REGION_LENGTH);
if (ret != NULL)
@@ -1314,7 +1318,7 @@
ret = amd_iommu_init_dma_ops();
if (ret)
- goto free;
+ goto free_disable;
amd_iommu_init_api();
@@ -1332,9 +1336,10 @@
out:
return ret;
-free:
+free_disable:
disable_iommus();
+free:
amd_iommu_uninit_devices();
free_pages((unsigned long)amd_iommu_pd_alloc_bitmap,
@@ -1353,6 +1358,15 @@
free_unity_maps();
+#ifdef CONFIG_GART_IOMMU
+ /*
+ * We failed to initialize the AMD IOMMU - try fallback to GART
+ * if possible.
+ */
+ gart_iommu_init();
+
+#endif
+
goto out;
}
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 33f3563..e41ed24 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -89,8 +89,8 @@
/* IO APIC gsi routing info */
struct mp_ioapic_gsi mp_gsi_routing[MAX_IO_APICS];
-/* The last gsi number used */
-u32 gsi_end;
+/* The one past the highest gsi number used */
+u32 gsi_top;
/* MP IRQ source entries */
struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES];
@@ -1035,7 +1035,7 @@
if (gsi >= NR_IRQS_LEGACY)
irq = gsi;
else
- irq = gsi_end + 1 + gsi;
+ irq = gsi_top + gsi;
}
#ifdef CONFIG_X86_32
@@ -3853,7 +3853,7 @@
{
int nr;
- nr = gsi_end + 1 + NR_IRQS_LEGACY;
+ nr = gsi_top + NR_IRQS_LEGACY;
if (nr > nr_irqs_gsi)
nr_irqs_gsi = nr;
@@ -4294,8 +4294,8 @@
*/
nr_ioapic_registers[idx] = entries;
- if (mp_gsi_routing[idx].gsi_end > gsi_end)
- gsi_end = mp_gsi_routing[idx].gsi_end;
+ if (mp_gsi_routing[idx].gsi_end >= gsi_top)
+ gsi_top = mp_gsi_routing[idx].gsi_end + 1;
printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
"GSI %d-%d\n", idx, mp_ioapics[idx].apicid,
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 707165d..18cc425 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -36,6 +36,7 @@
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/debugfs.h>
+#include <linux/edac_mce.h>
#include <asm/processor.h>
#include <asm/hw_irq.h>
@@ -169,6 +170,15 @@
entry = rcu_dereference_check_mce(mcelog.next);
for (;;) {
/*
+ * If edac_mce is enabled, it will check the error type
+ * and will process it, if it is a known error.
+ * Otherwise, the error will be sent through mcelog
+ * interface
+ */
+ if (edac_mce_parse(mce))
+ return;
+
+ /*
* When the buffer fills up discard new entries.
* Assume that the earlier errors are the more
* interesting ones:
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index c775860..5db5b7d 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -106,6 +106,7 @@
int n_events;
int n_added;
+ int n_txn;
int assign[X86_PMC_IDX_MAX]; /* event to counter assignment */
u64 tags[X86_PMC_IDX_MAX];
struct perf_event *event_list[X86_PMC_IDX_MAX]; /* in enabled order */
@@ -983,6 +984,7 @@
out:
cpuc->n_events = n;
cpuc->n_added += n - n0;
+ cpuc->n_txn += n - n0;
return 0;
}
@@ -1089,6 +1091,14 @@
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
int i;
+ /*
+ * If we're called during a txn, we don't need to do anything.
+ * The events never got scheduled and ->cancel_txn will truncate
+ * the event_list.
+ */
+ if (cpuc->group_flag & PERF_EVENT_TXN_STARTED)
+ return;
+
x86_pmu_stop(event);
for (i = 0; i < cpuc->n_events; i++) {
@@ -1379,6 +1389,7 @@
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
cpuc->group_flag |= PERF_EVENT_TXN_STARTED;
+ cpuc->n_txn = 0;
}
/*
@@ -1391,6 +1402,11 @@
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
cpuc->group_flag &= ~PERF_EVENT_TXN_STARTED;
+ /*
+ * Truncate the collected events.
+ */
+ cpuc->n_added -= cpuc->n_txn;
+ cpuc->n_events -= cpuc->n_txn;
}
/*
@@ -1419,6 +1435,12 @@
*/
memcpy(cpuc->assign, assign, n*sizeof(int));
+ /*
+ * Clear out the txn count so that ->cancel_txn() which gets
+ * run after ->commit_txn() doesn't undo things.
+ */
+ cpuc->n_txn = 0;
+
return 0;
}
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index fdbc652..214ac86 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -72,6 +72,7 @@
INTEL_EVENT_CONSTRAINT(0x51, 0x3), /* L1D */
INTEL_EVENT_CONSTRAINT(0x60, 0x1), /* OFFCORE_REQUESTS_OUTSTANDING */
INTEL_EVENT_CONSTRAINT(0x63, 0x3), /* CACHE_LOCK_CYCLES */
+ INTEL_EVENT_CONSTRAINT(0xb3, 0x1), /* SNOOPQ_REQUEST_OUTSTANDING */
EVENT_CONSTRAINT_END
};
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 7bca3c6..0d6fc71 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -729,7 +729,7 @@
struct e820entry *ei = &e820.map[i];
if (ei->type == E820_NVS)
- hibernate_nvs_register(ei->addr, ei->size);
+ suspend_nvs_register(ei->addr, ei->size);
}
return 0;
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index 5ae5d24..d86dbf7 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -123,7 +123,7 @@
printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n",
m->apicid, m->apicver, m->apicaddr);
- mp_register_ioapic(m->apicid, m->apicaddr, gsi_end + 1);
+ mp_register_ioapic(m->apicid, m->apicaddr, gsi_top);
}
static void print_MP_intsrc_info(struct mpc_intsrc *m)
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index fb99f7e..0b96b55 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -103,11 +103,16 @@
#define PMR_SOFTSTOPFAULT 0x40000000
#define PMR_HARDSTOP 0x20000000
-#define MAX_NUM_OF_PHBS 8 /* how many PHBs in total? */
-#define MAX_NUM_CHASSIS 8 /* max number of chassis */
-/* MAX_PHB_BUS_NUM is the maximal possible dev->bus->number */
-#define MAX_PHB_BUS_NUM (MAX_NUM_OF_PHBS * MAX_NUM_CHASSIS * 2)
-#define PHBS_PER_CALGARY 4
+/*
+ * The maximum PHB bus number.
+ * x3950M2 (rare): 8 chassis, 48 PHBs per chassis = 384
+ * x3950M2: 4 chassis, 48 PHBs per chassis = 192
+ * x3950 (PCIE): 8 chassis, 32 PHBs per chassis = 256
+ * x3950 (PCIX): 8 chassis, 16 PHBs per chassis = 128
+ */
+#define MAX_PHB_BUS_NUM 384
+
+#define PHBS_PER_CALGARY 4
/* register offsets in Calgary's internal register space */
static const unsigned long tar_offsets[] = {
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 8e1aac8..e3af342 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -228,6 +228,14 @@
DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T5400"),
},
},
+ { /* Handle problems with rebooting on Dell T7400's */
+ .callback = set_bios_reboot,
+ .ident = "Dell Precision T7400",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T7400"),
+ },
+ },
{ /* Handle problems with rebooting on HP laptops */
.callback = set_bios_reboot,
.ident = "HP Compaq Laptop",
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c
index cf59276..de3b63a 100644
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -21,12 +21,6 @@
#include <asm/cpu.h>
#include <asm/stackprotector.h>
-#ifdef CONFIG_DEBUG_PER_CPU_MAPS
-# define DBG(fmt, ...) pr_dbg(fmt, ##__VA_ARGS__)
-#else
-# define DBG(fmt, ...) do { if (0) pr_dbg(fmt, ##__VA_ARGS__); } while (0)
-#endif
-
DEFINE_PER_CPU(int, cpu_number);
EXPORT_PER_CPU_SYMBOL(cpu_number);
diff --git a/arch/x86/kernel/sfi.c b/arch/x86/kernel/sfi.c
index 7ded578..cb22acf 100644
--- a/arch/x86/kernel/sfi.c
+++ b/arch/x86/kernel/sfi.c
@@ -93,7 +93,7 @@
pentry = (struct sfi_apic_table_entry *)sb->pentry;
for (i = 0; i < num; i++) {
- mp_register_ioapic(i, pentry->phys_addr, gsi_end + 1);
+ mp_register_ioapic(i, pentry->phys_addr, gsi_top);
pentry++;
}
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 37462f1..c4f33b2 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -686,7 +686,7 @@
static void __cpuinit announce_cpu(int cpu, int apicid)
{
static int current_node = -1;
- int node = cpu_to_node(cpu);
+ int node = early_cpu_to_node(cpu);
if (system_state == SYSTEM_BOOTING) {
if (node != current_node) {
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 81563e7..a6f695d 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -1815,6 +1815,9 @@
spte |= PT_WRITABLE_MASK;
+ if (!tdp_enabled && !(pte_access & ACC_WRITE_MASK))
+ spte &= ~PT_USER_MASK;
+
/*
* Optimization: for pte sync, if spte was writable the hash
* lookup is unnecessary (and expensive). Write protection
@@ -1870,6 +1873,8 @@
child = page_header(pte & PT64_BASE_ADDR_MASK);
mmu_page_remove_parent_pte(child, sptep);
+ __set_spte(sptep, shadow_trap_nonpresent_pte);
+ kvm_flush_remote_tlbs(vcpu->kvm);
} else if (pfn != spte_to_pfn(*sptep)) {
pgprintk("hfn old %lx new %lx\n",
spte_to_pfn(*sptep), pfn);
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 96dc232..ce438e0 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -28,6 +28,7 @@
#include <linux/ftrace_event.h>
#include <linux/slab.h>
+#include <asm/tlbflush.h>
#include <asm/desc.h>
#include <asm/virtext.h>
@@ -56,6 +57,8 @@
#define DEBUGCTL_RESERVED_BITS (~(0x3fULL))
+static bool erratum_383_found __read_mostly;
+
static const u32 host_save_user_msrs[] = {
#ifdef CONFIG_X86_64
MSR_STAR, MSR_LSTAR, MSR_CSTAR, MSR_SYSCALL_MASK, MSR_KERNEL_GS_BASE,
@@ -374,6 +377,31 @@
svm->vmcb->control.event_inj_err = error_code;
}
+static void svm_init_erratum_383(void)
+{
+ u32 low, high;
+ int err;
+ u64 val;
+
+ /* Only Fam10h is affected */
+ if (boot_cpu_data.x86 != 0x10)
+ return;
+
+ /* Use _safe variants to not break nested virtualization */
+ val = native_read_msr_safe(MSR_AMD64_DC_CFG, &err);
+ if (err)
+ return;
+
+ val |= (1ULL << 47);
+
+ low = lower_32_bits(val);
+ high = upper_32_bits(val);
+
+ native_write_msr_safe(MSR_AMD64_DC_CFG, low, high);
+
+ erratum_383_found = true;
+}
+
static int has_svm(void)
{
const char *msg;
@@ -429,6 +457,8 @@
wrmsrl(MSR_VM_HSAVE_PA, page_to_pfn(sd->save_area) << PAGE_SHIFT);
+ svm_init_erratum_383();
+
return 0;
}
@@ -1410,8 +1440,59 @@
return 1;
}
-static int mc_interception(struct vcpu_svm *svm)
+static bool is_erratum_383(void)
{
+ int err, i;
+ u64 value;
+
+ if (!erratum_383_found)
+ return false;
+
+ value = native_read_msr_safe(MSR_IA32_MC0_STATUS, &err);
+ if (err)
+ return false;
+
+ /* Bit 62 may or may not be set for this mce */
+ value &= ~(1ULL << 62);
+
+ if (value != 0xb600000000010015ULL)
+ return false;
+
+ /* Clear MCi_STATUS registers */
+ for (i = 0; i < 6; ++i)
+ native_write_msr_safe(MSR_IA32_MCx_STATUS(i), 0, 0);
+
+ value = native_read_msr_safe(MSR_IA32_MCG_STATUS, &err);
+ if (!err) {
+ u32 low, high;
+
+ value &= ~(1ULL << 2);
+ low = lower_32_bits(value);
+ high = upper_32_bits(value);
+
+ native_write_msr_safe(MSR_IA32_MCG_STATUS, low, high);
+ }
+
+ /* Flush tlb to evict multi-match entries */
+ __flush_tlb_all();
+
+ return true;
+}
+
+static void svm_handle_mce(struct vcpu_svm *svm)
+{
+ if (is_erratum_383()) {
+ /*
+ * Erratum 383 triggered. Guest state is corrupt so kill the
+ * guest.
+ */
+ pr_err("KVM: Guest triggered AMD Erratum 383\n");
+
+ set_bit(KVM_REQ_TRIPLE_FAULT, &svm->vcpu.requests);
+
+ return;
+ }
+
/*
* On an #MC intercept the MCE handler is not called automatically in
* the host. So do it by hand here.
@@ -1420,6 +1501,11 @@
"int $0x12\n");
/* not sure if we ever come back to this point */
+ return;
+}
+
+static int mc_interception(struct vcpu_svm *svm)
+{
return 1;
}
@@ -3088,6 +3174,14 @@
vcpu->arch.regs_avail &= ~(1 << VCPU_EXREG_PDPTR);
vcpu->arch.regs_dirty &= ~(1 << VCPU_EXREG_PDPTR);
}
+
+ /*
+ * We need to handle MC intercepts here before the vcpu has a chance to
+ * change the physical cpu
+ */
+ if (unlikely(svm->vmcb->control.exit_code ==
+ SVM_EXIT_EXCP_BASE + MC_VECTOR))
+ svm_handle_mce(svm);
}
#undef R
diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c
index 550df48..787c52c 100644
--- a/arch/x86/mm/numa.c
+++ b/arch/x86/mm/numa.c
@@ -3,12 +3,6 @@
#include <linux/module.h>
#include <linux/bootmem.h>
-#ifdef CONFIG_DEBUG_PER_CPU_MAPS
-# define DBG(x...) printk(KERN_DEBUG x)
-#else
-# define DBG(x...)
-#endif
-
/*
* Which logical CPUs are on which nodes
*/
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index acc15b2..64121a1 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -302,7 +302,7 @@
return -EINVAL;
}
- new = kmalloc(sizeof(struct memtype), GFP_KERNEL);
+ new = kzalloc(sizeof(struct memtype), GFP_KERNEL);
if (!new)
return -ENOMEM;
diff --git a/arch/x86/mm/pat_rbtree.c b/arch/x86/mm/pat_rbtree.c
index f537087..f20eeec 100644
--- a/arch/x86/mm/pat_rbtree.c
+++ b/arch/x86/mm/pat_rbtree.c
@@ -226,6 +226,7 @@
if (ret_type)
new->type = *ret_type;
+ new->subtree_max_end = new->end;
memtype_rb_insert(&memtype_rbroot, new);
}
return err;
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 97da2ba..6fdb3ec 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -96,6 +96,7 @@
* the fact the PCI specs explicitly allow address decoders to be
* shared between expansion ROMs and other resource regions, it's
* at least dangerous)
+ * - bad resource sizes or overlaps with other regions
*
* Our solution:
* (1) Allocate resources for all buses behind PCI-to-PCI bridges.
@@ -136,6 +137,7 @@
* child resource allocations in this
* range.
*/
+ r->start = r->end = 0;
r->flags = 0;
}
}
diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c
index 0db5eaf..8d460ea 100644
--- a/arch/x86/pci/legacy.c
+++ b/arch/x86/pci/legacy.c
@@ -11,28 +11,14 @@
*/
static void __devinit pcibios_fixup_peer_bridges(void)
{
- int n, devfn;
- long node;
+ int n;
if (pcibios_last_bus <= 0 || pcibios_last_bus > 0xff)
return;
DBG("PCI: Peer bridge fixup\n");
- for (n=0; n <= pcibios_last_bus; n++) {
- u32 l;
- if (pci_find_bus(0, n))
- continue;
- node = get_mp_bus_to_node(n);
- for (devfn = 0; devfn < 256; devfn += 8) {
- if (!raw_pci_read(0, n, devfn, PCI_VENDOR_ID, 2, &l) &&
- l != 0x0000 && l != 0xffff) {
- DBG("Found device at %02x:%02x [%04x]\n", n, devfn, l);
- printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n);
- pci_scan_bus_on_node(n, &pci_root_ops, node);
- break;
- }
- }
- }
+ for (n=0; n <= pcibios_last_bus; n++)
+ pcibios_scan_specific_bus(n);
}
int __init pci_legacy_init(void)
@@ -50,6 +36,28 @@
return 0;
}
+void pcibios_scan_specific_bus(int busn)
+{
+ int devfn;
+ long node;
+ u32 l;
+
+ if (pci_find_bus(0, busn))
+ return;
+
+ node = get_mp_bus_to_node(busn);
+ for (devfn = 0; devfn < 256; devfn += 8) {
+ if (!raw_pci_read(0, busn, devfn, PCI_VENDOR_ID, 2, &l) &&
+ l != 0x0000 && l != 0xffff) {
+ DBG("Found device at %02x:%02x [%04x]\n", busn, devfn, l);
+ printk(KERN_INFO "PCI: Discovered peer bus %02x\n", busn);
+ pci_scan_bus_on_node(busn, &pci_root_ops, node);
+ return;
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(pcibios_scan_specific_bus);
+
int __init pci_subsys_init(void)
{
/*
diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
index 0a979f3..1290ba5 100644
--- a/arch/x86/power/cpu.c
+++ b/arch/x86/power/cpu.c
@@ -105,6 +105,8 @@
ctxt->cr4 = read_cr4();
ctxt->cr8 = read_cr8();
#endif
+ ctxt->misc_enable_saved = !rdmsrl_safe(MSR_IA32_MISC_ENABLE,
+ &ctxt->misc_enable);
}
/* Needed by apm.c */
@@ -152,6 +154,8 @@
*/
static void __restore_processor_state(struct saved_context *ctxt)
{
+ if (ctxt->misc_enable_saved)
+ wrmsrl(MSR_IA32_MISC_ENABLE, ctxt->misc_enable);
/*
* control registers
*/
diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c
index 987267f..a9c6611 100644
--- a/arch/x86/xen/suspend.c
+++ b/arch/x86/xen/suspend.c
@@ -60,6 +60,6 @@
void xen_arch_resume(void)
{
- smp_call_function(xen_vcpu_notify_restore,
- (void *)CLOCK_EVT_NOTIFY_RESUME, 1);
+ on_each_cpu(xen_vcpu_notify_restore,
+ (void *)CLOCK_EVT_NOTIFY_RESUME, 1);
}
diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c
index bc07333..e367e30 100644
--- a/arch/xtensa/mm/fault.c
+++ b/arch/xtensa/mm/fault.c
@@ -105,7 +105,6 @@
* make sure we exit gracefully rather than endlessly redo
* the fault.
*/
-survive:
fault = handle_mm_fault(mm, vma, address, is_write ? FAULT_FLAG_WRITE : 0);
if (unlikely(fault & VM_FAULT_ERROR)) {
if (fault & VM_FAULT_OOM)
@@ -146,15 +145,10 @@
*/
out_of_memory:
up_read(&mm->mmap_sem);
- if (is_global_init(current)) {
- yield();
- down_read(&mm->mmap_sem);
- goto survive;
- }
- printk("VM: killing process %s\n", current->comm);
- if (user_mode(regs))
- do_group_exit(SIGKILL);
- bad_page_fault(regs, address, SIGKILL);
+ if (!user_mode(regs))
+ bad_page_fault(regs, address, SIGKILL);
+ else
+ pagefault_out_of_memory();
return;
do_sigbus:
diff --git a/block/blk-core.c b/block/blk-core.c
index 3bc5579..f0640d7 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -467,6 +467,9 @@
{
struct request_list *rl = &q->rq;
+ if (unlikely(rl->rq_pool))
+ return 0;
+
rl->count[BLK_RW_SYNC] = rl->count[BLK_RW_ASYNC] = 0;
rl->starved[BLK_RW_SYNC] = rl->starved[BLK_RW_ASYNC] = 0;
rl->elvpriv = 0;
@@ -570,9 +573,17 @@
struct request_queue *
blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
{
- struct request_queue *q = blk_alloc_queue_node(GFP_KERNEL, node_id);
+ struct request_queue *uninit_q, *q;
- return blk_init_allocated_queue_node(q, rfn, lock, node_id);
+ uninit_q = blk_alloc_queue_node(GFP_KERNEL, node_id);
+ if (!uninit_q)
+ return NULL;
+
+ q = blk_init_allocated_queue_node(uninit_q, rfn, lock, node_id);
+ if (!q)
+ blk_cleanup_queue(uninit_q);
+
+ return q;
}
EXPORT_SYMBOL(blk_init_queue_node);
@@ -592,10 +603,8 @@
return NULL;
q->node = node_id;
- if (blk_init_free_list(q)) {
- kmem_cache_free(blk_requestq_cachep, q);
+ if (blk_init_free_list(q))
return NULL;
- }
q->request_fn = rfn;
q->prep_rq_fn = NULL;
@@ -618,7 +627,6 @@
return q;
}
- blk_put_queue(q);
return NULL;
}
EXPORT_SYMBOL(blk_init_allocated_queue_node);
@@ -1141,13 +1149,10 @@
else
req->cmd_flags |= bio->bi_rw & REQ_FAILFAST_MASK;
- if (unlikely(bio_rw_flagged(bio, BIO_RW_DISCARD))) {
+ if (bio_rw_flagged(bio, BIO_RW_DISCARD))
req->cmd_flags |= REQ_DISCARD;
- if (bio_rw_flagged(bio, BIO_RW_BARRIER))
- req->cmd_flags |= REQ_SOFTBARRIER;
- } else if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER)))
+ if (bio_rw_flagged(bio, BIO_RW_BARRIER))
req->cmd_flags |= REQ_HARDBARRIER;
-
if (bio_rw_flagged(bio, BIO_RW_SYNCIO))
req->cmd_flags |= REQ_RW_SYNC;
if (bio_rw_flagged(bio, BIO_RW_META))
@@ -1578,7 +1583,7 @@
* If it's a regular read/write or a barrier with data attached,
* go through the normal accounting stuff before submission.
*/
- if (bio_has_data(bio)) {
+ if (bio_has_data(bio) && !(rw & (1 << BIO_RW_DISCARD))) {
if (rw & WRITE) {
count_vm_events(PGPGOUT, count);
} else {
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index ed897b5..7982b83 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -14,7 +14,7 @@
#include <linux/rbtree.h>
#include <linux/ioprio.h>
#include <linux/blktrace_api.h>
-#include "blk-cgroup.h"
+#include "cfq.h"
/*
* tunables
@@ -64,6 +64,9 @@
static struct completion *ioc_gone;
static DEFINE_SPINLOCK(ioc_gone_lock);
+static DEFINE_SPINLOCK(cic_index_lock);
+static DEFINE_IDA(cic_index_ida);
+
#define CFQ_PRIO_LISTS IOPRIO_BE_NR
#define cfq_class_idle(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE)
#define cfq_class_rt(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_RT)
@@ -271,6 +274,7 @@
unsigned int cfq_latency;
unsigned int cfq_group_isolation;
+ unsigned int cic_index;
struct list_head cic_list;
/*
@@ -430,6 +434,24 @@
cic->cfqq[is_sync] = cfqq;
}
+#define CIC_DEAD_KEY 1ul
+#define CIC_DEAD_INDEX_SHIFT 1
+
+static inline void *cfqd_dead_key(struct cfq_data *cfqd)
+{
+ return (void *)(cfqd->cic_index << CIC_DEAD_INDEX_SHIFT | CIC_DEAD_KEY);
+}
+
+static inline struct cfq_data *cic_to_cfqd(struct cfq_io_context *cic)
+{
+ struct cfq_data *cfqd = cic->key;
+
+ if (unlikely((unsigned long) cfqd & CIC_DEAD_KEY))
+ return NULL;
+
+ return cfqd;
+}
+
/*
* We regard a request as SYNC, if it's either a read or has the SYNC bit
* set (in which case it could also be direct WRITE).
@@ -857,7 +879,7 @@
if (!RB_EMPTY_NODE(&cfqg->rb_node))
cfq_rb_erase(&cfqg->rb_node, st);
cfqg->saved_workload_slice = 0;
- blkiocg_update_dequeue_stats(&cfqg->blkg, 1);
+ cfq_blkiocg_update_dequeue_stats(&cfqg->blkg, 1);
}
static inline unsigned int cfq_cfqq_slice_usage(struct cfq_queue *cfqq)
@@ -917,8 +939,8 @@
cfq_log_cfqg(cfqd, cfqg, "served: vt=%llu min_vt=%llu", cfqg->vdisktime,
st->min_vdisktime);
- blkiocg_update_timeslice_used(&cfqg->blkg, used_sl);
- blkiocg_set_start_empty_time(&cfqg->blkg);
+ cfq_blkiocg_update_timeslice_used(&cfqg->blkg, used_sl);
+ cfq_blkiocg_set_start_empty_time(&cfqg->blkg);
}
#ifdef CONFIG_CFQ_GROUP_IOSCHED
@@ -973,7 +995,7 @@
/* Add group onto cgroup list */
sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor);
- blkiocg_add_blkio_group(blkcg, &cfqg->blkg, (void *)cfqd,
+ cfq_blkiocg_add_blkio_group(blkcg, &cfqg->blkg, (void *)cfqd,
MKDEV(major, minor));
cfqg->weight = blkcg_get_weight(blkcg, cfqg->blkg.dev);
@@ -1057,7 +1079,7 @@
* it from cgroup list, then it will take care of destroying
* cfqg also.
*/
- if (!blkiocg_del_blkio_group(&cfqg->blkg))
+ if (!cfq_blkiocg_del_blkio_group(&cfqg->blkg))
cfq_destroy_cfqg(cfqd, cfqg);
}
}
@@ -1399,10 +1421,10 @@
{
elv_rb_del(&cfqq->sort_list, rq);
cfqq->queued[rq_is_sync(rq)]--;
- blkiocg_update_io_remove_stats(&(RQ_CFQG(rq))->blkg, rq_data_dir(rq),
- rq_is_sync(rq));
+ cfq_blkiocg_update_io_remove_stats(&(RQ_CFQG(rq))->blkg,
+ rq_data_dir(rq), rq_is_sync(rq));
cfq_add_rq_rb(rq);
- blkiocg_update_io_add_stats(&(RQ_CFQG(rq))->blkg,
+ cfq_blkiocg_update_io_add_stats(&(RQ_CFQG(rq))->blkg,
&cfqq->cfqd->serving_group->blkg, rq_data_dir(rq),
rq_is_sync(rq));
}
@@ -1460,8 +1482,8 @@
cfq_del_rq_rb(rq);
cfqq->cfqd->rq_queued--;
- blkiocg_update_io_remove_stats(&(RQ_CFQG(rq))->blkg, rq_data_dir(rq),
- rq_is_sync(rq));
+ cfq_blkiocg_update_io_remove_stats(&(RQ_CFQG(rq))->blkg,
+ rq_data_dir(rq), rq_is_sync(rq));
if (rq_is_meta(rq)) {
WARN_ON(!cfqq->meta_pending);
cfqq->meta_pending--;
@@ -1496,8 +1518,8 @@
static void cfq_bio_merged(struct request_queue *q, struct request *req,
struct bio *bio)
{
- blkiocg_update_io_merged_stats(&(RQ_CFQG(req))->blkg, bio_data_dir(bio),
- cfq_bio_sync(bio));
+ cfq_blkiocg_update_io_merged_stats(&(RQ_CFQG(req))->blkg,
+ bio_data_dir(bio), cfq_bio_sync(bio));
}
static void
@@ -1517,8 +1539,8 @@
if (cfqq->next_rq == next)
cfqq->next_rq = rq;
cfq_remove_request(next);
- blkiocg_update_io_merged_stats(&(RQ_CFQG(rq))->blkg, rq_data_dir(next),
- rq_is_sync(next));
+ cfq_blkiocg_update_io_merged_stats(&(RQ_CFQG(rq))->blkg,
+ rq_data_dir(next), rq_is_sync(next));
}
static int cfq_allow_merge(struct request_queue *q, struct request *rq,
@@ -1549,7 +1571,7 @@
static inline void cfq_del_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq)
{
del_timer(&cfqd->idle_slice_timer);
- blkiocg_update_idle_time_stats(&cfqq->cfqg->blkg);
+ cfq_blkiocg_update_idle_time_stats(&cfqq->cfqg->blkg);
}
static void __cfq_set_active_queue(struct cfq_data *cfqd,
@@ -1558,7 +1580,7 @@
if (cfqq) {
cfq_log_cfqq(cfqd, cfqq, "set_active wl_prio:%d wl_type:%d",
cfqd->serving_prio, cfqd->serving_type);
- blkiocg_update_avg_queue_size_stats(&cfqq->cfqg->blkg);
+ cfq_blkiocg_update_avg_queue_size_stats(&cfqq->cfqg->blkg);
cfqq->slice_start = 0;
cfqq->dispatch_start = jiffies;
cfqq->allocated_slice = 0;
@@ -1889,7 +1911,7 @@
sl = cfqd->cfq_slice_idle;
mod_timer(&cfqd->idle_slice_timer, jiffies + sl);
- blkiocg_update_set_idle_time_stats(&cfqq->cfqg->blkg);
+ cfq_blkiocg_update_set_idle_time_stats(&cfqq->cfqg->blkg);
cfq_log_cfqq(cfqd, cfqq, "arm_idle: %lu", sl);
}
@@ -1909,7 +1931,7 @@
elv_dispatch_sort(q, rq);
cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]++;
- blkiocg_update_dispatch_stats(&cfqq->cfqg->blkg, blk_rq_bytes(rq),
+ cfq_blkiocg_update_dispatch_stats(&cfqq->cfqg->blkg, blk_rq_bytes(rq),
rq_data_dir(rq), rq_is_sync(rq));
}
@@ -1964,6 +1986,15 @@
int process_refs, new_process_refs;
struct cfq_queue *__cfqq;
+ /*
+ * If there are no process references on the new_cfqq, then it is
+ * unsafe to follow the ->new_cfqq chain as other cfqq's in the
+ * chain may have dropped their last reference (not just their
+ * last process reference).
+ */
+ if (!cfqq_process_refs(new_cfqq))
+ return;
+
/* Avoid a circular list and skip interim queue merges */
while ((__cfqq = new_cfqq->new_cfqq)) {
if (__cfqq == cfqq)
@@ -1972,17 +2003,17 @@
}
process_refs = cfqq_process_refs(cfqq);
+ new_process_refs = cfqq_process_refs(new_cfqq);
/*
* If the process for the cfqq has gone away, there is no
* sense in merging the queues.
*/
- if (process_refs == 0)
+ if (process_refs == 0 || new_process_refs == 0)
return;
/*
* Merge in the direction of the lesser amount of work.
*/
- new_process_refs = cfqq_process_refs(new_cfqq);
if (new_process_refs >= process_refs) {
cfqq->new_cfqq = new_cfqq;
atomic_add(process_refs, &new_cfqq->ref);
@@ -2510,11 +2541,12 @@
static void cic_free_func(struct io_context *ioc, struct cfq_io_context *cic)
{
unsigned long flags;
+ unsigned long dead_key = (unsigned long) cic->key;
- BUG_ON(!cic->dead_key);
+ BUG_ON(!(dead_key & CIC_DEAD_KEY));
spin_lock_irqsave(&ioc->lock, flags);
- radix_tree_delete(&ioc->radix_root, cic->dead_key);
+ radix_tree_delete(&ioc->radix_root, dead_key >> CIC_DEAD_INDEX_SHIFT);
hlist_del_rcu(&cic->cic_list);
spin_unlock_irqrestore(&ioc->lock, flags);
@@ -2537,15 +2569,10 @@
__call_for_each_cic(ioc, cic_free_func);
}
-static void cfq_exit_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq)
+static void cfq_put_cooperator(struct cfq_queue *cfqq)
{
struct cfq_queue *__cfqq, *next;
- if (unlikely(cfqq == cfqd->active_queue)) {
- __cfq_slice_expired(cfqd, cfqq, 0);
- cfq_schedule_dispatch(cfqd);
- }
-
/*
* If this queue was scheduled to merge with another queue, be
* sure to drop the reference taken on that queue (and others in
@@ -2561,6 +2588,16 @@
cfq_put_queue(__cfqq);
__cfqq = next;
}
+}
+
+static void cfq_exit_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq)
+{
+ if (unlikely(cfqq == cfqd->active_queue)) {
+ __cfq_slice_expired(cfqd, cfqq, 0);
+ cfq_schedule_dispatch(cfqd);
+ }
+
+ cfq_put_cooperator(cfqq);
cfq_put_queue(cfqq);
}
@@ -2573,11 +2610,10 @@
list_del_init(&cic->queue_list);
/*
- * Make sure key == NULL is seen for dead queues
+ * Make sure dead mark is seen for dead queues
*/
smp_wmb();
- cic->dead_key = (unsigned long) cic->key;
- cic->key = NULL;
+ cic->key = cfqd_dead_key(cfqd);
if (ioc->ioc_data == cic)
rcu_assign_pointer(ioc->ioc_data, NULL);
@@ -2596,7 +2632,7 @@
static void cfq_exit_single_io_context(struct io_context *ioc,
struct cfq_io_context *cic)
{
- struct cfq_data *cfqd = cic->key;
+ struct cfq_data *cfqd = cic_to_cfqd(cic);
if (cfqd) {
struct request_queue *q = cfqd->queue;
@@ -2609,7 +2645,7 @@
* race between exiting task and queue
*/
smp_read_barrier_depends();
- if (cic->key)
+ if (cic->key == cfqd)
__cfq_exit_single_io_context(cfqd, cic);
spin_unlock_irqrestore(q->queue_lock, flags);
@@ -2689,7 +2725,7 @@
static void changed_ioprio(struct io_context *ioc, struct cfq_io_context *cic)
{
- struct cfq_data *cfqd = cic->key;
+ struct cfq_data *cfqd = cic_to_cfqd(cic);
struct cfq_queue *cfqq;
unsigned long flags;
@@ -2746,7 +2782,7 @@
static void changed_cgroup(struct io_context *ioc, struct cfq_io_context *cic)
{
struct cfq_queue *sync_cfqq = cic_to_cfqq(cic, 1);
- struct cfq_data *cfqd = cic->key;
+ struct cfq_data *cfqd = cic_to_cfqd(cic);
unsigned long flags;
struct request_queue *q;
@@ -2883,12 +2919,13 @@
unsigned long flags;
WARN_ON(!list_empty(&cic->queue_list));
+ BUG_ON(cic->key != cfqd_dead_key(cfqd));
spin_lock_irqsave(&ioc->lock, flags);
BUG_ON(ioc->ioc_data == cic);
- radix_tree_delete(&ioc->radix_root, (unsigned long) cfqd);
+ radix_tree_delete(&ioc->radix_root, cfqd->cic_index);
hlist_del_rcu(&cic->cic_list);
spin_unlock_irqrestore(&ioc->lock, flags);
@@ -2900,7 +2937,6 @@
{
struct cfq_io_context *cic;
unsigned long flags;
- void *k;
if (unlikely(!ioc))
return NULL;
@@ -2917,13 +2953,11 @@
}
do {
- cic = radix_tree_lookup(&ioc->radix_root, (unsigned long) cfqd);
+ cic = radix_tree_lookup(&ioc->radix_root, cfqd->cic_index);
rcu_read_unlock();
if (!cic)
break;
- /* ->key must be copied to avoid race with cfq_exit_queue() */
- k = cic->key;
- if (unlikely(!k)) {
+ if (unlikely(cic->key != cfqd)) {
cfq_drop_dead_cic(cfqd, ioc, cic);
rcu_read_lock();
continue;
@@ -2956,7 +2990,7 @@
spin_lock_irqsave(&ioc->lock, flags);
ret = radix_tree_insert(&ioc->radix_root,
- (unsigned long) cfqd, cic);
+ cfqd->cic_index, cic);
if (!ret)
hlist_add_head_rcu(&cic->cic_list, &ioc->cic_list);
spin_unlock_irqrestore(&ioc->lock, flags);
@@ -3223,7 +3257,7 @@
cfq_clear_cfqq_wait_request(cfqq);
__blk_run_queue(cfqd->queue);
} else {
- blkiocg_update_idle_time_stats(
+ cfq_blkiocg_update_idle_time_stats(
&cfqq->cfqg->blkg);
cfq_mark_cfqq_must_dispatch(cfqq);
}
@@ -3251,7 +3285,7 @@
rq_set_fifo_time(rq, jiffies + cfqd->cfq_fifo_expire[rq_is_sync(rq)]);
list_add_tail(&rq->queuelist, &cfqq->fifo);
cfq_add_rq_rb(rq);
- blkiocg_update_io_add_stats(&(RQ_CFQG(rq))->blkg,
+ cfq_blkiocg_update_io_add_stats(&(RQ_CFQG(rq))->blkg,
&cfqd->serving_group->blkg, rq_data_dir(rq),
rq_is_sync(rq));
cfq_rq_enqueued(cfqd, cfqq, rq);
@@ -3339,9 +3373,9 @@
WARN_ON(!cfqq->dispatched);
cfqd->rq_in_driver--;
cfqq->dispatched--;
- blkiocg_update_completion_stats(&cfqq->cfqg->blkg, rq_start_time_ns(rq),
- rq_io_start_time_ns(rq), rq_data_dir(rq),
- rq_is_sync(rq));
+ cfq_blkiocg_update_completion_stats(&cfqq->cfqg->blkg,
+ rq_start_time_ns(rq), rq_io_start_time_ns(rq),
+ rq_data_dir(rq), rq_is_sync(rq));
cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]--;
@@ -3516,6 +3550,9 @@
}
cic_set_cfqq(cic, NULL, 1);
+
+ cfq_put_cooperator(cfqq);
+
cfq_put_queue(cfqq);
return NULL;
}
@@ -3702,16 +3739,38 @@
cfq_put_async_queues(cfqd);
cfq_release_cfq_groups(cfqd);
- blkiocg_del_blkio_group(&cfqd->root_group.blkg);
+ cfq_blkiocg_del_blkio_group(&cfqd->root_group.blkg);
spin_unlock_irq(q->queue_lock);
cfq_shutdown_timer_wq(cfqd);
+ spin_lock(&cic_index_lock);
+ ida_remove(&cic_index_ida, cfqd->cic_index);
+ spin_unlock(&cic_index_lock);
+
/* Wait for cfqg->blkg->key accessors to exit their grace periods. */
call_rcu(&cfqd->rcu, cfq_cfqd_free);
}
+static int cfq_alloc_cic_index(void)
+{
+ int index, error;
+
+ do {
+ if (!ida_pre_get(&cic_index_ida, GFP_KERNEL))
+ return -ENOMEM;
+
+ spin_lock(&cic_index_lock);
+ error = ida_get_new(&cic_index_ida, &index);
+ spin_unlock(&cic_index_lock);
+ if (error && error != -EAGAIN)
+ return error;
+ } while (error);
+
+ return index;
+}
+
static void *cfq_init_queue(struct request_queue *q)
{
struct cfq_data *cfqd;
@@ -3719,10 +3778,16 @@
struct cfq_group *cfqg;
struct cfq_rb_root *st;
+ i = cfq_alloc_cic_index();
+ if (i < 0)
+ return NULL;
+
cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL | __GFP_ZERO, q->node);
if (!cfqd)
return NULL;
+ cfqd->cic_index = i;
+
/* Init root service tree */
cfqd->grp_service_tree = CFQ_RB_ROOT;
@@ -3742,8 +3807,8 @@
*/
atomic_set(&cfqg->ref, 1);
rcu_read_lock();
- blkiocg_add_blkio_group(&blkio_root_cgroup, &cfqg->blkg, (void *)cfqd,
- 0);
+ cfq_blkiocg_add_blkio_group(&blkio_root_cgroup, &cfqg->blkg,
+ (void *)cfqd, 0);
rcu_read_unlock();
#endif
/*
@@ -3984,6 +4049,7 @@
*/
if (elv_ioc_count_read(cfq_ioc_count))
wait_for_completion(&all_gone);
+ ida_destroy(&cic_index_ida);
cfq_slab_kill();
}
diff --git a/block/cfq.h b/block/cfq.h
new file mode 100644
index 0000000..93448e5
--- /dev/null
+++ b/block/cfq.h
@@ -0,0 +1,115 @@
+#ifndef _CFQ_H
+#define _CFQ_H
+#include "blk-cgroup.h"
+
+#ifdef CONFIG_CFQ_GROUP_IOSCHED
+static inline void cfq_blkiocg_update_io_add_stats(struct blkio_group *blkg,
+ struct blkio_group *curr_blkg, bool direction, bool sync)
+{
+ blkiocg_update_io_add_stats(blkg, curr_blkg, direction, sync);
+}
+
+static inline void cfq_blkiocg_update_dequeue_stats(struct blkio_group *blkg,
+ unsigned long dequeue)
+{
+ blkiocg_update_dequeue_stats(blkg, dequeue);
+}
+
+static inline void cfq_blkiocg_update_timeslice_used(struct blkio_group *blkg,
+ unsigned long time)
+{
+ blkiocg_update_timeslice_used(blkg, time);
+}
+
+static inline void cfq_blkiocg_set_start_empty_time(struct blkio_group *blkg)
+{
+ blkiocg_set_start_empty_time(blkg);
+}
+
+static inline void cfq_blkiocg_update_io_remove_stats(struct blkio_group *blkg,
+ bool direction, bool sync)
+{
+ blkiocg_update_io_remove_stats(blkg, direction, sync);
+}
+
+static inline void cfq_blkiocg_update_io_merged_stats(struct blkio_group *blkg,
+ bool direction, bool sync)
+{
+ blkiocg_update_io_merged_stats(blkg, direction, sync);
+}
+
+static inline void cfq_blkiocg_update_idle_time_stats(struct blkio_group *blkg)
+{
+ blkiocg_update_idle_time_stats(blkg);
+}
+
+static inline void
+cfq_blkiocg_update_avg_queue_size_stats(struct blkio_group *blkg)
+{
+ blkiocg_update_avg_queue_size_stats(blkg);
+}
+
+static inline void
+cfq_blkiocg_update_set_idle_time_stats(struct blkio_group *blkg)
+{
+ blkiocg_update_set_idle_time_stats(blkg);
+}
+
+static inline void cfq_blkiocg_update_dispatch_stats(struct blkio_group *blkg,
+ uint64_t bytes, bool direction, bool sync)
+{
+ blkiocg_update_dispatch_stats(blkg, bytes, direction, sync);
+}
+
+static inline void cfq_blkiocg_update_completion_stats(struct blkio_group *blkg, uint64_t start_time, uint64_t io_start_time, bool direction, bool sync)
+{
+ blkiocg_update_completion_stats(blkg, start_time, io_start_time,
+ direction, sync);
+}
+
+static inline void cfq_blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
+ struct blkio_group *blkg, void *key, dev_t dev) {
+ blkiocg_add_blkio_group(blkcg, blkg, key, dev);
+}
+
+static inline int cfq_blkiocg_del_blkio_group(struct blkio_group *blkg)
+{
+ return blkiocg_del_blkio_group(blkg);
+}
+
+#else /* CFQ_GROUP_IOSCHED */
+static inline void cfq_blkiocg_update_io_add_stats(struct blkio_group *blkg,
+ struct blkio_group *curr_blkg, bool direction, bool sync) {}
+
+static inline void cfq_blkiocg_update_dequeue_stats(struct blkio_group *blkg,
+ unsigned long dequeue) {}
+
+static inline void cfq_blkiocg_update_timeslice_used(struct blkio_group *blkg,
+ unsigned long time) {}
+static inline void cfq_blkiocg_set_start_empty_time(struct blkio_group *blkg) {}
+static inline void cfq_blkiocg_update_io_remove_stats(struct blkio_group *blkg,
+ bool direction, bool sync) {}
+static inline void cfq_blkiocg_update_io_merged_stats(struct blkio_group *blkg,
+ bool direction, bool sync) {}
+static inline void cfq_blkiocg_update_idle_time_stats(struct blkio_group *blkg)
+{
+}
+static inline void
+cfq_blkiocg_update_avg_queue_size_stats(struct blkio_group *blkg) {}
+
+static inline void
+cfq_blkiocg_update_set_idle_time_stats(struct blkio_group *blkg) {}
+
+static inline void cfq_blkiocg_update_dispatch_stats(struct blkio_group *blkg,
+ uint64_t bytes, bool direction, bool sync) {}
+static inline void cfq_blkiocg_update_completion_stats(struct blkio_group *blkg, uint64_t start_time, uint64_t io_start_time, bool direction, bool sync) {}
+
+static inline void cfq_blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
+ struct blkio_group *blkg, void *key, dev_t dev) {}
+static inline int cfq_blkiocg_del_blkio_group(struct blkio_group *blkg)
+{
+ return 0;
+}
+
+#endif /* CFQ_GROUP_IOSCHED */
+#endif
diff --git a/block/elevator.c b/block/elevator.c
index 6df2b50..923a913 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -242,9 +242,11 @@
{
struct elevator_type *e = NULL;
struct elevator_queue *eq;
- int ret = 0;
void *data;
+ if (unlikely(q->elevator))
+ return 0;
+
INIT_LIST_HEAD(&q->queue_head);
q->last_merge = NULL;
q->end_sector = 0;
@@ -284,7 +286,7 @@
}
elevator_attach(q, eq, data);
- return ret;
+ return 0;
}
EXPORT_SYMBOL(elevator_init);
@@ -1097,7 +1099,7 @@
struct elevator_type *__e;
int len = 0;
- if (!q->elevator)
+ if (!q->elevator || !blk_queue_stackable(q))
return sprintf(name, "none\n");
elv = e->elevator_type;
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
index d269a8f..446aced 100644
--- a/drivers/acpi/acpi_pad.c
+++ b/drivers/acpi/acpi_pad.c
@@ -46,6 +46,8 @@
static unsigned char tsc_detected_unstable;
static unsigned char tsc_marked_unstable;
+static unsigned char lapic_detected_unstable;
+static unsigned char lapic_marked_unstable;
static void power_saving_mwait_init(void)
{
@@ -75,9 +77,6 @@
power_saving_mwait_eax = (highest_cstate << MWAIT_SUBSTATE_SIZE) |
(highest_subcstate - 1);
- for_each_online_cpu(i)
- clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &i);
-
#if defined(CONFIG_GENERIC_TIME) && defined(CONFIG_X86)
switch (boot_cpu_data.x86_vendor) {
case X86_VENDOR_AMD:
@@ -86,13 +85,15 @@
* AMD Fam10h TSC will tick in all
* C/P/S0/S1 states when this bit is set.
*/
- if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
- return;
-
- /*FALL THROUGH*/
+ if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
+ tsc_detected_unstable = 1;
+ if (!boot_cpu_has(X86_FEATURE_ARAT))
+ lapic_detected_unstable = 1;
+ break;
default:
- /* TSC could halt in idle */
+ /* TSC & LAPIC could halt in idle */
tsc_detected_unstable = 1;
+ lapic_detected_unstable = 1;
}
#endif
}
@@ -180,10 +181,20 @@
mark_tsc_unstable("TSC halts in idle");
tsc_marked_unstable = 1;
}
+ if (lapic_detected_unstable && !lapic_marked_unstable) {
+ int i;
+ /* LAPIC could halt in idle, so notify users */
+ for_each_online_cpu(i)
+ clockevents_notify(
+ CLOCK_EVT_NOTIFY_BROADCAST_ON,
+ &i);
+ lapic_marked_unstable = 1;
+ }
local_irq_disable();
cpu = smp_processor_id();
- clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
- &cpu);
+ if (lapic_marked_unstable)
+ clockevents_notify(
+ CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
stop_critical_timings();
__monitor((void *)¤t_thread_info()->flags, 0, 0);
@@ -192,8 +203,9 @@
__mwait(power_saving_mwait_eax, 1);
start_critical_timings();
- clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
- &cpu);
+ if (lapic_marked_unstable)
+ clockevents_notify(
+ CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
local_irq_enable();
if (jiffies > expire_time) {
diff --git a/drivers/acpi/acpica/acconfig.h b/drivers/acpi/acpica/acconfig.h
index 33181ad..b17d8de 100644
--- a/drivers/acpi/acpica/acconfig.h
+++ b/drivers/acpi/acpica/acconfig.h
@@ -119,6 +119,10 @@
#define ACPI_MAX_LOOP_ITERATIONS 0xFFFF
+/* Maximum sleep allowed via Sleep() operator */
+
+#define ACPI_MAX_SLEEP 20000 /* Two seconds */
+
/******************************************************************************
*
* ACPI Specification constants (Do not change unless the specification changes)
diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h
index 64d1e5c..c3f43da 100644
--- a/drivers/acpi/acpica/acevents.h
+++ b/drivers/acpi/acpica/acevents.h
@@ -80,10 +80,6 @@
acpi_status
acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info);
-acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info);
-
-acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info);
-
struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
u32 gpe_number);
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index 9070f1f..899d68a 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -125,6 +125,14 @@
*/
u8 ACPI_INIT_GLOBAL(acpi_gbl_copy_dsdt_locally, FALSE);
+/*
+ * Optionally truncate I/O addresses to 16 bits. Provides compatibility
+ * with other ACPI implementations. NOTE: During ACPICA initialization,
+ * this value is set to TRUE if any Windows OSI strings have been
+ * requested by the BIOS.
+ */
+u8 ACPI_INIT_GLOBAL(acpi_gbl_truncate_io_addresses, FALSE);
+
/* acpi_gbl_FADT is a local copy of the FADT, converted to a common format. */
struct acpi_table_fadt acpi_gbl_FADT;
diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h
index 5900f13..3239158 100644
--- a/drivers/acpi/acpica/achware.h
+++ b/drivers/acpi/acpica/achware.h
@@ -90,7 +90,11 @@
/*
* hwgpe - GPE support
*/
-acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info);
+u32 acpi_hw_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info,
+ struct acpi_gpe_register_info *gpe_register_info);
+
+acpi_status
+acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action);
acpi_status
acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info *gpe_event_info);
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c
index a221ad4..7c2c336 100644
--- a/drivers/acpi/acpica/evgpe.c
+++ b/drivers/acpi/acpica/evgpe.c
@@ -69,7 +69,7 @@
acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)
{
struct acpi_gpe_register_info *gpe_register_info;
- u8 register_bit;
+ u32 register_bit;
ACPI_FUNCTION_TRACE(ev_update_gpe_enable_masks);
@@ -78,9 +78,8 @@
return_ACPI_STATUS(AE_NOT_EXIST);
}
- register_bit = (u8)
- (1 <<
- (gpe_event_info->gpe_number - gpe_register_info->base_gpe_number));
+ register_bit = acpi_hw_gpe_register_bit(gpe_event_info,
+ gpe_register_info);
/* Clear the wake/run bits up front */
@@ -100,106 +99,6 @@
return_ACPI_STATUS(AE_OK);
}
-/*******************************************************************************
- *
- * FUNCTION: acpi_ev_enable_gpe
- *
- * PARAMETERS: gpe_event_info - GPE to enable
- *
- * RETURN: Status
- *
- * DESCRIPTION: Hardware-enable a GPE. Always enables the GPE, regardless
- * of type or number of references.
- *
- * Note: The GPE lock should be already acquired when this function is called.
- *
- ******************************************************************************/
-
-acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
-{
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE(ev_enable_gpe);
-
-
- /*
- * We will only allow a GPE to be enabled if it has either an
- * associated method (_Lxx/_Exx) or a handler. Otherwise, the
- * GPE will be immediately disabled by acpi_ev_gpe_dispatch the
- * first time it fires.
- */
- if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) {
- return_ACPI_STATUS(AE_NO_HANDLER);
- }
-
- /* Ensure the HW enable masks are current */
-
- status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
-
- /* Clear the GPE (of stale events) */
-
- status = acpi_hw_clear_gpe(gpe_event_info);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
-
- /* Enable the requested GPE */
-
- status = acpi_hw_write_gpe_enable_reg(gpe_event_info);
- return_ACPI_STATUS(status);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ev_disable_gpe
- *
- * PARAMETERS: gpe_event_info - GPE to disable
- *
- * RETURN: Status
- *
- * DESCRIPTION: Hardware-disable a GPE. Always disables the requested GPE,
- * regardless of the type or number of references.
- *
- * Note: The GPE lock should be already acquired when this function is called.
- *
- ******************************************************************************/
-
-acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
-{
- acpi_status status;
-
- ACPI_FUNCTION_TRACE(ev_disable_gpe);
-
-
- /*
- * Note: Always disable the GPE, even if we think that that it is already
- * disabled. It is possible that the AML or some other code has enabled
- * the GPE behind our back.
- */
-
- /* Ensure the HW enable masks are current */
-
- status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
-
- /*
- * Always H/W disable this GPE, even if we don't know the GPE type.
- * Simply clear the enable bit for this particular GPE, but do not
- * write out the current GPE enable mask since this may inadvertently
- * enable GPEs too early. An example is a rogue GPE that has arrived
- * during ACPICA initialization - possibly because AML or other code
- * has enabled the GPE.
- */
- status = acpi_hw_low_disable_gpe(gpe_event_info);
- return_ACPI_STATUS(status);
-}
-
/*******************************************************************************
*
@@ -451,10 +350,6 @@
return_VOID;
}
- /* Update the GPE register masks for return to enabled state */
-
- (void)acpi_ev_update_gpe_enable_masks(gpe_event_info);
-
/*
* Take a snapshot of the GPE info for this level - we copy the info to
* prevent a race condition with remove_handler/remove_block.
@@ -607,7 +502,7 @@
* Disable the GPE, so it doesn't keep firing before the method has a
* chance to run (it runs asynchronously with interrupts enabled).
*/
- status = acpi_ev_disable_gpe(gpe_event_info);
+ status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Unable to disable GPE[0x%2X]",
@@ -644,7 +539,7 @@
* Disable the GPE. The GPE will remain disabled a handler
* is installed or ACPICA is restarted.
*/
- status = acpi_ev_disable_gpe(gpe_event_info);
+ status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Unable to disable GPE[0x%2X]",
diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c
index 7c28f2d..341a38c 100644
--- a/drivers/acpi/acpica/evgpeblk.c
+++ b/drivers/acpi/acpica/evgpeblk.c
@@ -500,6 +500,19 @@
gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j;
gpe_event_info = &gpe_block->event_info[gpe_index];
+ gpe_number = gpe_index + gpe_block->block_base_number;
+
+ /*
+ * If the GPE has already been enabled for runtime
+ * signaling, make sure it remains enabled, but do not
+ * increment its reference counter.
+ */
+ if (gpe_event_info->runtime_count) {
+ acpi_set_gpe(gpe_device, gpe_number,
+ ACPI_GPE_ENABLE);
+ gpe_enabled_count++;
+ continue;
+ }
if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) {
wake_gpe_count++;
@@ -516,7 +529,6 @@
/* Enable this GPE */
- gpe_number = gpe_index + gpe_block->block_base_number;
status = acpi_enable_gpe(gpe_device, gpe_number,
ACPI_GPE_TYPE_RUNTIME);
if (ACPI_FAILURE(status)) {
diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c
index cc82502..4a531cd 100644
--- a/drivers/acpi/acpica/evxface.c
+++ b/drivers/acpi/acpica/evxface.c
@@ -719,13 +719,6 @@
handler->context = context;
handler->method_node = gpe_event_info->dispatch.method_node;
- /* Disable the GPE before installing the handler */
-
- status = acpi_ev_disable_gpe(gpe_event_info);
- if (ACPI_FAILURE (status)) {
- goto unlock_and_exit;
- }
-
/* Install the handler */
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c
index d5a5efc..d97b8dc 100644
--- a/drivers/acpi/acpica/evxfevnt.c
+++ b/drivers/acpi/acpica/evxfevnt.c
@@ -210,6 +210,44 @@
/*******************************************************************************
*
+ * FUNCTION: acpi_clear_and_enable_gpe
+ *
+ * PARAMETERS: gpe_event_info - GPE to enable
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Clear the given GPE from stale events and enable it.
+ *
+ ******************************************************************************/
+static acpi_status
+acpi_clear_and_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
+{
+ acpi_status status;
+
+ /*
+ * We will only allow a GPE to be enabled if it has either an
+ * associated method (_Lxx/_Exx) or a handler. Otherwise, the
+ * GPE will be immediately disabled by acpi_ev_gpe_dispatch the
+ * first time it fires.
+ */
+ if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) {
+ return_ACPI_STATUS(AE_NO_HANDLER);
+ }
+
+ /* Clear the GPE (of stale events) */
+ status = acpi_hw_clear_gpe(gpe_event_info);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ /* Enable the requested GPE */
+ status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE);
+
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_set_gpe
*
* PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
@@ -249,11 +287,11 @@
switch (action) {
case ACPI_GPE_ENABLE:
- status = acpi_ev_enable_gpe(gpe_event_info);
+ status = acpi_clear_and_enable_gpe(gpe_event_info);
break;
case ACPI_GPE_DISABLE:
- status = acpi_ev_disable_gpe(gpe_event_info);
+ status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
break;
default:
@@ -316,7 +354,11 @@
gpe_event_info->runtime_count++;
if (gpe_event_info->runtime_count == 1) {
- status = acpi_ev_enable_gpe(gpe_event_info);
+ status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
+ if (ACPI_SUCCESS(status)) {
+ status = acpi_clear_and_enable_gpe(gpe_event_info);
+ }
+
if (ACPI_FAILURE(status)) {
gpe_event_info->runtime_count--;
goto unlock_and_exit;
@@ -343,7 +385,7 @@
*/
gpe_event_info->wakeup_count++;
if (gpe_event_info->wakeup_count == 1) {
- (void)acpi_ev_update_gpe_enable_masks(gpe_event_info);
+ status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
}
}
@@ -403,7 +445,12 @@
gpe_event_info->runtime_count--;
if (!gpe_event_info->runtime_count) {
- status = acpi_ev_disable_gpe(gpe_event_info);
+ status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
+ if (ACPI_SUCCESS(status)) {
+ status = acpi_hw_low_set_gpe(gpe_event_info,
+ ACPI_GPE_DISABLE);
+ }
+
if (ACPI_FAILURE(status)) {
gpe_event_info->runtime_count++;
goto unlock_and_exit;
@@ -424,7 +471,7 @@
gpe_event_info->wakeup_count--;
if (!gpe_event_info->wakeup_count) {
- (void)acpi_ev_update_gpe_enable_masks(gpe_event_info);
+ status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
}
}
diff --git a/drivers/acpi/acpica/exsystem.c b/drivers/acpi/acpica/exsystem.c
index 6d32e09..675aaa9 100644
--- a/drivers/acpi/acpica/exsystem.c
+++ b/drivers/acpi/acpica/exsystem.c
@@ -201,6 +201,14 @@
acpi_ex_relinquish_interpreter();
+ /*
+ * For compatibility with other ACPI implementations and to prevent
+ * accidental deep sleeps, limit the sleep time to something reasonable.
+ */
+ if (how_long > ACPI_MAX_SLEEP) {
+ how_long = ACPI_MAX_SLEEP;
+ }
+
acpi_os_sleep(how_long);
/* And now we must get the interpreter again */
diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c
index bd72319..3450309 100644
--- a/drivers/acpi/acpica/hwgpe.c
+++ b/drivers/acpi/acpica/hwgpe.c
@@ -57,21 +57,47 @@
/******************************************************************************
*
- * FUNCTION: acpi_hw_low_disable_gpe
+ * FUNCTION: acpi_hw_gpe_register_bit
*
- * PARAMETERS: gpe_event_info - Info block for the GPE to be disabled
+ * PARAMETERS: gpe_event_info - Info block for the GPE
+ * gpe_register_info - Info block for the GPE register
*
* RETURN: Status
*
- * DESCRIPTION: Disable a single GPE in the enable register.
+ * DESCRIPTION: Compute GPE enable mask with one bit corresponding to the given
+ * GPE set.
*
******************************************************************************/
-acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
+u32 acpi_hw_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info,
+ struct acpi_gpe_register_info *gpe_register_info)
+{
+ return (u32)1 << (gpe_event_info->gpe_number -
+ gpe_register_info->base_gpe_number);
+}
+
+/******************************************************************************
+ *
+ * FUNCTION: acpi_hw_low_set_gpe
+ *
+ * PARAMETERS: gpe_event_info - Info block for the GPE to be disabled
+ * action - Enable or disable
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Enable or disable a single GPE in its enable register.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action)
{
struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
u32 enable_mask;
+ u32 register_bit;
+
+ ACPI_FUNCTION_ENTRY();
/* Get the info block for the entire GPE register */
@@ -87,11 +113,27 @@
return (status);
}
- /* Clear just the bit that corresponds to this GPE */
+ /* Set ot clear just the bit that corresponds to this GPE */
- ACPI_CLEAR_BIT(enable_mask, ((u32)1 <<
- (gpe_event_info->gpe_number -
- gpe_register_info->base_gpe_number)));
+ register_bit = acpi_hw_gpe_register_bit(gpe_event_info,
+ gpe_register_info);
+ switch (action) {
+ case ACPI_GPE_COND_ENABLE:
+ if (!(register_bit & gpe_register_info->enable_for_run))
+ return (AE_BAD_PARAMETER);
+
+ case ACPI_GPE_ENABLE:
+ ACPI_SET_BIT(enable_mask, register_bit);
+ break;
+
+ case ACPI_GPE_DISABLE:
+ ACPI_CLEAR_BIT(enable_mask, register_bit);
+ break;
+
+ default:
+ ACPI_ERROR((AE_INFO, "Invalid action\n"));
+ return (AE_BAD_PARAMETER);
+ }
/* Write the updated enable mask */
@@ -116,23 +158,11 @@
acpi_status
acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info)
{
- struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
ACPI_FUNCTION_ENTRY();
- /* Get the info block for the entire GPE register */
-
- gpe_register_info = gpe_event_info->register_info;
- if (!gpe_register_info) {
- return (AE_NOT_EXIST);
- }
-
- /* Write the entire GPE (runtime) enable register */
-
- status = acpi_hw_write(gpe_register_info->enable_for_run,
- &gpe_register_info->enable_address);
-
+ status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_COND_ENABLE);
return (status);
}
@@ -150,21 +180,28 @@
acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
{
+ struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
- u8 register_bit;
+ u32 register_bit;
ACPI_FUNCTION_ENTRY();
- register_bit = (u8)(1 <<
- (gpe_event_info->gpe_number -
- gpe_event_info->register_info->base_gpe_number));
+ /* Get the info block for the entire GPE register */
+
+ gpe_register_info = gpe_event_info->register_info;
+ if (!gpe_register_info) {
+ return (AE_NOT_EXIST);
+ }
+
+ register_bit = acpi_hw_gpe_register_bit(gpe_event_info,
+ gpe_register_info);
/*
* Write a one to the appropriate bit in the status register to
* clear this GPE.
*/
status = acpi_hw_write(register_bit,
- &gpe_event_info->register_info->status_address);
+ &gpe_register_info->status_address);
return (status);
}
@@ -187,7 +224,7 @@
acpi_event_status * event_status)
{
u32 in_byte;
- u8 register_bit;
+ u32 register_bit;
struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
acpi_event_status local_event_status = 0;
@@ -204,9 +241,8 @@
/* Get the register bitmask for this GPE */
- register_bit = (u8)(1 <<
- (gpe_event_info->gpe_number -
- gpe_event_info->register_info->base_gpe_number));
+ register_bit = acpi_hw_gpe_register_bit(gpe_event_info,
+ gpe_register_info);
/* GPE currently enabled? (enabled for runtime?) */
diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c
index c10d587..e1d9c77 100644
--- a/drivers/acpi/acpica/hwvalid.c
+++ b/drivers/acpi/acpica/hwvalid.c
@@ -222,6 +222,12 @@
u32 one_byte;
u32 i;
+ /* Truncate address to 16 bits if requested */
+
+ if (acpi_gbl_truncate_io_addresses) {
+ address &= ACPI_UINT16_MAX;
+ }
+
/* Validate the entire request and perform the I/O */
status = acpi_hw_validate_io_request(address, width);
@@ -279,6 +285,12 @@
acpi_status status;
u32 i;
+ /* Truncate address to 16 bits if requested */
+
+ if (acpi_gbl_truncate_io_addresses) {
+ address &= ACPI_UINT16_MAX;
+ }
+
/* Validate the entire request and perform the I/O */
status = acpi_hw_validate_io_request(address, width);
diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c
index 9bd6f05..4e5272c 100644
--- a/drivers/acpi/acpica/nsinit.c
+++ b/drivers/acpi/acpica/nsinit.c
@@ -193,6 +193,15 @@
acpi_ns_init_one_device, NULL, &info,
NULL);
+ /*
+ * Any _OSI requests should be completed by now. If the BIOS has
+ * requested any Windows OSI strings, we will always truncate
+ * I/O addresses to 16 bits -- for Windows compatibility.
+ */
+ if (acpi_gbl_osi_data >= ACPI_OSI_WIN_2000) {
+ acpi_gbl_truncate_io_addresses = TRUE;
+ }
+
ACPI_FREE(info.evaluate_info);
if (ACPI_FAILURE(status)) {
goto error_exit;
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c
index db3946e..216e1e9 100644
--- a/drivers/acpi/apei/apei-base.c
+++ b/drivers/acpi/apei/apei-base.c
@@ -34,6 +34,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/acpi.h>
+#include <linux/slab.h>
#include <linux/io.h>
#include <linux/kref.h>
#include <linux/rculist.h>
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index 2ebc391..864dd46 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -781,7 +781,7 @@
status = acpi_get_table(ACPI_SIG_ERST, 0,
(struct acpi_table_header **)&erst_tab);
if (status == AE_NOT_FOUND) {
- pr_err(ERST_PFX "Table is not found!\n");
+ pr_info(ERST_PFX "Table is not found!\n");
goto err;
} else if (ACPI_FAILURE(status)) {
const char *msg = acpi_format_exception(status);
diff --git a/drivers/acpi/atomicio.c b/drivers/acpi/atomicio.c
index 814b192..8f8bd73 100644
--- a/drivers/acpi/atomicio.c
+++ b/drivers/acpi/atomicio.c
@@ -31,6 +31,7 @@
#include <linux/kref.h>
#include <linux/rculist.h>
#include <linux/interrupt.h>
+#include <linux/slab.h>
#include <acpi/atomicio.h>
#define ACPI_PFX "ACPI: "
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
index 2815df6..01381be 100644
--- a/drivers/acpi/blacklist.c
+++ b/drivers/acpi/blacklist.c
@@ -218,6 +218,14 @@
},
},
{
+ .callback = dmi_disable_osi_vista,
+ .ident = "VGN-NS50B_L",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS50B_L"),
+ },
+ },
+ {
.callback = dmi_disable_osi_win7,
.ident = "ASUS K50IJ",
.matches = {
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index fd51c4a..7d857da 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -425,7 +425,7 @@
/* Button's GPE is run-wake GPE */
acpi_enable_gpe(device->wakeup.gpe_device,
device->wakeup.gpe_number,
- ACPI_GPE_TYPE_WAKE_RUN);
+ ACPI_GPE_TYPE_RUNTIME);
device->wakeup.run_wake_count++;
device->wakeup.state.enabled = 1;
}
@@ -449,7 +449,7 @@
if (device->wakeup.flags.valid) {
acpi_disable_gpe(device->wakeup.gpe_device,
device->wakeup.gpe_number,
- ACPI_GPE_TYPE_WAKE_RUN);
+ ACPI_GPE_TYPE_RUNTIME);
device->wakeup.run_wake_count--;
device->wakeup.state.enabled = 0;
}
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index e61d4f8..5f2027d 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -79,7 +79,7 @@
EC_FLAGS_GPE_STORM, /* GPE storm detected */
EC_FLAGS_HANDLERS_INSTALLED, /* Handlers for GPE and
* OpReg are installed */
- EC_FLAGS_FROZEN, /* Transactions are suspended */
+ EC_FLAGS_BLOCKED, /* Transactions are blocked */
};
/* If we find an EC via the ECDT, we need to keep a ptr to its context */
@@ -293,7 +293,7 @@
if (t->rdata)
memset(t->rdata, 0, t->rlen);
mutex_lock(&ec->lock);
- if (test_bit(EC_FLAGS_FROZEN, &ec->flags)) {
+ if (test_bit(EC_FLAGS_BLOCKED, &ec->flags)) {
status = -EINVAL;
goto unlock;
}
@@ -459,7 +459,7 @@
EXPORT_SYMBOL(ec_transaction);
-void acpi_ec_suspend_transactions(void)
+void acpi_ec_block_transactions(void)
{
struct acpi_ec *ec = first_ec;
@@ -468,11 +468,11 @@
mutex_lock(&ec->lock);
/* Prevent transactions from being carried out */
- set_bit(EC_FLAGS_FROZEN, &ec->flags);
+ set_bit(EC_FLAGS_BLOCKED, &ec->flags);
mutex_unlock(&ec->lock);
}
-void acpi_ec_resume_transactions(void)
+void acpi_ec_unblock_transactions(void)
{
struct acpi_ec *ec = first_ec;
@@ -481,10 +481,20 @@
mutex_lock(&ec->lock);
/* Allow transactions to be carried out again */
- clear_bit(EC_FLAGS_FROZEN, &ec->flags);
+ clear_bit(EC_FLAGS_BLOCKED, &ec->flags);
mutex_unlock(&ec->lock);
}
+void acpi_ec_unblock_transactions_early(void)
+{
+ /*
+ * Allow transactions to happen again (this function is called from
+ * atomic context during wakeup, so we don't need to acquire the mutex).
+ */
+ if (first_ec)
+ clear_bit(EC_FLAGS_BLOCKED, &first_ec->flags);
+}
+
static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data)
{
int result;
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index acf2ab2..8a3b840 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -347,7 +347,6 @@
{
int result = 0;
-
#ifdef CONFIG_ACPI_PROCFS
acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir);
if (!acpi_fan_dir)
@@ -356,7 +355,9 @@
result = acpi_bus_register_driver(&acpi_fan_driver);
if (result < 0) {
+#ifdef CONFIG_ACPI_PROCFS
remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir);
+#endif
return -ENODEV;
}
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index e284113..f8f190e 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -49,8 +49,9 @@
int acpi_ec_init(void);
int acpi_ec_ecdt_probe(void);
int acpi_boot_ec_enable(void);
-void acpi_ec_suspend_transactions(void);
-void acpi_ec_resume_transactions(void);
+void acpi_ec_block_transactions(void);
+void acpi_ec_unblock_transactions(void);
+void acpi_ec_unblock_transactions_early(void);
/*--------------------------------------------------------------------------
Suspend/Resume
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index b1034a9..38ea0cc 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -581,6 +581,11 @@
return 0;
}
+#ifdef CONFIG_SMP
+ if (pr->id >= setup_max_cpus && pr->id != 0)
+ return 0;
+#endif
+
BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));
/*
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 2e8c27d..b1b3856 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -80,7 +80,7 @@
static unsigned int latency_factor __read_mostly = 2;
module_param(latency_factor, uint, 0644);
-static s64 us_to_pm_timer_ticks(s64 t)
+static u64 us_to_pm_timer_ticks(s64 t)
{
return div64_u64(t * PM_TIMER_FREQUENCY, 1000000);
}
@@ -731,10 +731,10 @@
seq_puts(seq, "demotion[--] ");
- seq_printf(seq, "latency[%03d] usage[%08d] duration[%020llu]\n",
+ seq_printf(seq, "latency[%03d] usage[%08d] duration[%020Lu]\n",
pr->power.states[i].latency,
pr->power.states[i].usage,
- (unsigned long long)pr->power.states[i].time);
+ us_to_pm_timer_ticks(pr->power.states[i].time));
}
end:
@@ -861,7 +861,6 @@
ktime_t kt1, kt2;
s64 idle_time_ns;
s64 idle_time;
- s64 sleep_ticks = 0;
pr = __get_cpu_var(processors);
@@ -906,8 +905,6 @@
idle_time = idle_time_ns;
do_div(idle_time, NSEC_PER_USEC);
- sleep_ticks = us_to_pm_timer_ticks(idle_time);
-
/* Tell the scheduler how much we idled: */
sched_clock_idle_wakeup_event(idle_time_ns);
@@ -918,7 +915,7 @@
cx->usage++;
lapic_timer_state_broadcast(pr, cx, 0);
- cx->time += sleep_ticks;
+ cx->time += idle_time;
return idle_time;
}
@@ -940,7 +937,6 @@
ktime_t kt1, kt2;
s64 idle_time_ns;
s64 idle_time;
- s64 sleep_ticks = 0;
pr = __get_cpu_var(processors);
@@ -1022,11 +1018,10 @@
spin_unlock(&c3_lock);
}
kt2 = ktime_get_real();
- idle_time_ns = ktime_to_us(ktime_sub(kt2, kt1));
+ idle_time_ns = ktime_to_ns(ktime_sub(kt2, kt1));
idle_time = idle_time_ns;
do_div(idle_time, NSEC_PER_USEC);
- sleep_ticks = us_to_pm_timer_ticks(idle_time);
/* Tell the scheduler how much we idled: */
sched_clock_idle_wakeup_event(idle_time_ns);
@@ -1037,7 +1032,7 @@
cx->usage++;
lapic_timer_state_broadcast(pr, cx, 0);
- cx->time += sleep_ticks;
+ cx->time += idle_time;
return idle_time;
}
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 4ab2275..5b7c52e 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -94,11 +94,13 @@
}
/**
- * acpi_pm_disable_gpes - Disable the GPEs.
+ * acpi_pm_freeze - Disable the GPEs and suspend EC transactions.
*/
-static int acpi_pm_disable_gpes(void)
+static int acpi_pm_freeze(void)
{
acpi_disable_all_gpes();
+ acpi_os_wait_events_complete(NULL);
+ acpi_ec_block_transactions();
return 0;
}
@@ -112,6 +114,8 @@
{
int error = acpi_sleep_prepare(acpi_target_sleep_state);
+ suspend_nvs_save();
+
if (error)
acpi_target_sleep_state = ACPI_STATE_S0;
return error;
@@ -126,7 +130,8 @@
int error = __acpi_pm_prepare();
if (!error)
- acpi_disable_all_gpes();
+ acpi_pm_freeze();
+
return error;
}
@@ -140,6 +145,9 @@
{
u32 acpi_state = acpi_target_sleep_state;
+ suspend_nvs_free();
+ acpi_ec_unblock_transactions();
+
if (acpi_state == ACPI_STATE_S0)
return;
@@ -189,6 +197,11 @@
u32 acpi_state = acpi_suspend_states[pm_state];
int error = 0;
+ error = suspend_nvs_alloc();
+
+ if (error)
+ return error;
+
if (sleep_states[acpi_state]) {
acpi_target_sleep_state = acpi_state;
acpi_sleep_tts_switch(acpi_target_sleep_state);
@@ -256,6 +269,8 @@
* acpi_leave_sleep_state will reenable specific GPEs later
*/
acpi_disable_all_gpes();
+ /* Allow EC transactions to happen. */
+ acpi_ec_unblock_transactions_early();
local_irq_restore(flags);
printk(KERN_DEBUG "Back to C!\n");
@@ -264,9 +279,16 @@
if (acpi_state == ACPI_STATE_S3)
acpi_restore_state_mem();
+ suspend_nvs_restore();
+
return ACPI_SUCCESS(status) ? 0 : -EFAULT;
}
+static void acpi_suspend_finish(void)
+{
+ acpi_pm_finish();
+}
+
static int acpi_suspend_state_valid(suspend_state_t pm_state)
{
u32 acpi_state;
@@ -288,7 +310,7 @@
.begin = acpi_suspend_begin,
.prepare_late = acpi_pm_prepare,
.enter = acpi_suspend_enter,
- .wake = acpi_pm_finish,
+ .wake = acpi_suspend_finish,
.end = acpi_pm_end,
};
@@ -314,9 +336,9 @@
static struct platform_suspend_ops acpi_suspend_ops_old = {
.valid = acpi_suspend_state_valid,
.begin = acpi_suspend_begin_old,
- .prepare_late = acpi_pm_disable_gpes,
+ .prepare_late = acpi_pm_freeze,
.enter = acpi_suspend_enter,
- .wake = acpi_pm_finish,
+ .wake = acpi_suspend_finish,
.end = acpi_pm_end,
.recover = acpi_pm_finish,
};
@@ -393,7 +415,7 @@
{
int error;
- error = s4_no_nvs ? 0 : hibernate_nvs_alloc();
+ error = s4_no_nvs ? 0 : suspend_nvs_alloc();
if (!error) {
acpi_target_sleep_state = ACPI_STATE_S4;
acpi_sleep_tts_switch(acpi_target_sleep_state);
@@ -407,7 +429,7 @@
int error = acpi_pm_prepare();
if (!error)
- hibernate_nvs_save();
+ suspend_nvs_save();
return error;
}
@@ -430,12 +452,6 @@
return ACPI_SUCCESS(status) ? 0 : -EFAULT;
}
-static void acpi_hibernation_finish(void)
-{
- hibernate_nvs_free();
- acpi_pm_finish();
-}
-
static void acpi_hibernation_leave(void)
{
/*
@@ -452,20 +468,14 @@
panic("ACPI S4 hardware signature mismatch");
}
/* Restore the NVS memory area */
- hibernate_nvs_restore();
+ suspend_nvs_restore();
+ /* Allow EC transactions to happen. */
+ acpi_ec_unblock_transactions_early();
}
-static int acpi_pm_pre_restore(void)
+static void acpi_pm_thaw(void)
{
- acpi_disable_all_gpes();
- acpi_os_wait_events_complete(NULL);
- acpi_ec_suspend_transactions();
- return 0;
-}
-
-static void acpi_pm_restore_cleanup(void)
-{
- acpi_ec_resume_transactions();
+ acpi_ec_unblock_transactions();
acpi_enable_all_runtime_gpes();
}
@@ -473,12 +483,12 @@
.begin = acpi_hibernation_begin,
.end = acpi_pm_end,
.pre_snapshot = acpi_hibernation_pre_snapshot,
- .finish = acpi_hibernation_finish,
+ .finish = acpi_pm_finish,
.prepare = acpi_pm_prepare,
.enter = acpi_hibernation_enter,
.leave = acpi_hibernation_leave,
- .pre_restore = acpi_pm_pre_restore,
- .restore_cleanup = acpi_pm_restore_cleanup,
+ .pre_restore = acpi_pm_freeze,
+ .restore_cleanup = acpi_pm_thaw,
};
/**
@@ -501,7 +511,7 @@
if (!error) {
if (!s4_no_nvs)
- error = hibernate_nvs_alloc();
+ error = suspend_nvs_alloc();
if (!error)
acpi_target_sleep_state = ACPI_STATE_S4;
}
@@ -510,12 +520,9 @@
static int acpi_hibernation_pre_snapshot_old(void)
{
- int error = acpi_pm_disable_gpes();
-
- if (!error)
- hibernate_nvs_save();
-
- return error;
+ acpi_pm_freeze();
+ suspend_nvs_save();
+ return 0;
}
/*
@@ -526,12 +533,12 @@
.begin = acpi_hibernation_begin_old,
.end = acpi_pm_end,
.pre_snapshot = acpi_hibernation_pre_snapshot_old,
- .finish = acpi_hibernation_finish,
- .prepare = acpi_pm_disable_gpes,
+ .prepare = acpi_pm_freeze,
+ .finish = acpi_pm_finish,
.enter = acpi_hibernation_enter,
.leave = acpi_hibernation_leave,
- .pre_restore = acpi_pm_pre_restore,
- .restore_cleanup = acpi_pm_restore_cleanup,
+ .pre_restore = acpi_pm_freeze,
+ .restore_cleanup = acpi_pm_thaw,
.recover = acpi_pm_finish,
};
#endif /* CONFIG_HIBERNATION */
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
index c79e789..f8db50a0 100644
--- a/drivers/acpi/system.c
+++ b/drivers/acpi/system.c
@@ -388,10 +388,12 @@
if (index < num_gpes) {
if (!strcmp(buf, "disable\n") &&
(status & ACPI_EVENT_FLAG_ENABLED))
- result = acpi_set_gpe(handle, index, ACPI_GPE_DISABLE);
+ result = acpi_disable_gpe(handle, index,
+ ACPI_GPE_TYPE_RUNTIME);
else if (!strcmp(buf, "enable\n") &&
!(status & ACPI_EVENT_FLAG_ENABLED))
- result = acpi_set_gpe(handle, index, ACPI_GPE_ENABLE);
+ result = acpi_enable_gpe(handle, index,
+ ACPI_GPE_TYPE_RUNTIME);
else if (!strcmp(buf, "clear\n") &&
(status & ACPI_EVENT_FLAG_SET))
result = acpi_clear_gpe(handle, index);
diff --git a/drivers/acpi/wakeup.c b/drivers/acpi/wakeup.c
index 4b9d339..388747a 100644
--- a/drivers/acpi/wakeup.c
+++ b/drivers/acpi/wakeup.c
@@ -64,16 +64,13 @@
struct acpi_device *dev =
container_of(node, struct acpi_device, wakeup_list);
- if (!dev->wakeup.flags.valid)
- continue;
-
- if ((!dev->wakeup.state.enabled && !dev->wakeup.prepare_count)
+ if (!dev->wakeup.flags.valid || !dev->wakeup.state.enabled
|| sleep_state > (u32) dev->wakeup.sleep_state)
continue;
/* The wake-up power should have been enabled already. */
- acpi_set_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
- ACPI_GPE_ENABLE);
+ acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
+ ACPI_GPE_TYPE_WAKE);
}
}
@@ -96,6 +93,8 @@
|| (sleep_state > (u32) dev->wakeup.sleep_state))
continue;
+ acpi_disable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
+ ACPI_GPE_TYPE_WAKE);
acpi_disable_wakeup_device_power(dev);
}
}
@@ -109,13 +108,8 @@
struct acpi_device *dev = container_of(node,
struct acpi_device,
wakeup_list);
- /* In case user doesn't load button driver */
- if (!dev->wakeup.flags.always_enabled ||
- dev->wakeup.state.enabled)
- continue;
- acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
- ACPI_GPE_TYPE_WAKE);
- dev->wakeup.state.enabled = 1;
+ if (dev->wakeup.flags.always_enabled)
+ dev->wakeup.state.enabled = 1;
}
mutex_unlock(&acpi_device_lock);
return 0;
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 73f8833..aa85a98 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -168,10 +168,10 @@
default y
help
This option adds support for SFF ATA controllers with BMDMA
- capability. BMDMA stands for bus-master DMA and the
- de-facto DMA interface for SFF controllers.
+ capability. BMDMA stands for bus-master DMA and is the
+ de facto DMA interface for SFF controllers.
- If unuser, say Y.
+ If unsure, say Y.
if ATA_BMDMA
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 8ca16f5..f252253 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1053,6 +1053,16 @@
if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
return -ENODEV;
+ /*
+ * For some reason, MCP89 on MacBook 7,1 doesn't work with
+ * ahci, use ata_generic instead.
+ */
+ if (pdev->vendor == PCI_VENDOR_ID_NVIDIA &&
+ pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA &&
+ pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
+ pdev->subsystem_device == 0xcb89)
+ return -ENODEV;
+
/* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode.
* At the moment, we can only use the AHCI mode. Let the users know
* that for SAS drives they're out of luck.
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index 573158a..7107a69 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -32,6 +32,11 @@
* A generic parallel ATA driver using libata
*/
+enum {
+ ATA_GEN_CLASS_MATCH = (1 << 0),
+ ATA_GEN_FORCE_DMA = (1 << 1),
+};
+
/**
* generic_set_mode - mode setting
* @link: link to set up
@@ -46,13 +51,17 @@
static int generic_set_mode(struct ata_link *link, struct ata_device **unused)
{
struct ata_port *ap = link->ap;
+ const struct pci_device_id *id = ap->host->private_data;
int dma_enabled = 0;
struct ata_device *dev;
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
- /* Bits 5 and 6 indicate if DMA is active on master/slave */
- if (ap->ioaddr.bmdma_addr)
+ if (id->driver_data & ATA_GEN_FORCE_DMA) {
+ dma_enabled = 0xff;
+ } else if (ap->ioaddr.bmdma_addr) {
+ /* Bits 5 and 6 indicate if DMA is active on master/slave */
dma_enabled = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+ }
if (pdev->vendor == PCI_VENDOR_ID_CENATEK)
dma_enabled = 0xFF;
@@ -126,7 +135,7 @@
const struct ata_port_info *ppi[] = { &info, NULL };
/* Don't use the generic entry unless instructed to do so */
- if (id->driver_data == 1 && all_generic_ide == 0)
+ if ((id->driver_data & ATA_GEN_CLASS_MATCH) && all_generic_ide == 0)
return -ENODEV;
/* Devices that need care */
@@ -155,7 +164,7 @@
return rc;
pcim_pin_device(dev);
}
- return ata_pci_bmdma_init_one(dev, ppi, &generic_sht, NULL, 0);
+ return ata_pci_bmdma_init_one(dev, ppi, &generic_sht, (void *)id, 0);
}
static struct pci_device_id ata_generic[] = {
@@ -167,7 +176,15 @@
{ PCI_DEVICE(PCI_VENDOR_ID_HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE), },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561), },
{ PCI_DEVICE(PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558), },
- { PCI_DEVICE(PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE), },
+ { PCI_DEVICE(PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE),
+ .driver_data = ATA_GEN_FORCE_DMA },
+ /*
+ * For some reason, MCP89 on MacBook 7,1 doesn't work with
+ * ahci, use ata_generic instead.
+ */
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA,
+ PCI_VENDOR_ID_APPLE, 0xcb89,
+ .driver_data = ATA_GEN_FORCE_DMA },
#if !defined(CONFIG_PATA_TOSHIBA) && !defined(CONFIG_PATA_TOSHIBA_MODULE)
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), },
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), },
@@ -175,7 +192,8 @@
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_5), },
#endif
/* Must come last. If you add entries adjust this table appropriately */
- { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 1},
+ { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL),
+ .driver_data = ATA_GEN_CLASS_MATCH },
{ 0, },
};
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 1984a6e..81e772a 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -324,6 +324,7 @@
struct ahci_host_priv *hpriv = ap->host->private_data;
void __iomem *mmio = hpriv->mmio;
void __iomem *em_mmio = mmio + hpriv->em_loc;
+ const unsigned char *msg_buf = buf;
u32 em_ctl, msg;
unsigned long flags;
int i;
@@ -343,8 +344,8 @@
}
for (i = 0; i < size; i += 4) {
- msg = buf[i] | buf[i + 1] << 8 |
- buf[i + 2] << 16 | buf[i + 3] << 24;
+ msg = msg_buf[i] | msg_buf[i + 1] << 8 |
+ msg_buf[i + 2] << 16 | msg_buf[i + 3] << 24;
writel(msg, em_mmio + i);
}
@@ -541,29 +542,11 @@
return -EINVAL;
}
-static int ahci_is_device_present(void __iomem *port_mmio)
-{
- u8 status = readl(port_mmio + PORT_TFDATA) & 0xff;
-
- /* Make sure PxTFD.STS.BSY and PxTFD.STS.DRQ are 0 */
- if (status & (ATA_BUSY | ATA_DRQ))
- return 0;
-
- /* Make sure PxSSTS.DET is 3h */
- status = readl(port_mmio + PORT_SCR_STAT) & 0xf;
- if (status != 3)
- return 0;
- return 1;
-}
-
void ahci_start_engine(struct ata_port *ap)
{
void __iomem *port_mmio = ahci_port_base(ap);
u32 tmp;
- if (!ahci_is_device_present(port_mmio))
- return;
-
/* start DMA */
tmp = readl(port_mmio + PORT_CMD);
tmp |= PORT_CMD_START;
@@ -1892,6 +1875,9 @@
}
sata_pmp_error_handler(ap);
+
+ if (!ata_dev_enabled(ap->link.device))
+ ahci_stop_engine(ap);
}
static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 06b7e49..ddf8e48 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4119,9 +4119,8 @@
dev->n_sectors > n_sectors && dev->n_sectors == n_native_sectors) {
ata_dev_printk(dev, KERN_WARNING,
"new n_sectors matches native, probably "
- "late HPA unlock, continuing\n");
- /* keep using the old n_sectors */
- dev->n_sectors = n_sectors;
+ "late HPA unlock, n_sectors updated\n");
+ /* use the larger n_sectors */
return 0;
}
@@ -6669,6 +6668,7 @@
EXPORT_SYMBOL_GPL(ata_link_next);
EXPORT_SYMBOL_GPL(ata_dev_next);
EXPORT_SYMBOL_GPL(ata_std_bios_param);
+EXPORT_SYMBOL_GPL(ata_scsi_unlock_native_capacity);
EXPORT_SYMBOL_GPL(ata_host_init);
EXPORT_SYMBOL_GPL(ata_host_alloc);
EXPORT_SYMBOL_GPL(ata_host_alloc_pinfo);
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index cfa9dd3..a54273d 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -415,6 +415,35 @@
}
/**
+ * ata_scsi_unlock_native_capacity - unlock native capacity
+ * @sdev: SCSI device to adjust device capacity for
+ *
+ * This function is called if a partition on @sdev extends beyond
+ * the end of the device. It requests EH to unlock HPA.
+ *
+ * LOCKING:
+ * Defined by the SCSI layer. Might sleep.
+ */
+void ata_scsi_unlock_native_capacity(struct scsi_device *sdev)
+{
+ struct ata_port *ap = ata_shost_to_port(sdev->host);
+ struct ata_device *dev;
+ unsigned long flags;
+
+ spin_lock_irqsave(ap->lock, flags);
+
+ dev = ata_scsi_find_dev(ap, sdev);
+ if (dev && dev->n_sectors < dev->n_native_sectors) {
+ dev->flags |= ATA_DFLAG_UNLOCK_HPA;
+ dev->link->eh_info.action |= ATA_EH_RESET;
+ ata_port_schedule_eh(ap);
+ }
+
+ spin_unlock_irqrestore(ap->lock, flags);
+ ata_port_wait_eh(ap);
+}
+
+/**
* ata_get_identity - Handler for HDIO_GET_IDENTITY ioctl
* @ap: target port
* @sdev: SCSI device to get identify data for
diff --git a/drivers/ata/pata_macio.c b/drivers/ata/pata_macio.c
index 76640ac..75b49d0 100644
--- a/drivers/ata/pata_macio.c
+++ b/drivers/ata/pata_macio.c
@@ -1355,8 +1355,11 @@
static struct macio_driver pata_macio_driver =
{
- .name = "pata-macio",
- .match_table = pata_macio_match,
+ .driver = {
+ .name = "pata-macio",
+ .owner = THIS_MODULE,
+ .of_match_table = pata_macio_match,
+ },
.probe = pata_macio_attach,
.remove = pata_macio_detach,
#ifdef CONFIG_PM
@@ -1366,9 +1369,6 @@
#ifdef CONFIG_PMAC_MEDIABAY
.mediabay_event = pata_macio_mb_event,
#endif
- .driver = {
- .owner = THIS_MODULE,
- },
};
static const struct pci_device_id pata_macio_pci_match[] = {
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 6fd1147..2116113 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -1669,7 +1669,6 @@
mask = readl(mmio_base + NV_INT_ENABLE_MCP55);
mask &= ~(NV_INT_ALL_MCP55 << shift);
writel(mask, mmio_base + NV_INT_ENABLE_MCP55);
- ata_sff_freeze(ap);
}
static void nv_mcp55_thaw(struct ata_port *ap)
@@ -1683,7 +1682,6 @@
mask = readl(mmio_base + NV_INT_ENABLE_MCP55);
mask |= (NV_INT_MASK_MCP55 << shift);
writel(mask, mmio_base + NV_INT_ENABLE_MCP55);
- ata_sff_thaw(ap);
}
static void nv_adma_error_handler(struct ata_port *ap)
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index e925051..be7726d 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -539,12 +539,12 @@
writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
/* zero error counters. */
- writel(0x8000, port + PORT_DECODE_ERR_THRESH);
- writel(0x8000, port + PORT_CRC_ERR_THRESH);
- writel(0x8000, port + PORT_HSHK_ERR_THRESH);
- writel(0x0000, port + PORT_DECODE_ERR_CNT);
- writel(0x0000, port + PORT_CRC_ERR_CNT);
- writel(0x0000, port + PORT_HSHK_ERR_CNT);
+ writew(0x8000, port + PORT_DECODE_ERR_THRESH);
+ writew(0x8000, port + PORT_CRC_ERR_THRESH);
+ writew(0x8000, port + PORT_HSHK_ERR_THRESH);
+ writew(0x0000, port + PORT_DECODE_ERR_CNT);
+ writew(0x0000, port + PORT_CRC_ERR_CNT);
+ writew(0x0000, port + PORT_HSHK_ERR_CNT);
/* always use 64bit activation */
writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR);
@@ -622,6 +622,11 @@
irq_enabled = readl(port + PORT_IRQ_ENABLE_SET);
writel(PORT_IRQ_COMPLETE | PORT_IRQ_ERROR, port + PORT_IRQ_ENABLE_CLR);
+ /*
+ * The barrier is required to ensure that writes to cmd_block reach
+ * the memory before the write to PORT_CMD_ACTIVATE.
+ */
+ wmb();
writel((u32)paddr, port + PORT_CMD_ACTIVATE);
writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4);
@@ -865,7 +870,7 @@
} else {
prb = &cb->atapi.prb;
sge = cb->atapi.sge;
- memset(cb->atapi.cdb, 0, 32);
+ memset(cb->atapi.cdb, 0, sizeof(cb->atapi.cdb));
memcpy(cb->atapi.cdb, qc->cdb, qc->dev->cdb_len);
if (ata_is_data(qc->tf.protocol)) {
@@ -895,6 +900,11 @@
paddr = pp->cmd_block_dma + tag * sizeof(*pp->cmd_block);
activate = port + PORT_CMD_ACTIVATE + tag * 8;
+ /*
+ * The barrier is required to ensure that writes to cmd_block reach
+ * the memory before the write to PORT_CMD_ACTIVATE.
+ */
+ wmb();
writel((u32)paddr, activate);
writel((u64)paddr >> 32, activate + 4);
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index 101d8c2..4730c42 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -575,6 +575,33 @@
tmp8 |= NATIVE_MODE_ALL;
pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);
}
+
+ /*
+ * vt6421 has problems talking to some drives. The following
+ * is the fix from Joseph Chan <JosephChan@via.com.tw>.
+ *
+ * When host issues HOLD, device may send up to 20DW of data
+ * before acknowledging it with HOLDA and the host should be
+ * able to buffer them in FIFO. Unfortunately, some WD drives
+ * send upto 40DW before acknowledging HOLD and, in the
+ * default configuration, this ends up overflowing vt6421's
+ * FIFO, making the controller abort the transaction with
+ * R_ERR.
+ *
+ * Rx52[2] is the internal 128DW FIFO Flow control watermark
+ * adjusting mechanism enable bit and the default value 0
+ * means host will issue HOLD to device when the left FIFO
+ * size goes below 32DW. Setting it to 1 makes the watermark
+ * 64DW.
+ *
+ * https://bugzilla.kernel.org/show_bug.cgi?id=15173
+ * http://article.gmane.org/gmane.linux.ide/46352
+ */
+ if (pdev->device == 0x3249) {
+ pci_read_config_byte(pdev, 0x52, &tmp8);
+ tmp8 |= 1 << 2;
+ pci_write_config_byte(pdev, 0x52, tmp8);
+ }
}
static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index 6081e81..f1bf79d 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -133,6 +133,28 @@
return page;
}
+static void brd_free_page(struct brd_device *brd, sector_t sector)
+{
+ struct page *page;
+ pgoff_t idx;
+
+ spin_lock(&brd->brd_lock);
+ idx = sector >> PAGE_SECTORS_SHIFT;
+ page = radix_tree_delete(&brd->brd_pages, idx);
+ spin_unlock(&brd->brd_lock);
+ if (page)
+ __free_page(page);
+}
+
+static void brd_zero_page(struct brd_device *brd, sector_t sector)
+{
+ struct page *page;
+
+ page = brd_lookup_page(brd, sector);
+ if (page)
+ clear_highpage(page);
+}
+
/*
* Free all backing store pages and radix tree. This must only be called when
* there are no other users of the device.
@@ -189,6 +211,24 @@
return 0;
}
+static void discard_from_brd(struct brd_device *brd,
+ sector_t sector, size_t n)
+{
+ while (n >= PAGE_SIZE) {
+ /*
+ * Don't want to actually discard pages here because
+ * re-allocating the pages can result in writeback
+ * deadlocks under heavy load.
+ */
+ if (0)
+ brd_free_page(brd, sector);
+ else
+ brd_zero_page(brd, sector);
+ sector += PAGE_SIZE >> SECTOR_SHIFT;
+ n -= PAGE_SIZE;
+ }
+}
+
/*
* Copy n bytes from src to the brd starting at sector. Does not sleep.
*/
@@ -300,6 +340,12 @@
get_capacity(bdev->bd_disk))
goto out;
+ if (unlikely(bio_rw_flagged(bio, BIO_RW_DISCARD))) {
+ err = 0;
+ discard_from_brd(brd, sector, bio->bi_size);
+ goto out;
+ }
+
rw = bio_rw(bio);
if (rw == READA)
rw = READ;
@@ -320,7 +366,7 @@
}
#ifdef CONFIG_BLK_DEV_XIP
-static int brd_direct_access (struct block_device *bdev, sector_t sector,
+static int brd_direct_access(struct block_device *bdev, sector_t sector,
void **kaddr, unsigned long *pfn)
{
struct brd_device *brd = bdev->bd_disk->private_data;
@@ -437,6 +483,11 @@
blk_queue_max_hw_sectors(brd->brd_queue, 1024);
blk_queue_bounce_limit(brd->brd_queue, BLK_BOUNCE_ANY);
+ brd->brd_queue->limits.discard_granularity = PAGE_SIZE;
+ brd->brd_queue->limits.max_discard_sectors = UINT_MAX;
+ brd->brd_queue->limits.discard_zeroes_data = 1;
+ queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, brd->brd_queue);
+
disk = brd->brd_disk = alloc_disk(1 << part_shift);
if (!disk)
goto out_free_queue;
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index e1d0e2c..72dae92 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -188,11 +188,11 @@
sa = h->scsi_ctlr;
stk = &sa->cmd_stack;
+ stk->top++;
if (stk->top >= CMD_STACK_SIZE) {
printk("cciss: scsi_cmd_free called too many times.\n");
BUG();
}
- stk->top++;
stk->elem[stk->top] = (struct cciss_scsi_cmd_stack_elem_t *) cmd;
}
@@ -861,6 +861,7 @@
sh->n_io_port = 0; // I don't think we use these two...
sh->this_id = SELF_SCSI_ID;
sh->sg_tablesize = hba[ctlr]->maxsgentries;
+ sh->max_cmd_len = MAX_COMMAND_SIZE;
((struct cciss_scsi_adapter_data_t *)
hba[ctlr]->scsi_ctlr)->scsi_host = sh;
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index 91d1163..abb4ec6 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -386,7 +386,7 @@
}
/* pdev is NULL for eisa */
-static int __init cpqarray_register_ctlr( int i, struct pci_dev *pdev)
+static int __devinit cpqarray_register_ctlr( int i, struct pci_dev *pdev)
{
struct request_queue *q;
int j;
@@ -503,7 +503,7 @@
return -1;
}
-static int __init cpqarray_init_one( struct pci_dev *pdev,
+static int __devinit cpqarray_init_one( struct pci_dev *pdev,
const struct pci_device_id *ent)
{
int i;
@@ -740,7 +740,7 @@
/*
* Find an EISA controller's signature. Set up an hba if we find it.
*/
-static int __init cpqarray_eisa_detect(void)
+static int __devinit cpqarray_eisa_detect(void)
{
int i=0, j;
__u32 board_id;
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index e9654c8..485ed8c 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -943,8 +943,7 @@
struct drbd_work resync_work,
unplug_work,
md_sync_work,
- delay_probe_work,
- uuid_work;
+ delay_probe_work;
struct timer_list resync_timer;
struct timer_list md_sync_timer;
struct timer_list delay_probe_timer;
@@ -1069,7 +1068,6 @@
struct timeval dps_time; /* delay-probes-start-time */
unsigned int dp_volume_last; /* send_cnt of last delay probe */
int c_sync_rate; /* current resync rate after delay_probe magic */
- atomic_t new_c_uuid;
};
static inline struct drbd_conf *minor_to_mdev(unsigned int minor)
@@ -1476,7 +1474,6 @@
extern int w_ov_finished(struct drbd_conf *, struct drbd_work *, int);
extern int w_resync_inactive(struct drbd_conf *, struct drbd_work *, int);
extern int w_resume_next_sg(struct drbd_conf *, struct drbd_work *, int);
-extern int w_io_error(struct drbd_conf *, struct drbd_work *, int);
extern int w_send_write_hint(struct drbd_conf *, struct drbd_work *, int);
extern int w_make_resync_request(struct drbd_conf *, struct drbd_work *, int);
extern int w_send_dblock(struct drbd_conf *, struct drbd_work *, int);
@@ -1542,7 +1539,7 @@
static inline void drbd_tcp_quickack(struct socket *sock)
{
- int __user val = 1;
+ int __user val = 2;
(void) drbd_setsockopt(sock, SOL_TCP, TCP_QUICKACK,
(char __user *)&val, sizeof(val));
}
@@ -1728,7 +1725,7 @@
switch (mdev->ldev->dc.on_io_error) {
case EP_PASS_ON:
if (!forcedetach) {
- if (printk_ratelimit())
+ if (__ratelimit(&drbd_ratelimit_state))
dev_err(DEV, "Local IO failed in %s."
"Passing error on...\n", where);
break;
@@ -2219,8 +2216,6 @@
return 0;
if (test_bit(BITMAP_IO, &mdev->flags))
return 0;
- if (atomic_read(&mdev->new_c_uuid))
- return 0;
return 1;
}
@@ -2241,9 +2236,6 @@
* to avoid races with the reconnect code,
* we need to atomic_inc within the spinlock. */
- if (atomic_read(&mdev->new_c_uuid) && atomic_add_unless(&mdev->new_c_uuid, -1, 1))
- drbd_queue_work_front(&mdev->data.work, &mdev->uuid_work);
-
spin_lock_irq(&mdev->req_lock);
while (!__inc_ap_bio_cond(mdev)) {
prepare_to_wait(&mdev->misc_wait, &wait, TASK_UNINTERRUPTIBLE);
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index be2d2da..7258c95 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -1215,18 +1215,17 @@
ns.pdsk == D_OUTDATED)) {
if (get_ldev(mdev)) {
if ((ns.role == R_PRIMARY || ns.peer == R_PRIMARY) &&
- mdev->ldev->md.uuid[UI_BITMAP] == 0 && ns.disk >= D_UP_TO_DATE &&
- !atomic_read(&mdev->new_c_uuid))
- atomic_set(&mdev->new_c_uuid, 2);
+ mdev->ldev->md.uuid[UI_BITMAP] == 0 && ns.disk >= D_UP_TO_DATE) {
+ drbd_uuid_new_current(mdev);
+ drbd_send_uuids(mdev);
+ }
put_ldev(mdev);
}
}
if (ns.pdsk < D_INCONSISTENT && get_ldev(mdev)) {
- /* Diskless peer becomes primary or got connected do diskless, primary peer. */
- if (ns.peer == R_PRIMARY && mdev->ldev->md.uuid[UI_BITMAP] == 0 &&
- !atomic_read(&mdev->new_c_uuid))
- atomic_set(&mdev->new_c_uuid, 2);
+ if (ns.peer == R_PRIMARY && mdev->ldev->md.uuid[UI_BITMAP] == 0)
+ drbd_uuid_new_current(mdev);
/* D_DISKLESS Peer becomes secondary */
if (os.peer == R_PRIMARY && ns.peer == R_SECONDARY)
@@ -1237,8 +1236,6 @@
/* Last part of the attaching process ... */
if (ns.conn >= C_CONNECTED &&
os.disk == D_ATTACHING && ns.disk == D_NEGOTIATING) {
- kfree(mdev->p_uuid); /* We expect to receive up-to-date UUIDs soon. */
- mdev->p_uuid = NULL; /* ...to not use the old ones in the mean time */
drbd_send_sizes(mdev, 0, 0); /* to start sync... */
drbd_send_uuids(mdev);
drbd_send_state(mdev);
@@ -1350,24 +1347,6 @@
drbd_md_sync(mdev);
}
-static int w_new_current_uuid(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
-{
- if (get_ldev(mdev)) {
- if (mdev->ldev->md.uuid[UI_BITMAP] == 0) {
- drbd_uuid_new_current(mdev);
- if (get_net_conf(mdev)) {
- drbd_send_uuids(mdev);
- put_net_conf(mdev);
- }
- drbd_md_sync(mdev);
- }
- put_ldev(mdev);
- }
- atomic_dec(&mdev->new_c_uuid);
- wake_up(&mdev->misc_wait);
-
- return 1;
-}
static int drbd_thread_setup(void *arg)
{
@@ -2291,9 +2270,9 @@
* with page_count == 0 or PageSlab.
*/
static int _drbd_no_send_page(struct drbd_conf *mdev, struct page *page,
- int offset, size_t size)
+ int offset, size_t size, unsigned msg_flags)
{
- int sent = drbd_send(mdev, mdev->data.socket, kmap(page) + offset, size, 0);
+ int sent = drbd_send(mdev, mdev->data.socket, kmap(page) + offset, size, msg_flags);
kunmap(page);
if (sent == size)
mdev->send_cnt += size>>9;
@@ -2301,7 +2280,7 @@
}
static int _drbd_send_page(struct drbd_conf *mdev, struct page *page,
- int offset, size_t size)
+ int offset, size_t size, unsigned msg_flags)
{
mm_segment_t oldfs = get_fs();
int sent, ok;
@@ -2314,14 +2293,15 @@
* __page_cache_release a page that would actually still be referenced
* by someone, leading to some obscure delayed Oops somewhere else. */
if (disable_sendpage || (page_count(page) < 1) || PageSlab(page))
- return _drbd_no_send_page(mdev, page, offset, size);
+ return _drbd_no_send_page(mdev, page, offset, size, msg_flags);
+ msg_flags |= MSG_NOSIGNAL;
drbd_update_congested(mdev);
set_fs(KERNEL_DS);
do {
sent = mdev->data.socket->ops->sendpage(mdev->data.socket, page,
offset, len,
- MSG_NOSIGNAL);
+ msg_flags);
if (sent == -EAGAIN) {
if (we_should_drop_the_connection(mdev,
mdev->data.socket))
@@ -2350,9 +2330,11 @@
{
struct bio_vec *bvec;
int i;
+ /* hint all but last page with MSG_MORE */
__bio_for_each_segment(bvec, bio, i, 0) {
if (!_drbd_no_send_page(mdev, bvec->bv_page,
- bvec->bv_offset, bvec->bv_len))
+ bvec->bv_offset, bvec->bv_len,
+ i == bio->bi_vcnt -1 ? 0 : MSG_MORE))
return 0;
}
return 1;
@@ -2362,12 +2344,13 @@
{
struct bio_vec *bvec;
int i;
+ /* hint all but last page with MSG_MORE */
__bio_for_each_segment(bvec, bio, i, 0) {
if (!_drbd_send_page(mdev, bvec->bv_page,
- bvec->bv_offset, bvec->bv_len))
+ bvec->bv_offset, bvec->bv_len,
+ i == bio->bi_vcnt -1 ? 0 : MSG_MORE))
return 0;
}
-
return 1;
}
@@ -2375,9 +2358,11 @@
{
struct page *page = e->pages;
unsigned len = e->size;
+ /* hint all but last page with MSG_MORE */
page_chain_for_each(page) {
unsigned l = min_t(unsigned, len, PAGE_SIZE);
- if (!_drbd_send_page(mdev, page, 0, l))
+ if (!_drbd_send_page(mdev, page, 0, l,
+ page_chain_next(page) ? MSG_MORE : 0))
return 0;
len -= l;
}
@@ -2457,11 +2442,11 @@
p.dp_flags = cpu_to_be32(dp_flags);
set_bit(UNPLUG_REMOTE, &mdev->flags);
ok = (sizeof(p) ==
- drbd_send(mdev, mdev->data.socket, &p, sizeof(p), MSG_MORE));
+ drbd_send(mdev, mdev->data.socket, &p, sizeof(p), dgs ? MSG_MORE : 0));
if (ok && dgs) {
dgb = mdev->int_dig_out;
drbd_csum_bio(mdev, mdev->integrity_w_tfm, req->master_bio, dgb);
- ok = drbd_send(mdev, mdev->data.socket, dgb, dgs, MSG_MORE);
+ ok = drbd_send(mdev, mdev->data.socket, dgb, dgs, 0);
}
if (ok) {
if (mdev->net_conf->wire_protocol == DRBD_PROT_A)
@@ -2510,11 +2495,11 @@
return 0;
ok = sizeof(p) == drbd_send(mdev, mdev->data.socket, &p,
- sizeof(p), MSG_MORE);
+ sizeof(p), dgs ? MSG_MORE : 0);
if (ok && dgs) {
dgb = mdev->int_dig_out;
drbd_csum_ee(mdev, mdev->integrity_w_tfm, e, dgb);
- ok = drbd_send(mdev, mdev->data.socket, dgb, dgs, MSG_MORE);
+ ok = drbd_send(mdev, mdev->data.socket, dgb, dgs, 0);
}
if (ok)
ok = _drbd_send_zc_ee(mdev, e);
@@ -2708,7 +2693,6 @@
atomic_set(&mdev->net_cnt, 0);
atomic_set(&mdev->packet_seq, 0);
atomic_set(&mdev->pp_in_use, 0);
- atomic_set(&mdev->new_c_uuid, 0);
mutex_init(&mdev->md_io_mutex);
mutex_init(&mdev->data.mutex);
@@ -2739,14 +2723,12 @@
INIT_LIST_HEAD(&mdev->bm_io_work.w.list);
INIT_LIST_HEAD(&mdev->delay_probes);
INIT_LIST_HEAD(&mdev->delay_probe_work.list);
- INIT_LIST_HEAD(&mdev->uuid_work.list);
mdev->resync_work.cb = w_resync_inactive;
mdev->unplug_work.cb = w_send_write_hint;
mdev->md_sync_work.cb = w_md_sync;
mdev->bm_io_work.w.cb = w_bitmap_io;
mdev->delay_probe_work.cb = w_delay_probes;
- mdev->uuid_work.cb = w_new_current_uuid;
init_timer(&mdev->resync_timer);
init_timer(&mdev->md_sync_timer);
init_timer(&mdev->delay_probe_timer);
@@ -3799,7 +3781,7 @@
if (ret) {
fault_count++;
- if (printk_ratelimit())
+ if (__ratelimit(&drbd_ratelimit_state))
dev_warn(DEV, "***Simulating %s failure\n",
_drbd_fault_str(type));
}
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 632e324..2151f18 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -1114,6 +1114,12 @@
mdev->new_state_tmp.i = ns.i;
ns.i = os.i;
ns.disk = D_NEGOTIATING;
+
+ /* We expect to receive up-to-date UUIDs soon.
+ To avoid a race in receive_state, free p_uuid while
+ holding req_lock. I.e. atomic with the state change */
+ kfree(mdev->p_uuid);
+ mdev->p_uuid = NULL;
}
rv = _drbd_set_state(mdev, ns, CS_VERBOSE, NULL);
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index bc9ab7f..dff4870 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -42,7 +42,6 @@
#include <linux/unistd.h>
#include <linux/vmalloc.h>
#include <linux/random.h>
-#include <linux/mm.h>
#include <linux/string.h>
#include <linux/scatterlist.h>
#include "drbd_int.h"
@@ -571,6 +570,25 @@
return rv;
}
+/* quoting tcp(7):
+ * On individual connections, the socket buffer size must be set prior to the
+ * listen(2) or connect(2) calls in order to have it take effect.
+ * This is our wrapper to do so.
+ */
+static void drbd_setbufsize(struct socket *sock, unsigned int snd,
+ unsigned int rcv)
+{
+ /* open coded SO_SNDBUF, SO_RCVBUF */
+ if (snd) {
+ sock->sk->sk_sndbuf = snd;
+ sock->sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
+ }
+ if (rcv) {
+ sock->sk->sk_rcvbuf = rcv;
+ sock->sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
+ }
+}
+
static struct socket *drbd_try_connect(struct drbd_conf *mdev)
{
const char *what;
@@ -592,6 +610,8 @@
sock->sk->sk_rcvtimeo =
sock->sk->sk_sndtimeo = mdev->net_conf->try_connect_int*HZ;
+ drbd_setbufsize(sock, mdev->net_conf->sndbuf_size,
+ mdev->net_conf->rcvbuf_size);
/* explicitly bind to the configured IP as source IP
* for the outgoing connections.
@@ -670,6 +690,8 @@
s_listen->sk->sk_reuse = 1; /* SO_REUSEADDR */
s_listen->sk->sk_rcvtimeo = timeo;
s_listen->sk->sk_sndtimeo = timeo;
+ drbd_setbufsize(s_listen, mdev->net_conf->sndbuf_size,
+ mdev->net_conf->rcvbuf_size);
what = "bind before listen";
err = s_listen->ops->bind(s_listen,
@@ -856,16 +878,6 @@
sock->sk->sk_priority = TC_PRIO_INTERACTIVE_BULK;
msock->sk->sk_priority = TC_PRIO_INTERACTIVE;
- if (mdev->net_conf->sndbuf_size) {
- sock->sk->sk_sndbuf = mdev->net_conf->sndbuf_size;
- sock->sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
- }
-
- if (mdev->net_conf->rcvbuf_size) {
- sock->sk->sk_rcvbuf = mdev->net_conf->rcvbuf_size;
- sock->sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
- }
-
/* NOT YET ...
* sock->sk->sk_sndtimeo = mdev->net_conf->timeout*HZ/10;
* sock->sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT;
@@ -1154,17 +1166,6 @@
unsigned n_bios = 0;
unsigned nr_pages = (ds + PAGE_SIZE -1) >> PAGE_SHIFT;
- if (atomic_read(&mdev->new_c_uuid)) {
- if (atomic_add_unless(&mdev->new_c_uuid, -1, 1)) {
- drbd_uuid_new_current(mdev);
- drbd_md_sync(mdev);
-
- atomic_dec(&mdev->new_c_uuid);
- wake_up(&mdev->misc_wait);
- }
- wait_event(mdev->misc_wait, !atomic_read(&mdev->new_c_uuid));
- }
-
/* In most cases, we will only need one bio. But in case the lower
* level restrictions happen to be different at this offset on this
* side than those of the sending peer, we may need to submit the
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 3397f11..654f1ef 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -102,32 +102,7 @@
}
}
- /* if it was a local io error, we want to notify our
- * peer about that, and see if we need to
- * detach the disk and stuff.
- * to avoid allocating some special work
- * struct, reuse the request. */
-
- /* THINK
- * why do we do this not when we detect the error,
- * but delay it until it is "done", i.e. possibly
- * until the next barrier ack? */
-
- if (rw == WRITE &&
- ((s & RQ_LOCAL_MASK) && !(s & RQ_LOCAL_OK))) {
- if (!(req->w.list.next == LIST_POISON1 ||
- list_empty(&req->w.list))) {
- /* DEBUG ASSERT only; if this triggers, we
- * probably corrupt the worker list here */
- dev_err(DEV, "req->w.list.next = %p\n", req->w.list.next);
- dev_err(DEV, "req->w.list.prev = %p\n", req->w.list.prev);
- }
- req->w.cb = w_io_error;
- drbd_queue_work(&mdev->data.work, &req->w);
- /* drbd_req_free() is done in w_io_error */
- } else {
- drbd_req_free(req);
- }
+ drbd_req_free(req);
}
static void queue_barrier(struct drbd_conf *mdev)
@@ -453,9 +428,6 @@
req->rq_state |= RQ_LOCAL_COMPLETED;
req->rq_state &= ~RQ_LOCAL_PENDING;
- dev_alert(DEV, "Local WRITE failed sec=%llus size=%u\n",
- (unsigned long long)req->sector, req->size);
- /* and now: check how to handle local io error. */
__drbd_chk_io_error(mdev, FALSE);
_req_may_be_done(req, m);
put_ldev(mdev);
@@ -475,22 +447,21 @@
req->rq_state |= RQ_LOCAL_COMPLETED;
req->rq_state &= ~RQ_LOCAL_PENDING;
- dev_alert(DEV, "Local READ failed sec=%llus size=%u\n",
- (unsigned long long)req->sector, req->size);
- /* _req_mod(req,to_be_send); oops, recursion... */
D_ASSERT(!(req->rq_state & RQ_NET_MASK));
- req->rq_state |= RQ_NET_PENDING;
- inc_ap_pending(mdev);
__drbd_chk_io_error(mdev, FALSE);
put_ldev(mdev);
- /* NOTE: if we have no connection,
- * or know the peer has no good data either,
- * then we don't actually need to "queue_for_net_read",
- * but we do so anyways, since the drbd_io_error()
- * and the potential state change to "Diskless"
- * needs to be done from process context */
+ /* no point in retrying if there is no good remote data,
+ * or we have no connection. */
+ if (mdev->state.pdsk != D_UP_TO_DATE) {
+ _req_may_be_done(req, m);
+ break;
+ }
+
+ /* _req_mod(req,to_be_send); oops, recursion... */
+ req->rq_state |= RQ_NET_PENDING;
+ inc_ap_pending(mdev);
/* fall through: _req_mod(req,queue_for_net_read); */
case queue_for_net_read:
@@ -600,6 +571,9 @@
_req_may_be_done(req, m);
break;
+ case read_retry_remote_canceled:
+ req->rq_state &= ~RQ_NET_QUEUED;
+ /* fall through, in case we raced with drbd_disconnect */
case connection_lost_while_pending:
/* transfer log cleanup after connection loss */
/* assert something? */
diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h
index 16119d7..02d575d 100644
--- a/drivers/block/drbd/drbd_req.h
+++ b/drivers/block/drbd/drbd_req.h
@@ -91,6 +91,7 @@
send_failed,
handed_over_to_network,
connection_lost_while_pending,
+ read_retry_remote_canceled,
recv_acked_by_peer,
write_acked_by_peer,
write_acked_by_peer_and_sis, /* and set_in_sync */
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index 727ff63..b623cee 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -224,9 +224,6 @@
enum drbd_req_event what;
int uptodate = bio_flagged(bio, BIO_UPTODATE);
- if (error)
- dev_warn(DEV, "p %s: error=%d\n",
- bio_data_dir(bio) == WRITE ? "write" : "read", error);
if (!error && !uptodate) {
dev_warn(DEV, "p %s: setting error to -EIO\n",
bio_data_dir(bio) == WRITE ? "write" : "read");
@@ -257,20 +254,6 @@
complete_master_bio(mdev, &m);
}
-int w_io_error(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
-{
- struct drbd_request *req = container_of(w, struct drbd_request, w);
-
- /* NOTE: mdev->ldev can be NULL by the time we get here! */
- /* D_ASSERT(mdev->ldev->dc.on_io_error != EP_PASS_ON); */
-
- /* the only way this callback is scheduled is from _req_may_be_done,
- * when it is done and had a local write error, see comments there */
- drbd_req_free(req);
-
- return TRUE;
-}
-
int w_read_retry_remote(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
{
struct drbd_request *req = container_of(w, struct drbd_request, w);
@@ -280,12 +263,9 @@
* to give the disk the chance to relocate that block */
spin_lock_irq(&mdev->req_lock);
- if (cancel ||
- mdev->state.conn < C_CONNECTED ||
- mdev->state.pdsk <= D_INCONSISTENT) {
- _req_mod(req, send_canceled);
+ if (cancel || mdev->state.pdsk != D_UP_TO_DATE) {
+ _req_mod(req, read_retry_remote_canceled);
spin_unlock_irq(&mdev->req_lock);
- dev_alert(DEV, "WE ARE LOST. Local IO failure, no peer.\n");
return 1;
}
spin_unlock_irq(&mdev->req_lock);
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index 52f2d11..ed6fb91 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -1159,8 +1159,10 @@
static struct macio_driver swim3_driver =
{
- .name = "swim3",
- .match_table = swim3_match,
+ .driver = {
+ .name = "swim3",
+ .of_match_table = swim3_match,
+ },
.probe = swim3_attach,
#if 0
.suspend = swim3_suspend,
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 83fa09a..258bc2a 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -298,7 +298,9 @@
err = virtio_config_val(vdev, VIRTIO_BLK_F_SEG_MAX,
offsetof(struct virtio_blk_config, seg_max),
&sg_elems);
- if (err)
+
+ /* We need at least one SG element, whatever they say. */
+ if (err || !sg_elems)
sg_elems = 1;
/* We need an extra sg elements at head and tail. */
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index f09fc0e..7cfcc62 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -1123,6 +1123,7 @@
config RAMOOPS
tristate "Log panic/oops to a RAM buffer"
+ depends on HAS_IOMEM
default n
help
This enables panic and oops messages to be logged to a circular
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index 4b51982..d2abf51 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -97,20 +97,18 @@
void agp_alloc_page_array(size_t size, struct agp_memory *mem)
{
mem->pages = NULL;
- mem->vmalloc_flag = false;
if (size <= 2*PAGE_SIZE)
- mem->pages = kmalloc(size, GFP_KERNEL | __GFP_NORETRY);
+ mem->pages = kmalloc(size, GFP_KERNEL | __GFP_NOWARN);
if (mem->pages == NULL) {
mem->pages = vmalloc(size);
- mem->vmalloc_flag = true;
}
}
EXPORT_SYMBOL(agp_alloc_page_array);
void agp_free_page_array(struct agp_memory *mem)
{
- if (mem->vmalloc_flag) {
+ if (is_vmalloc_addr(mem->pages)) {
vfree(mem->pages);
} else {
kfree(mem->pages);
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
index 95db713..f845a8f 100644
--- a/drivers/char/agp/uninorth-agp.c
+++ b/drivers/char/agp/uninorth-agp.c
@@ -415,7 +415,7 @@
bridge->gatt_table_real = (u32 *) table;
/* Need to clear out any dirty data still sitting in caches */
flush_dcache_range((unsigned long)table,
- (unsigned long)(table_end + PAGE_SIZE));
+ (unsigned long)table_end + 1);
bridge->gatt_table = vmap(pages, (1 << page_order), 0, PAGE_KERNEL_NCG);
if (bridge->gatt_table == NULL)
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 35603dd..094bdc3 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -302,6 +302,12 @@
static int force_kipmid[SI_MAX_PARMS];
static int num_force_kipmid;
+#ifdef CONFIG_PCI
+static int pci_registered;
+#endif
+#ifdef CONFIG_PPC_OF
+static int of_registered;
+#endif
static unsigned int kipmid_max_busy_us[SI_MAX_PARMS];
static int num_max_busy_us;
@@ -1018,7 +1024,7 @@
else if (smi_result == SI_SM_IDLE)
schedule_timeout_interruptible(100);
else
- schedule_timeout_interruptible(0);
+ schedule_timeout_interruptible(1);
}
return 0;
}
@@ -3314,6 +3320,8 @@
rv = pci_register_driver(&ipmi_pci_driver);
if (rv)
printk(KERN_ERR PFX "Unable to register PCI driver: %d\n", rv);
+ else
+ pci_registered = 1;
#endif
#ifdef CONFIG_ACPI
@@ -3330,6 +3338,7 @@
#ifdef CONFIG_PPC_OF
of_register_platform_driver(&ipmi_of_platform_driver);
+ of_registered = 1;
#endif
/* We prefer devices with interrupts, but in the case of a machine
@@ -3383,11 +3392,13 @@
if (unload_when_empty && list_empty(&smi_infos)) {
mutex_unlock(&smi_infos_lock);
#ifdef CONFIG_PCI
- pci_unregister_driver(&ipmi_pci_driver);
+ if (pci_registered)
+ pci_unregister_driver(&ipmi_pci_driver);
#endif
#ifdef CONFIG_PPC_OF
- of_unregister_platform_driver(&ipmi_of_platform_driver);
+ if (of_registered)
+ of_unregister_platform_driver(&ipmi_of_platform_driver);
#endif
driver_unregister(&ipmi_driver.driver);
printk(KERN_WARNING PFX
@@ -3478,14 +3489,16 @@
return;
#ifdef CONFIG_PCI
- pci_unregister_driver(&ipmi_pci_driver);
+ if (pci_registered)
+ pci_unregister_driver(&ipmi_pci_driver);
#endif
#ifdef CONFIG_ACPI
pnp_unregister_driver(&ipmi_pnp_driver);
#endif
#ifdef CONFIG_PPC_OF
- of_unregister_platform_driver(&ipmi_of_platform_driver);
+ if (of_registered)
+ of_unregister_platform_driver(&ipmi_of_platform_driver);
#endif
mutex_lock(&smi_infos_lock);
diff --git a/drivers/char/n_gsm.c b/drivers/char/n_gsm.c
index c4161d5..e4089c4 100644
--- a/drivers/char/n_gsm.c
+++ b/drivers/char/n_gsm.c
@@ -904,9 +904,7 @@
int len;
/* Priority ordering: We should do priority with RR of the groups */
int i = 1;
- unsigned long flags;
- spin_lock_irqsave(&gsm->tx_lock, flags);
while (i < NUM_DLCI) {
struct gsm_dlci *dlci;
@@ -927,7 +925,6 @@
if (len == 0)
i++;
}
- spin_unlock_irqrestore(&gsm->tx_lock, flags);
}
/**
@@ -2230,12 +2227,16 @@
static void gsmld_write_wakeup(struct tty_struct *tty)
{
struct gsm_mux *gsm = tty->disc_data;
+ unsigned long flags;
/* Queue poll */
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
gsm_data_kick(gsm);
- if (gsm->tx_bytes < TX_THRESH_LO)
+ if (gsm->tx_bytes < TX_THRESH_LO) {
+ spin_lock_irqsave(&gsm->tx_lock, flags);
gsm_dlci_data_sweep(gsm);
+ spin_unlock_irqrestore(&gsm->tx_lock, flags);
+ }
}
/**
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 5d15630..5d64e3a 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -580,8 +580,12 @@
case KEY_RIGHTALT:
if (value)
sysrq_alt = code;
- else if (sysrq_down && code == sysrq_alt_use)
- sysrq_down = false;
+ else {
+ if (sysrq_down && code == sysrq_alt_use)
+ sysrq_down = false;
+
+ sysrq_alt = 0;
+ }
break;
case KEY_SYSRQ:
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 8e00b4d..792868d 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -224,6 +224,7 @@
u8 algorithm[4];
u8 encscheme[2];
u8 sigscheme[2];
+ __be32 paramsize;
u8 parameters[12]; /*assuming RSA*/
__be32 keysize;
u8 modulus[256];
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 8c99bf1..942a982 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -529,6 +529,10 @@
{
bool ret;
+ if (!port->guest_connected) {
+ /* Port got hot-unplugged. Let's exit. */
+ return false;
+ }
if (!port->host_connected)
return true;
@@ -1099,6 +1103,13 @@
{
struct port_buffer *buf;
+ if (port->guest_connected) {
+ port->guest_connected = false;
+ port->host_connected = false;
+ wake_up_interruptible(&port->waitqueue);
+ send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0);
+ }
+
spin_lock_irq(&port->portdev->ports_lock);
list_del(&port->list);
spin_unlock_irq(&port->portdev->ports_lock);
@@ -1120,9 +1131,6 @@
hvc_remove(port->cons.hvc);
#endif
}
- if (port->guest_connected)
- send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0);
-
sysfs_remove_group(&port->dev->kobj, &port_attribute_group);
device_destroy(pdrvdata.class, port->dev->devt);
cdev_del(&port->cdev);
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index 6aa1028..cb19dbc 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -1303,7 +1303,9 @@
if (!perm)
goto eperm;
ret = copy_from_user(&ui, up, sizeof(struct unimapinit));
- if (!ret)
+ if (ret)
+ ret = -EFAULT;
+ else
con_clear_unimap(vc, &ui);
break;
}
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index f6677cb..717305d 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -412,18 +412,10 @@
static int sh_cmt_clocksource_enable(struct clocksource *cs)
{
struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
- int ret;
p->total_cycles = 0;
- ret = sh_cmt_start(p, FLAG_CLOCKSOURCE);
- if (ret)
- return ret;
-
- /* TODO: calculate good shift from rate and counter bit width */
- cs->shift = 0;
- cs->mult = clocksource_hz2mult(p->rate, cs->shift);
- return 0;
+ return sh_cmt_start(p, FLAG_CLOCKSOURCE);
}
static void sh_cmt_clocksource_disable(struct clocksource *cs)
@@ -450,8 +442,20 @@
cs->resume = sh_cmt_clocksource_resume;
cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8);
cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
+
+ /* clk_get_rate() needs an enabled clock */
+ clk_enable(p->clk);
+ p->rate = clk_get_rate(p->clk) / (p->width == 16) ? 512 : 8;
+ clk_disable(p->clk);
+
+ /* TODO: calculate good shift from rate and counter bit width */
+ cs->shift = 0;
+ cs->mult = clocksource_hz2mult(p->rate, cs->shift);
+
dev_info(&p->pdev->dev, "used as clock source\n");
+
clocksource_register(cs);
+
return 0;
}
diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index 8e44e14..de71590 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -199,16 +199,8 @@
static int sh_tmu_clocksource_enable(struct clocksource *cs)
{
struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
- int ret;
- ret = sh_tmu_enable(p);
- if (ret)
- return ret;
-
- /* TODO: calculate good shift from rate and counter bit width */
- cs->shift = 10;
- cs->mult = clocksource_hz2mult(p->rate, cs->shift);
- return 0;
+ return sh_tmu_enable(p);
}
static void sh_tmu_clocksource_disable(struct clocksource *cs)
@@ -228,6 +220,16 @@
cs->disable = sh_tmu_clocksource_disable;
cs->mask = CLOCKSOURCE_MASK(32);
cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
+
+ /* clk_get_rate() needs an enabled clock */
+ clk_enable(p->clk);
+ /* channel will be configured at parent clock / 4 */
+ p->rate = clk_get_rate(p->clk) / 4;
+ clk_disable(p->clk);
+ /* TODO: calculate good shift from rate and counter bit width */
+ cs->shift = 10;
+ cs->mult = clocksource_hz2mult(p->rate, cs->shift);
+
dev_info(&p->pdev->dev, "used as clock source\n");
clocksource_register(cs);
return 0;
diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
index 9d65b37..983530b 100644
--- a/drivers/crypto/amcc/crypto4xx_core.c
+++ b/drivers/crypto/amcc/crypto4xx_core.c
@@ -1158,7 +1158,7 @@
struct device *dev = &ofdev->dev;
struct crypto4xx_core_device *core_dev;
- rc = of_address_to_resource(ofdev->node, 0, &res);
+ rc = of_address_to_resource(ofdev->dev.of_node, 0, &res);
if (rc)
return -ENODEV;
@@ -1215,13 +1215,13 @@
(unsigned long) dev);
/* Register for Crypto isr, Crypto Engine IRQ */
- core_dev->irq = irq_of_parse_and_map(ofdev->node, 0);
+ core_dev->irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
rc = request_irq(core_dev->irq, crypto4xx_ce_interrupt_handler, 0,
core_dev->dev->name, dev);
if (rc)
goto err_request_irq;
- core_dev->dev->ce_base = of_iomap(ofdev->node, 0);
+ core_dev->dev->ce_base = of_iomap(ofdev->dev.of_node, 0);
if (!core_dev->dev->ce_base) {
dev_err(dev, "failed to of_iomap\n");
goto err_iomap;
diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c
index 8566be8..23163fd 100644
--- a/drivers/crypto/n2_core.c
+++ b/drivers/crypto/n2_core.c
@@ -251,16 +251,10 @@
struct n2_hash_ctx {
struct n2_base_ctx base;
- struct crypto_ahash *fallback;
+ struct crypto_ahash *fallback_tfm;
+};
- /* These next three members must match the layout created by
- * crypto_init_shash_ops_async. This allows us to properly
- * plumb requests we can't do in hardware down to the fallback
- * operation, providing all of the data structures and layouts
- * expected by those paths.
- */
- struct ahash_request fallback_req;
- struct shash_desc fallback_desc;
+struct n2_hash_req_ctx {
union {
struct md5_state md5;
struct sha1_state sha1;
@@ -269,56 +263,62 @@
unsigned char hash_key[64];
unsigned char keyed_zero_hash[32];
+
+ struct ahash_request fallback_req;
};
static int n2_hash_async_init(struct ahash_request *req)
{
+ struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
- ctx->fallback_req.base.tfm = crypto_ahash_tfm(ctx->fallback);
- ctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
+ ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
+ rctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
- return crypto_ahash_init(&ctx->fallback_req);
+ return crypto_ahash_init(&rctx->fallback_req);
}
static int n2_hash_async_update(struct ahash_request *req)
{
+ struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
- ctx->fallback_req.base.tfm = crypto_ahash_tfm(ctx->fallback);
- ctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
- ctx->fallback_req.nbytes = req->nbytes;
- ctx->fallback_req.src = req->src;
+ ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
+ rctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
+ rctx->fallback_req.nbytes = req->nbytes;
+ rctx->fallback_req.src = req->src;
- return crypto_ahash_update(&ctx->fallback_req);
+ return crypto_ahash_update(&rctx->fallback_req);
}
static int n2_hash_async_final(struct ahash_request *req)
{
+ struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
- ctx->fallback_req.base.tfm = crypto_ahash_tfm(ctx->fallback);
- ctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
- ctx->fallback_req.result = req->result;
+ ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
+ rctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
+ rctx->fallback_req.result = req->result;
- return crypto_ahash_final(&ctx->fallback_req);
+ return crypto_ahash_final(&rctx->fallback_req);
}
static int n2_hash_async_finup(struct ahash_request *req)
{
+ struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
- ctx->fallback_req.base.tfm = crypto_ahash_tfm(ctx->fallback);
- ctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
- ctx->fallback_req.nbytes = req->nbytes;
- ctx->fallback_req.src = req->src;
- ctx->fallback_req.result = req->result;
+ ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
+ rctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
+ rctx->fallback_req.nbytes = req->nbytes;
+ rctx->fallback_req.src = req->src;
+ rctx->fallback_req.result = req->result;
- return crypto_ahash_finup(&ctx->fallback_req);
+ return crypto_ahash_finup(&rctx->fallback_req);
}
static int n2_hash_cra_init(struct crypto_tfm *tfm)
@@ -338,7 +338,10 @@
goto out;
}
- ctx->fallback = fallback_tfm;
+ crypto_ahash_set_reqsize(ahash, (sizeof(struct n2_hash_req_ctx) +
+ crypto_ahash_reqsize(fallback_tfm)));
+
+ ctx->fallback_tfm = fallback_tfm;
return 0;
out:
@@ -350,7 +353,7 @@
struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
struct n2_hash_ctx *ctx = crypto_ahash_ctx(ahash);
- crypto_free_ahash(ctx->fallback);
+ crypto_free_ahash(ctx->fallback_tfm);
}
static unsigned long wait_for_tail(struct spu_queue *qp)
@@ -399,14 +402,16 @@
* exceed 2^16.
*/
if (unlikely(req->nbytes > (1 << 16))) {
- ctx->fallback_req.base.tfm = crypto_ahash_tfm(ctx->fallback);
- ctx->fallback_req.base.flags =
- req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
- ctx->fallback_req.nbytes = req->nbytes;
- ctx->fallback_req.src = req->src;
- ctx->fallback_req.result = req->result;
+ struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
- return crypto_ahash_digest(&ctx->fallback_req);
+ ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
+ rctx->fallback_req.base.flags =
+ req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
+ rctx->fallback_req.nbytes = req->nbytes;
+ rctx->fallback_req.src = req->src;
+ rctx->fallback_req.result = req->result;
+
+ return crypto_ahash_digest(&rctx->fallback_req);
}
n2_base_ctx_init(&ctx->base);
@@ -472,9 +477,8 @@
static int n2_md5_async_digest(struct ahash_request *req)
{
- struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
- struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
- struct md5_state *m = &ctx->u.md5;
+ struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
+ struct md5_state *m = &rctx->u.md5;
if (unlikely(req->nbytes == 0)) {
static const char md5_zero[MD5_DIGEST_SIZE] = {
@@ -497,9 +501,8 @@
static int n2_sha1_async_digest(struct ahash_request *req)
{
- struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
- struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
- struct sha1_state *s = &ctx->u.sha1;
+ struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
+ struct sha1_state *s = &rctx->u.sha1;
if (unlikely(req->nbytes == 0)) {
static const char sha1_zero[SHA1_DIGEST_SIZE] = {
@@ -524,9 +527,8 @@
static int n2_sha256_async_digest(struct ahash_request *req)
{
- struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
- struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
- struct sha256_state *s = &ctx->u.sha256;
+ struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
+ struct sha256_state *s = &rctx->u.sha256;
if (req->nbytes == 0) {
static const char sha256_zero[SHA256_DIGEST_SIZE] = {
@@ -555,9 +557,8 @@
static int n2_sha224_async_digest(struct ahash_request *req)
{
- struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
- struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
- struct sha256_state *s = &ctx->u.sha256;
+ struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
+ struct sha256_state *s = &rctx->u.sha256;
if (req->nbytes == 0) {
static const char sha224_zero[SHA224_DIGEST_SIZE] = {
@@ -1398,7 +1399,7 @@
intr = ip->ino_table[i].intr;
- dev_intrs = of_get_property(dev->node, "interrupts", NULL);
+ dev_intrs = of_get_property(dev->dev.of_node, "interrupts", NULL);
if (!dev_intrs)
return -ENODEV;
@@ -1449,7 +1450,7 @@
{
if (!queue_cache[HV_NCS_QTYPE_MAU - 1])
queue_cache[HV_NCS_QTYPE_MAU - 1] =
- kmem_cache_create("cwq_queue",
+ kmem_cache_create("mau_queue",
(MAU_NUM_ENTRIES *
MAU_ENTRY_SIZE),
MAU_ENTRY_SIZE, 0, NULL);
@@ -1574,7 +1575,7 @@
id = mdesc_get_property(mdesc, tgt, "id", NULL);
if (table[*id] != NULL) {
dev_err(&dev->dev, "%s: SPU cpu slot already set.\n",
- dev->node->full_name);
+ dev->dev.of_node->full_name);
return -EINVAL;
}
cpu_set(*id, p->sharing);
@@ -1595,7 +1596,7 @@
p = kzalloc(sizeof(struct spu_queue), GFP_KERNEL);
if (!p) {
dev_err(&dev->dev, "%s: Could not allocate SPU queue.\n",
- dev->node->full_name);
+ dev->dev.of_node->full_name);
return -ENOMEM;
}
@@ -1684,7 +1685,7 @@
const unsigned int *reg;
u64 node;
- reg = of_get_property(dev->node, "reg", NULL);
+ reg = of_get_property(dev->dev.of_node, "reg", NULL);
if (!reg)
return -ENODEV;
@@ -1836,7 +1837,7 @@
n2_spu_driver_version();
- full_name = dev->node->full_name;
+ full_name = dev->dev.of_node->full_name;
pr_info("Found N2CP at %s\n", full_name);
np = alloc_n2cp();
@@ -1948,7 +1949,7 @@
n2_spu_driver_version();
- full_name = dev->node->full_name;
+ full_name = dev->dev.of_node->full_name;
pr_info("Found NCP at %s\n", full_name);
mp = alloc_ncp();
@@ -2034,8 +2035,11 @@
MODULE_DEVICE_TABLE(of, n2_crypto_match);
static struct of_platform_driver n2_crypto_driver = {
- .name = "n2cp",
- .match_table = n2_crypto_match,
+ .driver = {
+ .name = "n2cp",
+ .owner = THIS_MODULE,
+ .of_match_table = n2_crypto_match,
+ },
.probe = n2_crypto_probe,
.remove = __devexit_p(n2_crypto_remove),
};
@@ -2055,8 +2059,11 @@
MODULE_DEVICE_TABLE(of, n2_mau_match);
static struct of_platform_driver n2_mau_driver = {
- .name = "ncp",
- .match_table = n2_mau_match,
+ .driver = {
+ .name = "ncp",
+ .owner = THIS_MODULE,
+ .of_match_table = n2_mau_match,
+ },
.probe = n2_mau_probe,
.remove = __devexit_p(n2_mau_remove),
};
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 201e6e1..14a8c0f 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -630,7 +630,7 @@
static int __devinit mpc_dma_probe(struct of_device *op,
const struct of_device_id *match)
{
- struct device_node *dn = op->node;
+ struct device_node *dn = op->dev.of_node;
struct device *dev = &op->dev;
struct dma_device *dma;
struct mpc_dma *mdma;
@@ -771,12 +771,12 @@
};
static struct of_platform_driver mpc_dma_driver = {
- .match_table = mpc_dma_match,
.probe = mpc_dma_probe,
.remove = __devexit_p(mpc_dma_remove),
- .driver = {
- .name = DRV_NAME,
- .owner = THIS_MODULE,
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = mpc_dma_match,
},
};
diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c
index fa98abe..5a22ca69 100644
--- a/drivers/dma/ppc4xx/adma.c
+++ b/drivers/dma/ppc4xx/adma.c
@@ -4394,7 +4394,7 @@
static int __devinit ppc440spe_adma_probe(struct of_device *ofdev,
const struct of_device_id *match)
{
- struct device_node *np = ofdev->node;
+ struct device_node *np = ofdev->dev.of_node;
struct resource res;
struct ppc440spe_adma_device *adev;
struct ppc440spe_adma_chan *chan;
@@ -4626,7 +4626,7 @@
static int __devexit ppc440spe_adma_remove(struct of_device *ofdev)
{
struct ppc440spe_adma_device *adev = dev_get_drvdata(&ofdev->dev);
- struct device_node *np = ofdev->node;
+ struct device_node *np = ofdev->dev.of_node;
struct resource res;
struct dma_chan *chan, *_chan;
struct ppc_dma_chan_ref *ref, *_ref;
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 55c9c59..aedef79 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -69,6 +69,9 @@
occurred so that a particular failing memory module can be
replaced. If unsure, select 'Y'.
+config EDAC_MCE
+ bool
+
config EDAC_AMD64
tristate "AMD64 (Opteron, Athlon64) K8, F10h, F11h"
depends on EDAC_MM_EDAC && K8_NB && X86_64 && PCI && EDAC_DECODE_MCE
@@ -166,6 +169,16 @@
Support for error detection and correction the Intel
i5400 MCH chipset (Seaburg).
+config EDAC_I7CORE
+ tristate "Intel i7 Core (Nehalem) processors"
+ depends on EDAC_MM_EDAC && PCI && X86
+ select EDAC_MCE
+ help
+ Support for error detection and correction the Intel
+ i7 Core (Nehalem) Integrated Memory Controller that exists on
+ newer processors like i7 Core, i7 Core Extreme, Xeon 35xx
+ and Xeon 55xx processors.
+
config EDAC_I82860
tristate "Intel 82860"
depends on EDAC_MM_EDAC && PCI && X86_32
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index bc5dc23..ca6b1bb 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -8,6 +8,7 @@
obj-$(CONFIG_EDAC) := edac_stub.o
obj-$(CONFIG_EDAC_MM_EDAC) += edac_core.o
+obj-$(CONFIG_EDAC_MCE) += edac_mce.o
edac_core-objs := edac_mc.o edac_device.o edac_mc_sysfs.o edac_pci_sysfs.o
edac_core-objs += edac_module.o edac_device_sysfs.o
@@ -23,6 +24,7 @@
obj-$(CONFIG_EDAC_I5000) += i5000_edac.o
obj-$(CONFIG_EDAC_I5100) += i5100_edac.o
obj-$(CONFIG_EDAC_I5400) += i5400_edac.o
+obj-$(CONFIG_EDAC_I7CORE) += i7core_edac.o
obj-$(CONFIG_EDAC_E7XXX) += e7xxx_edac.o
obj-$(CONFIG_EDAC_E752X) += e752x_edac.o
obj-$(CONFIG_EDAC_I82443BXGX) += i82443bxgx_edac.o
diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h
index 001b2e79..efca934 100644
--- a/drivers/edac/edac_core.h
+++ b/drivers/edac/edac_core.h
@@ -341,12 +341,30 @@
struct channel_info *channels;
};
+struct mcidev_sysfs_group {
+ const char *name; /* group name */
+ struct mcidev_sysfs_attribute *mcidev_attr; /* group attributes */
+};
+
+struct mcidev_sysfs_group_kobj {
+ struct list_head list; /* list for all instances within a mc */
+
+ struct kobject kobj; /* kobj for the group */
+
+ struct mcidev_sysfs_group *grp; /* group description table */
+ struct mem_ctl_info *mci; /* the parent */
+};
+
/* mcidev_sysfs_attribute structure
* used for driver sysfs attributes and in mem_ctl_info
* sysfs top level entries
*/
struct mcidev_sysfs_attribute {
- struct attribute attr;
+ /* It should use either attr or grp */
+ struct attribute attr;
+ struct mcidev_sysfs_group *grp; /* Points to a group of attributes */
+
+ /* Ops for show/store values at the attribute - not used on group */
ssize_t (*show)(struct mem_ctl_info *,char *);
ssize_t (*store)(struct mem_ctl_info *, const char *,size_t);
};
@@ -424,6 +442,9 @@
/* edac sysfs device control */
struct kobject edac_mci_kobj;
+ /* list for all grp instances within a mc */
+ struct list_head grp_kobj_list;
+
/* Additional top controller level attributes, but specified
* by the low level driver.
*
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index 418b65f..c200c2f 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -557,6 +557,8 @@
struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr);
+ debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info);
+
if (mcidev_attr->show)
return mcidev_attr->show(mem_ctl_info, buffer);
@@ -569,6 +571,8 @@
struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr);
+ debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info);
+
if (mcidev_attr->store)
return mcidev_attr->store(mem_ctl_info, buffer, count);
@@ -726,28 +730,118 @@
#define EDAC_DEVICE_SYMLINK "device"
+#define grp_to_mci(k) (container_of(k, struct mcidev_sysfs_group_kobj, kobj)->mci)
+
+/* MCI show/store functions for top most object */
+static ssize_t inst_grp_show(struct kobject *kobj, struct attribute *attr,
+ char *buffer)
+{
+ struct mem_ctl_info *mem_ctl_info = grp_to_mci(kobj);
+ struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr);
+
+ debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info);
+
+ if (mcidev_attr->show)
+ return mcidev_attr->show(mem_ctl_info, buffer);
+
+ return -EIO;
+}
+
+static ssize_t inst_grp_store(struct kobject *kobj, struct attribute *attr,
+ const char *buffer, size_t count)
+{
+ struct mem_ctl_info *mem_ctl_info = grp_to_mci(kobj);
+ struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr);
+
+ debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info);
+
+ if (mcidev_attr->store)
+ return mcidev_attr->store(mem_ctl_info, buffer, count);
+
+ return -EIO;
+}
+
+/* No memory to release for this kobj */
+static void edac_inst_grp_release(struct kobject *kobj)
+{
+ struct mcidev_sysfs_group_kobj *grp;
+ struct mem_ctl_info *mci;
+
+ debugf1("%s()\n", __func__);
+
+ grp = container_of(kobj, struct mcidev_sysfs_group_kobj, kobj);
+ mci = grp->mci;
+
+ kobject_put(&mci->edac_mci_kobj);
+}
+
+/* Intermediate show/store table */
+static struct sysfs_ops inst_grp_ops = {
+ .show = inst_grp_show,
+ .store = inst_grp_store
+};
+
+/* the kobj_type instance for a instance group */
+static struct kobj_type ktype_inst_grp = {
+ .release = edac_inst_grp_release,
+ .sysfs_ops = &inst_grp_ops,
+};
+
+
/*
* edac_create_mci_instance_attributes
- * create MC driver specific attributes at the topmost level
- * directory of this mci instance.
+ * create MC driver specific attributes bellow an specified kobj
+ * This routine calls itself recursively, in order to create an entire
+ * object tree.
*/
-static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci)
+static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci,
+ struct mcidev_sysfs_attribute *sysfs_attrib,
+ struct kobject *kobj)
{
int err;
- struct mcidev_sysfs_attribute *sysfs_attrib;
- /* point to the start of the array and iterate over it
- * adding each attribute listed to this mci instance's kobject
- */
- sysfs_attrib = mci->mc_driver_sysfs_attributes;
+ debugf1("%s()\n", __func__);
- while (sysfs_attrib && sysfs_attrib->attr.name) {
- err = sysfs_create_file(&mci->edac_mci_kobj,
- (struct attribute*) sysfs_attrib);
+ while (sysfs_attrib) {
+ if (sysfs_attrib->grp) {
+ struct mcidev_sysfs_group_kobj *grp_kobj;
+
+ grp_kobj = kzalloc(sizeof(*grp_kobj), GFP_KERNEL);
+ if (!grp_kobj)
+ return -ENOMEM;
+
+ list_add_tail(&grp_kobj->list, &mci->grp_kobj_list);
+
+ grp_kobj->grp = sysfs_attrib->grp;
+ grp_kobj->mci = mci;
+
+ debugf0("%s() grp %s, mci %p\n", __func__,
+ sysfs_attrib->grp->name, mci);
+
+ err = kobject_init_and_add(&grp_kobj->kobj,
+ &ktype_inst_grp,
+ &mci->edac_mci_kobj,
+ sysfs_attrib->grp->name);
+ if (err)
+ return err;
+
+ err = edac_create_mci_instance_attributes(mci,
+ grp_kobj->grp->mcidev_attr,
+ &grp_kobj->kobj);
+
+ if (err)
+ return err;
+ } else if (sysfs_attrib->attr.name) {
+ debugf0("%s() file %s\n", __func__,
+ sysfs_attrib->attr.name);
+
+ err = sysfs_create_file(kobj, &sysfs_attrib->attr);
+ } else
+ break;
+
if (err) {
return err;
}
-
sysfs_attrib++;
}
@@ -759,21 +853,44 @@
* remove MC driver specific attributes at the topmost level
* directory of this mci instance.
*/
-static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci)
+static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci,
+ struct mcidev_sysfs_attribute *sysfs_attrib,
+ struct kobject *kobj, int count)
{
- struct mcidev_sysfs_attribute *sysfs_attrib;
+ struct mcidev_sysfs_group_kobj *grp_kobj, *tmp;
- /* point to the start of the array and iterate over it
- * adding each attribute listed to this mci instance's kobject
+ debugf1("%s()\n", __func__);
+
+ /*
+ * loop if there are attributes and until we hit a NULL entry
+ * Remove first all the atributes
*/
- sysfs_attrib = mci->mc_driver_sysfs_attributes;
-
- /* loop if there are attributes and until we hit a NULL entry */
- while (sysfs_attrib && sysfs_attrib->attr.name) {
- sysfs_remove_file(&mci->edac_mci_kobj,
- (struct attribute *) sysfs_attrib);
+ while (sysfs_attrib) {
+ if (sysfs_attrib->grp) {
+ list_for_each_entry(grp_kobj, &mci->grp_kobj_list,
+ list)
+ if (grp_kobj->grp == sysfs_attrib->grp)
+ edac_remove_mci_instance_attributes(mci,
+ grp_kobj->grp->mcidev_attr,
+ &grp_kobj->kobj, count + 1);
+ } else if (sysfs_attrib->attr.name) {
+ debugf0("%s() file %s\n", __func__,
+ sysfs_attrib->attr.name);
+ sysfs_remove_file(kobj, &sysfs_attrib->attr);
+ } else
+ break;
sysfs_attrib++;
}
+
+ /*
+ * Now that all attributes got removed, it is save to remove all groups
+ */
+ if (!count)
+ list_for_each_entry_safe(grp_kobj, tmp, &mci->grp_kobj_list,
+ list) {
+ debugf0("%s() grp %s\n", __func__, grp_kobj->grp->name);
+ kobject_put(&grp_kobj->kobj);
+ }
}
@@ -794,6 +911,8 @@
debugf0("%s() idx=%d\n", __func__, mci->mc_idx);
+ INIT_LIST_HEAD(&mci->grp_kobj_list);
+
/* create a symlink for the device */
err = sysfs_create_link(kobj_mci, &mci->dev->kobj,
EDAC_DEVICE_SYMLINK);
@@ -806,7 +925,9 @@
* then create them now for the driver.
*/
if (mci->mc_driver_sysfs_attributes) {
- err = edac_create_mci_instance_attributes(mci);
+ err = edac_create_mci_instance_attributes(mci,
+ mci->mc_driver_sysfs_attributes,
+ &mci->edac_mci_kobj);
if (err) {
debugf1("%s() failure to create mci attributes\n",
__func__);
@@ -841,7 +962,8 @@
}
/* remove the mci instance's attributes, if any */
- edac_remove_mci_instance_attributes(mci);
+ edac_remove_mci_instance_attributes(mci,
+ mci->mc_driver_sysfs_attributes, &mci->edac_mci_kobj, 0);
/* remove the symlink */
sysfs_remove_link(kobj_mci, EDAC_DEVICE_SYMLINK);
@@ -875,8 +997,9 @@
debugf0("%s() remove_mci_instance\n", __func__);
/* remove this mci instance's attribtes */
- edac_remove_mci_instance_attributes(mci);
-
+ edac_remove_mci_instance_attributes(mci,
+ mci->mc_driver_sysfs_attributes,
+ &mci->edac_mci_kobj, 0);
debugf0("%s() unregister this mci kobj\n", __func__);
/* unregister this instance's kobject */
diff --git a/drivers/edac/edac_mce.c b/drivers/edac/edac_mce.c
new file mode 100644
index 0000000..9ccdc5b
--- /dev/null
+++ b/drivers/edac/edac_mce.c
@@ -0,0 +1,61 @@
+/* Provides edac interface to mcelog events
+ *
+ * This file may be distributed under the terms of the
+ * GNU General Public License version 2.
+ *
+ * Copyright (c) 2009 by:
+ * Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ * Red Hat Inc. http://www.redhat.com
+ */
+
+#include <linux/module.h>
+#include <linux/edac_mce.h>
+#include <asm/mce.h>
+
+int edac_mce_enabled;
+EXPORT_SYMBOL_GPL(edac_mce_enabled);
+
+
+/*
+ * Extension interface
+ */
+
+static LIST_HEAD(edac_mce_list);
+static DEFINE_MUTEX(edac_mce_lock);
+
+int edac_mce_register(struct edac_mce *edac_mce)
+{
+ mutex_lock(&edac_mce_lock);
+ list_add_tail(&edac_mce->list, &edac_mce_list);
+ mutex_unlock(&edac_mce_lock);
+ return 0;
+}
+EXPORT_SYMBOL(edac_mce_register);
+
+void edac_mce_unregister(struct edac_mce *edac_mce)
+{
+ mutex_lock(&edac_mce_lock);
+ list_del(&edac_mce->list);
+ mutex_unlock(&edac_mce_lock);
+}
+EXPORT_SYMBOL(edac_mce_unregister);
+
+int edac_mce_parse(struct mce *mce)
+{
+ struct edac_mce *edac_mce;
+
+ list_for_each_entry(edac_mce, &edac_mce_list, list) {
+ if (edac_mce->check_error(edac_mce->priv, mce))
+ return 1;
+ }
+
+ /* Nobody queued the error */
+ return 0;
+}
+EXPORT_SYMBOL_GPL(edac_mce_parse);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
+MODULE_DESCRIPTION("EDAC Driver for mcelog captured errors");
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
new file mode 100644
index 0000000..6b8b7b4
--- /dev/null
+++ b/drivers/edac/i7core_edac.c
@@ -0,0 +1,2078 @@
+/* Intel i7 core/Nehalem Memory Controller kernel module
+ *
+ * This driver supports yhe memory controllers found on the Intel
+ * processor families i7core, i7core 7xx/8xx, i5core, Xeon 35xx,
+ * Xeon 55xx and Xeon 56xx also known as Nehalem, Nehalem-EP, Lynnfield
+ * and Westmere-EP.
+ *
+ * This file may be distributed under the terms of the
+ * GNU General Public License version 2 only.
+ *
+ * Copyright (c) 2009-2010 by:
+ * Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ * Red Hat Inc. http://www.redhat.com
+ *
+ * Forked and adapted from the i5400_edac driver
+ *
+ * Based on the following public Intel datasheets:
+ * Intel Core i7 Processor Extreme Edition and Intel Core i7 Processor
+ * Datasheet, Volume 2:
+ * http://download.intel.com/design/processor/datashts/320835.pdf
+ * Intel Xeon Processor 5500 Series Datasheet Volume 2
+ * http://www.intel.com/Assets/PDF/datasheet/321322.pdf
+ * also available at:
+ * http://www.arrownac.com/manufacturers/intel/s/nehalem/5500-datasheet-v2.pdf
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/edac.h>
+#include <linux/mmzone.h>
+#include <linux/edac_mce.h>
+#include <linux/smp.h>
+#include <asm/processor.h>
+
+#include "edac_core.h"
+
+/*
+ * This is used for Nehalem-EP and Nehalem-EX devices, where the non-core
+ * registers start at bus 255, and are not reported by BIOS.
+ * We currently find devices with only 2 sockets. In order to support more QPI
+ * Quick Path Interconnect, just increment this number.
+ */
+#define MAX_SOCKET_BUSES 2
+
+
+/*
+ * Alter this version for the module when modifications are made
+ */
+#define I7CORE_REVISION " Ver: 1.0.0 " __DATE__
+#define EDAC_MOD_STR "i7core_edac"
+
+/*
+ * Debug macros
+ */
+#define i7core_printk(level, fmt, arg...) \
+ edac_printk(level, "i7core", fmt, ##arg)
+
+#define i7core_mc_printk(mci, level, fmt, arg...) \
+ edac_mc_chipset_printk(mci, level, "i7core", fmt, ##arg)
+
+/*
+ * i7core Memory Controller Registers
+ */
+
+ /* OFFSETS for Device 0 Function 0 */
+
+#define MC_CFG_CONTROL 0x90
+
+ /* OFFSETS for Device 3 Function 0 */
+
+#define MC_CONTROL 0x48
+#define MC_STATUS 0x4c
+#define MC_MAX_DOD 0x64
+
+/*
+ * OFFSETS for Device 3 Function 4, as inicated on Xeon 5500 datasheet:
+ * http://www.arrownac.com/manufacturers/intel/s/nehalem/5500-datasheet-v2.pdf
+ */
+
+#define MC_TEST_ERR_RCV1 0x60
+ #define DIMM2_COR_ERR(r) ((r) & 0x7fff)
+
+#define MC_TEST_ERR_RCV0 0x64
+ #define DIMM1_COR_ERR(r) (((r) >> 16) & 0x7fff)
+ #define DIMM0_COR_ERR(r) ((r) & 0x7fff)
+
+/* OFFSETS for Device 3 Function 2, as inicated on Xeon 5500 datasheet */
+#define MC_COR_ECC_CNT_0 0x80
+#define MC_COR_ECC_CNT_1 0x84
+#define MC_COR_ECC_CNT_2 0x88
+#define MC_COR_ECC_CNT_3 0x8c
+#define MC_COR_ECC_CNT_4 0x90
+#define MC_COR_ECC_CNT_5 0x94
+
+#define DIMM_TOP_COR_ERR(r) (((r) >> 16) & 0x7fff)
+#define DIMM_BOT_COR_ERR(r) ((r) & 0x7fff)
+
+
+ /* OFFSETS for Devices 4,5 and 6 Function 0 */
+
+#define MC_CHANNEL_DIMM_INIT_PARAMS 0x58
+ #define THREE_DIMMS_PRESENT (1 << 24)
+ #define SINGLE_QUAD_RANK_PRESENT (1 << 23)
+ #define QUAD_RANK_PRESENT (1 << 22)
+ #define REGISTERED_DIMM (1 << 15)
+
+#define MC_CHANNEL_MAPPER 0x60
+ #define RDLCH(r, ch) ((((r) >> (3 + (ch * 6))) & 0x07) - 1)
+ #define WRLCH(r, ch) ((((r) >> (ch * 6)) & 0x07) - 1)
+
+#define MC_CHANNEL_RANK_PRESENT 0x7c
+ #define RANK_PRESENT_MASK 0xffff
+
+#define MC_CHANNEL_ADDR_MATCH 0xf0
+#define MC_CHANNEL_ERROR_MASK 0xf8
+#define MC_CHANNEL_ERROR_INJECT 0xfc
+ #define INJECT_ADDR_PARITY 0x10
+ #define INJECT_ECC 0x08
+ #define MASK_CACHELINE 0x06
+ #define MASK_FULL_CACHELINE 0x06
+ #define MASK_MSB32_CACHELINE 0x04
+ #define MASK_LSB32_CACHELINE 0x02
+ #define NO_MASK_CACHELINE 0x00
+ #define REPEAT_EN 0x01
+
+ /* OFFSETS for Devices 4,5 and 6 Function 1 */
+
+#define MC_DOD_CH_DIMM0 0x48
+#define MC_DOD_CH_DIMM1 0x4c
+#define MC_DOD_CH_DIMM2 0x50
+ #define RANKOFFSET_MASK ((1 << 12) | (1 << 11) | (1 << 10))
+ #define RANKOFFSET(x) ((x & RANKOFFSET_MASK) >> 10)
+ #define DIMM_PRESENT_MASK (1 << 9)
+ #define DIMM_PRESENT(x) (((x) & DIMM_PRESENT_MASK) >> 9)
+ #define MC_DOD_NUMBANK_MASK ((1 << 8) | (1 << 7))
+ #define MC_DOD_NUMBANK(x) (((x) & MC_DOD_NUMBANK_MASK) >> 7)
+ #define MC_DOD_NUMRANK_MASK ((1 << 6) | (1 << 5))
+ #define MC_DOD_NUMRANK(x) (((x) & MC_DOD_NUMRANK_MASK) >> 5)
+ #define MC_DOD_NUMROW_MASK ((1 << 4) | (1 << 3) | (1 << 2))
+ #define MC_DOD_NUMROW(x) (((x) & MC_DOD_NUMROW_MASK) >> 2)
+ #define MC_DOD_NUMCOL_MASK 3
+ #define MC_DOD_NUMCOL(x) ((x) & MC_DOD_NUMCOL_MASK)
+
+#define MC_RANK_PRESENT 0x7c
+
+#define MC_SAG_CH_0 0x80
+#define MC_SAG_CH_1 0x84
+#define MC_SAG_CH_2 0x88
+#define MC_SAG_CH_3 0x8c
+#define MC_SAG_CH_4 0x90
+#define MC_SAG_CH_5 0x94
+#define MC_SAG_CH_6 0x98
+#define MC_SAG_CH_7 0x9c
+
+#define MC_RIR_LIMIT_CH_0 0x40
+#define MC_RIR_LIMIT_CH_1 0x44
+#define MC_RIR_LIMIT_CH_2 0x48
+#define MC_RIR_LIMIT_CH_3 0x4C
+#define MC_RIR_LIMIT_CH_4 0x50
+#define MC_RIR_LIMIT_CH_5 0x54
+#define MC_RIR_LIMIT_CH_6 0x58
+#define MC_RIR_LIMIT_CH_7 0x5C
+#define MC_RIR_LIMIT_MASK ((1 << 10) - 1)
+
+#define MC_RIR_WAY_CH 0x80
+ #define MC_RIR_WAY_OFFSET_MASK (((1 << 14) - 1) & ~0x7)
+ #define MC_RIR_WAY_RANK_MASK 0x7
+
+/*
+ * i7core structs
+ */
+
+#define NUM_CHANS 3
+#define MAX_DIMMS 3 /* Max DIMMS per channel */
+#define MAX_MCR_FUNC 4
+#define MAX_CHAN_FUNC 3
+
+struct i7core_info {
+ u32 mc_control;
+ u32 mc_status;
+ u32 max_dod;
+ u32 ch_map;
+};
+
+
+struct i7core_inject {
+ int enable;
+
+ u32 section;
+ u32 type;
+ u32 eccmask;
+
+ /* Error address mask */
+ int channel, dimm, rank, bank, page, col;
+};
+
+struct i7core_channel {
+ u32 ranks;
+ u32 dimms;
+};
+
+struct pci_id_descr {
+ int dev;
+ int func;
+ int dev_id;
+ int optional;
+};
+
+struct pci_id_table {
+ struct pci_id_descr *descr;
+ int n_devs;
+};
+
+struct i7core_dev {
+ struct list_head list;
+ u8 socket;
+ struct pci_dev **pdev;
+ int n_devs;
+ struct mem_ctl_info *mci;
+};
+
+struct i7core_pvt {
+ struct pci_dev *pci_noncore;
+ struct pci_dev *pci_mcr[MAX_MCR_FUNC + 1];
+ struct pci_dev *pci_ch[NUM_CHANS][MAX_CHAN_FUNC + 1];
+
+ struct i7core_dev *i7core_dev;
+
+ struct i7core_info info;
+ struct i7core_inject inject;
+ struct i7core_channel channel[NUM_CHANS];
+
+ int channels; /* Number of active channels */
+
+ int ce_count_available;
+ int csrow_map[NUM_CHANS][MAX_DIMMS];
+
+ /* ECC corrected errors counts per udimm */
+ unsigned long udimm_ce_count[MAX_DIMMS];
+ int udimm_last_ce_count[MAX_DIMMS];
+ /* ECC corrected errors counts per rdimm */
+ unsigned long rdimm_ce_count[NUM_CHANS][MAX_DIMMS];
+ int rdimm_last_ce_count[NUM_CHANS][MAX_DIMMS];
+
+ unsigned int is_registered;
+
+ /* mcelog glue */
+ struct edac_mce edac_mce;
+
+ /* Fifo double buffers */
+ struct mce mce_entry[MCE_LOG_LEN];
+ struct mce mce_outentry[MCE_LOG_LEN];
+
+ /* Fifo in/out counters */
+ unsigned mce_in, mce_out;
+
+ /* Count indicator to show errors not got */
+ unsigned mce_overrun;
+};
+
+/* Static vars */
+static LIST_HEAD(i7core_edac_list);
+static DEFINE_MUTEX(i7core_edac_lock);
+
+#define PCI_DESCR(device, function, device_id) \
+ .dev = (device), \
+ .func = (function), \
+ .dev_id = (device_id)
+
+struct pci_id_descr pci_dev_descr_i7core_nehalem[] = {
+ /* Memory controller */
+ { PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_I7_MCR) },
+ { PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_I7_MC_TAD) },
+ /* Exists only for RDIMM */
+ { PCI_DESCR(3, 2, PCI_DEVICE_ID_INTEL_I7_MC_RAS), .optional = 1 },
+ { PCI_DESCR(3, 4, PCI_DEVICE_ID_INTEL_I7_MC_TEST) },
+
+ /* Channel 0 */
+ { PCI_DESCR(4, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH0_CTRL) },
+ { PCI_DESCR(4, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH0_ADDR) },
+ { PCI_DESCR(4, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH0_RANK) },
+ { PCI_DESCR(4, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH0_TC) },
+
+ /* Channel 1 */
+ { PCI_DESCR(5, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH1_CTRL) },
+ { PCI_DESCR(5, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH1_ADDR) },
+ { PCI_DESCR(5, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH1_RANK) },
+ { PCI_DESCR(5, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH1_TC) },
+
+ /* Channel 2 */
+ { PCI_DESCR(6, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH2_CTRL) },
+ { PCI_DESCR(6, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH2_ADDR) },
+ { PCI_DESCR(6, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH2_RANK) },
+ { PCI_DESCR(6, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC) },
+
+ /* Generic Non-core registers */
+ /*
+ * This is the PCI device on i7core and on Xeon 35xx (8086:2c41)
+ * On Xeon 55xx, however, it has a different id (8086:2c40). So,
+ * the probing code needs to test for the other address in case of
+ * failure of this one
+ */
+ { PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_I7_NONCORE) },
+
+};
+
+struct pci_id_descr pci_dev_descr_lynnfield[] = {
+ { PCI_DESCR( 3, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MCR) },
+ { PCI_DESCR( 3, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TAD) },
+ { PCI_DESCR( 3, 4, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TEST) },
+
+ { PCI_DESCR( 4, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_CTRL) },
+ { PCI_DESCR( 4, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_ADDR) },
+ { PCI_DESCR( 4, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_RANK) },
+ { PCI_DESCR( 4, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_TC) },
+
+ { PCI_DESCR( 5, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_CTRL) },
+ { PCI_DESCR( 5, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_ADDR) },
+ { PCI_DESCR( 5, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_RANK) },
+ { PCI_DESCR( 5, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_TC) },
+
+ /*
+ * This is the PCI device has an alternate address on some
+ * processors like Core i7 860
+ */
+ { PCI_DESCR( 0, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE) },
+};
+
+struct pci_id_descr pci_dev_descr_i7core_westmere[] = {
+ /* Memory controller */
+ { PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MCR_REV2) },
+ { PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TAD_REV2) },
+ /* Exists only for RDIMM */
+ { PCI_DESCR(3, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_RAS_REV2), .optional = 1 },
+ { PCI_DESCR(3, 4, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TEST_REV2) },
+
+ /* Channel 0 */
+ { PCI_DESCR(4, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_CTRL_REV2) },
+ { PCI_DESCR(4, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_ADDR_REV2) },
+ { PCI_DESCR(4, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_RANK_REV2) },
+ { PCI_DESCR(4, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_TC_REV2) },
+
+ /* Channel 1 */
+ { PCI_DESCR(5, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_CTRL_REV2) },
+ { PCI_DESCR(5, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_ADDR_REV2) },
+ { PCI_DESCR(5, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_RANK_REV2) },
+ { PCI_DESCR(5, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_TC_REV2) },
+
+ /* Channel 2 */
+ { PCI_DESCR(6, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_CTRL_REV2) },
+ { PCI_DESCR(6, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_ADDR_REV2) },
+ { PCI_DESCR(6, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_RANK_REV2) },
+ { PCI_DESCR(6, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_TC_REV2) },
+
+ /* Generic Non-core registers */
+ { PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_REV2) },
+
+};
+
+#define PCI_ID_TABLE_ENTRY(A) { A, ARRAY_SIZE(A) }
+struct pci_id_table pci_dev_table[] = {
+ PCI_ID_TABLE_ENTRY(pci_dev_descr_i7core_nehalem),
+ PCI_ID_TABLE_ENTRY(pci_dev_descr_lynnfield),
+ PCI_ID_TABLE_ENTRY(pci_dev_descr_i7core_westmere),
+};
+
+/*
+ * pci_device_id table for which devices we are looking for
+ */
+static const struct pci_device_id i7core_pci_tbl[] __devinitdata = {
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_X58_HUB_MGMT)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNNFIELD_QPI_LINK0)},
+ {0,} /* 0 terminated list. */
+};
+
+static struct edac_pci_ctl_info *i7core_pci;
+
+/****************************************************************************
+ Anciliary status routines
+ ****************************************************************************/
+
+ /* MC_CONTROL bits */
+#define CH_ACTIVE(pvt, ch) ((pvt)->info.mc_control & (1 << (8 + ch)))
+#define ECCx8(pvt) ((pvt)->info.mc_control & (1 << 1))
+
+ /* MC_STATUS bits */
+#define ECC_ENABLED(pvt) ((pvt)->info.mc_status & (1 << 4))
+#define CH_DISABLED(pvt, ch) ((pvt)->info.mc_status & (1 << ch))
+
+ /* MC_MAX_DOD read functions */
+static inline int numdimms(u32 dimms)
+{
+ return (dimms & 0x3) + 1;
+}
+
+static inline int numrank(u32 rank)
+{
+ static int ranks[4] = { 1, 2, 4, -EINVAL };
+
+ return ranks[rank & 0x3];
+}
+
+static inline int numbank(u32 bank)
+{
+ static int banks[4] = { 4, 8, 16, -EINVAL };
+
+ return banks[bank & 0x3];
+}
+
+static inline int numrow(u32 row)
+{
+ static int rows[8] = {
+ 1 << 12, 1 << 13, 1 << 14, 1 << 15,
+ 1 << 16, -EINVAL, -EINVAL, -EINVAL,
+ };
+
+ return rows[row & 0x7];
+}
+
+static inline int numcol(u32 col)
+{
+ static int cols[8] = {
+ 1 << 10, 1 << 11, 1 << 12, -EINVAL,
+ };
+ return cols[col & 0x3];
+}
+
+static struct i7core_dev *get_i7core_dev(u8 socket)
+{
+ struct i7core_dev *i7core_dev;
+
+ list_for_each_entry(i7core_dev, &i7core_edac_list, list) {
+ if (i7core_dev->socket == socket)
+ return i7core_dev;
+ }
+
+ return NULL;
+}
+
+/****************************************************************************
+ Memory check routines
+ ****************************************************************************/
+static struct pci_dev *get_pdev_slot_func(u8 socket, unsigned slot,
+ unsigned func)
+{
+ struct i7core_dev *i7core_dev = get_i7core_dev(socket);
+ int i;
+
+ if (!i7core_dev)
+ return NULL;
+
+ for (i = 0; i < i7core_dev->n_devs; i++) {
+ if (!i7core_dev->pdev[i])
+ continue;
+
+ if (PCI_SLOT(i7core_dev->pdev[i]->devfn) == slot &&
+ PCI_FUNC(i7core_dev->pdev[i]->devfn) == func) {
+ return i7core_dev->pdev[i];
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * i7core_get_active_channels() - gets the number of channels and csrows
+ * @socket: Quick Path Interconnect socket
+ * @channels: Number of channels that will be returned
+ * @csrows: Number of csrows found
+ *
+ * Since EDAC core needs to know in advance the number of available channels
+ * and csrows, in order to allocate memory for csrows/channels, it is needed
+ * to run two similar steps. At the first step, implemented on this function,
+ * it checks the number of csrows/channels present at one socket.
+ * this is used in order to properly allocate the size of mci components.
+ *
+ * It should be noticed that none of the current available datasheets explain
+ * or even mention how csrows are seen by the memory controller. So, we need
+ * to add a fake description for csrows.
+ * So, this driver is attributing one DIMM memory for one csrow.
+ */
+static int i7core_get_active_channels(u8 socket, unsigned *channels,
+ unsigned *csrows)
+{
+ struct pci_dev *pdev = NULL;
+ int i, j;
+ u32 status, control;
+
+ *channels = 0;
+ *csrows = 0;
+
+ pdev = get_pdev_slot_func(socket, 3, 0);
+ if (!pdev) {
+ i7core_printk(KERN_ERR, "Couldn't find socket %d fn 3.0!!!\n",
+ socket);
+ return -ENODEV;
+ }
+
+ /* Device 3 function 0 reads */
+ pci_read_config_dword(pdev, MC_STATUS, &status);
+ pci_read_config_dword(pdev, MC_CONTROL, &control);
+
+ for (i = 0; i < NUM_CHANS; i++) {
+ u32 dimm_dod[3];
+ /* Check if the channel is active */
+ if (!(control & (1 << (8 + i))))
+ continue;
+
+ /* Check if the channel is disabled */
+ if (status & (1 << i))
+ continue;
+
+ pdev = get_pdev_slot_func(socket, i + 4, 1);
+ if (!pdev) {
+ i7core_printk(KERN_ERR, "Couldn't find socket %d "
+ "fn %d.%d!!!\n",
+ socket, i + 4, 1);
+ return -ENODEV;
+ }
+ /* Devices 4-6 function 1 */
+ pci_read_config_dword(pdev,
+ MC_DOD_CH_DIMM0, &dimm_dod[0]);
+ pci_read_config_dword(pdev,
+ MC_DOD_CH_DIMM1, &dimm_dod[1]);
+ pci_read_config_dword(pdev,
+ MC_DOD_CH_DIMM2, &dimm_dod[2]);
+
+ (*channels)++;
+
+ for (j = 0; j < 3; j++) {
+ if (!DIMM_PRESENT(dimm_dod[j]))
+ continue;
+ (*csrows)++;
+ }
+ }
+
+ debugf0("Number of active channels on socket %d: %d\n",
+ socket, *channels);
+
+ return 0;
+}
+
+static int get_dimm_config(struct mem_ctl_info *mci, int *csrow)
+{
+ struct i7core_pvt *pvt = mci->pvt_info;
+ struct csrow_info *csr;
+ struct pci_dev *pdev;
+ int i, j;
+ unsigned long last_page = 0;
+ enum edac_type mode;
+ enum mem_type mtype;
+
+ /* Get data from the MC register, function 0 */
+ pdev = pvt->pci_mcr[0];
+ if (!pdev)
+ return -ENODEV;
+
+ /* Device 3 function 0 reads */
+ pci_read_config_dword(pdev, MC_CONTROL, &pvt->info.mc_control);
+ pci_read_config_dword(pdev, MC_STATUS, &pvt->info.mc_status);
+ pci_read_config_dword(pdev, MC_MAX_DOD, &pvt->info.max_dod);
+ pci_read_config_dword(pdev, MC_CHANNEL_MAPPER, &pvt->info.ch_map);
+
+ debugf0("QPI %d control=0x%08x status=0x%08x dod=0x%08x map=0x%08x\n",
+ pvt->i7core_dev->socket, pvt->info.mc_control, pvt->info.mc_status,
+ pvt->info.max_dod, pvt->info.ch_map);
+
+ if (ECC_ENABLED(pvt)) {
+ debugf0("ECC enabled with x%d SDCC\n", ECCx8(pvt) ? 8 : 4);
+ if (ECCx8(pvt))
+ mode = EDAC_S8ECD8ED;
+ else
+ mode = EDAC_S4ECD4ED;
+ } else {
+ debugf0("ECC disabled\n");
+ mode = EDAC_NONE;
+ }
+
+ /* FIXME: need to handle the error codes */
+ debugf0("DOD Max limits: DIMMS: %d, %d-ranked, %d-banked "
+ "x%x x 0x%x\n",
+ numdimms(pvt->info.max_dod),
+ numrank(pvt->info.max_dod >> 2),
+ numbank(pvt->info.max_dod >> 4),
+ numrow(pvt->info.max_dod >> 6),
+ numcol(pvt->info.max_dod >> 9));
+
+ for (i = 0; i < NUM_CHANS; i++) {
+ u32 data, dimm_dod[3], value[8];
+
+ if (!pvt->pci_ch[i][0])
+ continue;
+
+ if (!CH_ACTIVE(pvt, i)) {
+ debugf0("Channel %i is not active\n", i);
+ continue;
+ }
+ if (CH_DISABLED(pvt, i)) {
+ debugf0("Channel %i is disabled\n", i);
+ continue;
+ }
+
+ /* Devices 4-6 function 0 */
+ pci_read_config_dword(pvt->pci_ch[i][0],
+ MC_CHANNEL_DIMM_INIT_PARAMS, &data);
+
+ pvt->channel[i].ranks = (data & QUAD_RANK_PRESENT) ?
+ 4 : 2;
+
+ if (data & REGISTERED_DIMM)
+ mtype = MEM_RDDR3;
+ else
+ mtype = MEM_DDR3;
+#if 0
+ if (data & THREE_DIMMS_PRESENT)
+ pvt->channel[i].dimms = 3;
+ else if (data & SINGLE_QUAD_RANK_PRESENT)
+ pvt->channel[i].dimms = 1;
+ else
+ pvt->channel[i].dimms = 2;
+#endif
+
+ /* Devices 4-6 function 1 */
+ pci_read_config_dword(pvt->pci_ch[i][1],
+ MC_DOD_CH_DIMM0, &dimm_dod[0]);
+ pci_read_config_dword(pvt->pci_ch[i][1],
+ MC_DOD_CH_DIMM1, &dimm_dod[1]);
+ pci_read_config_dword(pvt->pci_ch[i][1],
+ MC_DOD_CH_DIMM2, &dimm_dod[2]);
+
+ debugf0("Ch%d phy rd%d, wr%d (0x%08x): "
+ "%d ranks, %cDIMMs\n",
+ i,
+ RDLCH(pvt->info.ch_map, i), WRLCH(pvt->info.ch_map, i),
+ data,
+ pvt->channel[i].ranks,
+ (data & REGISTERED_DIMM) ? 'R' : 'U');
+
+ for (j = 0; j < 3; j++) {
+ u32 banks, ranks, rows, cols;
+ u32 size, npages;
+
+ if (!DIMM_PRESENT(dimm_dod[j]))
+ continue;
+
+ banks = numbank(MC_DOD_NUMBANK(dimm_dod[j]));
+ ranks = numrank(MC_DOD_NUMRANK(dimm_dod[j]));
+ rows = numrow(MC_DOD_NUMROW(dimm_dod[j]));
+ cols = numcol(MC_DOD_NUMCOL(dimm_dod[j]));
+
+ /* DDR3 has 8 I/O banks */
+ size = (rows * cols * banks * ranks) >> (20 - 3);
+
+ pvt->channel[i].dimms++;
+
+ debugf0("\tdimm %d %d Mb offset: %x, "
+ "bank: %d, rank: %d, row: %#x, col: %#x\n",
+ j, size,
+ RANKOFFSET(dimm_dod[j]),
+ banks, ranks, rows, cols);
+
+#if PAGE_SHIFT > 20
+ npages = size >> (PAGE_SHIFT - 20);
+#else
+ npages = size << (20 - PAGE_SHIFT);
+#endif
+
+ csr = &mci->csrows[*csrow];
+ csr->first_page = last_page + 1;
+ last_page += npages;
+ csr->last_page = last_page;
+ csr->nr_pages = npages;
+
+ csr->page_mask = 0;
+ csr->grain = 8;
+ csr->csrow_idx = *csrow;
+ csr->nr_channels = 1;
+
+ csr->channels[0].chan_idx = i;
+ csr->channels[0].ce_count = 0;
+
+ pvt->csrow_map[i][j] = *csrow;
+
+ switch (banks) {
+ case 4:
+ csr->dtype = DEV_X4;
+ break;
+ case 8:
+ csr->dtype = DEV_X8;
+ break;
+ case 16:
+ csr->dtype = DEV_X16;
+ break;
+ default:
+ csr->dtype = DEV_UNKNOWN;
+ }
+
+ csr->edac_mode = mode;
+ csr->mtype = mtype;
+
+ (*csrow)++;
+ }
+
+ pci_read_config_dword(pdev, MC_SAG_CH_0, &value[0]);
+ pci_read_config_dword(pdev, MC_SAG_CH_1, &value[1]);
+ pci_read_config_dword(pdev, MC_SAG_CH_2, &value[2]);
+ pci_read_config_dword(pdev, MC_SAG_CH_3, &value[3]);
+ pci_read_config_dword(pdev, MC_SAG_CH_4, &value[4]);
+ pci_read_config_dword(pdev, MC_SAG_CH_5, &value[5]);
+ pci_read_config_dword(pdev, MC_SAG_CH_6, &value[6]);
+ pci_read_config_dword(pdev, MC_SAG_CH_7, &value[7]);
+ debugf1("\t[%i] DIVBY3\tREMOVED\tOFFSET\n", i);
+ for (j = 0; j < 8; j++)
+ debugf1("\t\t%#x\t%#x\t%#x\n",
+ (value[j] >> 27) & 0x1,
+ (value[j] >> 24) & 0x7,
+ (value[j] && ((1 << 24) - 1)));
+ }
+
+ return 0;
+}
+
+/****************************************************************************
+ Error insertion routines
+ ****************************************************************************/
+
+/* The i7core has independent error injection features per channel.
+ However, to have a simpler code, we don't allow enabling error injection
+ on more than one channel.
+ Also, since a change at an inject parameter will be applied only at enable,
+ we're disabling error injection on all write calls to the sysfs nodes that
+ controls the error code injection.
+ */
+static int disable_inject(struct mem_ctl_info *mci)
+{
+ struct i7core_pvt *pvt = mci->pvt_info;
+
+ pvt->inject.enable = 0;
+
+ if (!pvt->pci_ch[pvt->inject.channel][0])
+ return -ENODEV;
+
+ pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0],
+ MC_CHANNEL_ERROR_INJECT, 0);
+
+ return 0;
+}
+
+/*
+ * i7core inject inject.section
+ *
+ * accept and store error injection inject.section value
+ * bit 0 - refers to the lower 32-byte half cacheline
+ * bit 1 - refers to the upper 32-byte half cacheline
+ */
+static ssize_t i7core_inject_section_store(struct mem_ctl_info *mci,
+ const char *data, size_t count)
+{
+ struct i7core_pvt *pvt = mci->pvt_info;
+ unsigned long value;
+ int rc;
+
+ if (pvt->inject.enable)
+ disable_inject(mci);
+
+ rc = strict_strtoul(data, 10, &value);
+ if ((rc < 0) || (value > 3))
+ return -EIO;
+
+ pvt->inject.section = (u32) value;
+ return count;
+}
+
+static ssize_t i7core_inject_section_show(struct mem_ctl_info *mci,
+ char *data)
+{
+ struct i7core_pvt *pvt = mci->pvt_info;
+ return sprintf(data, "0x%08x\n", pvt->inject.section);
+}
+
+/*
+ * i7core inject.type
+ *
+ * accept and store error injection inject.section value
+ * bit 0 - repeat enable - Enable error repetition
+ * bit 1 - inject ECC error
+ * bit 2 - inject parity error
+ */
+static ssize_t i7core_inject_type_store(struct mem_ctl_info *mci,
+ const char *data, size_t count)
+{
+ struct i7core_pvt *pvt = mci->pvt_info;
+ unsigned long value;
+ int rc;
+
+ if (pvt->inject.enable)
+ disable_inject(mci);
+
+ rc = strict_strtoul(data, 10, &value);
+ if ((rc < 0) || (value > 7))
+ return -EIO;
+
+ pvt->inject.type = (u32) value;
+ return count;
+}
+
+static ssize_t i7core_inject_type_show(struct mem_ctl_info *mci,
+ char *data)
+{
+ struct i7core_pvt *pvt = mci->pvt_info;
+ return sprintf(data, "0x%08x\n", pvt->inject.type);
+}
+
+/*
+ * i7core_inject_inject.eccmask_store
+ *
+ * The type of error (UE/CE) will depend on the inject.eccmask value:
+ * Any bits set to a 1 will flip the corresponding ECC bit
+ * Correctable errors can be injected by flipping 1 bit or the bits within
+ * a symbol pair (2 consecutive aligned 8-bit pairs - i.e. 7:0 and 15:8 or
+ * 23:16 and 31:24). Flipping bits in two symbol pairs will cause an
+ * uncorrectable error to be injected.
+ */
+static ssize_t i7core_inject_eccmask_store(struct mem_ctl_info *mci,
+ const char *data, size_t count)
+{
+ struct i7core_pvt *pvt = mci->pvt_info;
+ unsigned long value;
+ int rc;
+
+ if (pvt->inject.enable)
+ disable_inject(mci);
+
+ rc = strict_strtoul(data, 10, &value);
+ if (rc < 0)
+ return -EIO;
+
+ pvt->inject.eccmask = (u32) value;
+ return count;
+}
+
+static ssize_t i7core_inject_eccmask_show(struct mem_ctl_info *mci,
+ char *data)
+{
+ struct i7core_pvt *pvt = mci->pvt_info;
+ return sprintf(data, "0x%08x\n", pvt->inject.eccmask);
+}
+
+/*
+ * i7core_addrmatch
+ *
+ * The type of error (UE/CE) will depend on the inject.eccmask value:
+ * Any bits set to a 1 will flip the corresponding ECC bit
+ * Correctable errors can be injected by flipping 1 bit or the bits within
+ * a symbol pair (2 consecutive aligned 8-bit pairs - i.e. 7:0 and 15:8 or
+ * 23:16 and 31:24). Flipping bits in two symbol pairs will cause an
+ * uncorrectable error to be injected.
+ */
+
+#define DECLARE_ADDR_MATCH(param, limit) \
+static ssize_t i7core_inject_store_##param( \
+ struct mem_ctl_info *mci, \
+ const char *data, size_t count) \
+{ \
+ struct i7core_pvt *pvt; \
+ long value; \
+ int rc; \
+ \
+ debugf1("%s()\n", __func__); \
+ pvt = mci->pvt_info; \
+ \
+ if (pvt->inject.enable) \
+ disable_inject(mci); \
+ \
+ if (!strcasecmp(data, "any") || !strcasecmp(data, "any\n"))\
+ value = -1; \
+ else { \
+ rc = strict_strtoul(data, 10, &value); \
+ if ((rc < 0) || (value >= limit)) \
+ return -EIO; \
+ } \
+ \
+ pvt->inject.param = value; \
+ \
+ return count; \
+} \
+ \
+static ssize_t i7core_inject_show_##param( \
+ struct mem_ctl_info *mci, \
+ char *data) \
+{ \
+ struct i7core_pvt *pvt; \
+ \
+ pvt = mci->pvt_info; \
+ debugf1("%s() pvt=%p\n", __func__, pvt); \
+ if (pvt->inject.param < 0) \
+ return sprintf(data, "any\n"); \
+ else \
+ return sprintf(data, "%d\n", pvt->inject.param);\
+}
+
+#define ATTR_ADDR_MATCH(param) \
+ { \
+ .attr = { \
+ .name = #param, \
+ .mode = (S_IRUGO | S_IWUSR) \
+ }, \
+ .show = i7core_inject_show_##param, \
+ .store = i7core_inject_store_##param, \
+ }
+
+DECLARE_ADDR_MATCH(channel, 3);
+DECLARE_ADDR_MATCH(dimm, 3);
+DECLARE_ADDR_MATCH(rank, 4);
+DECLARE_ADDR_MATCH(bank, 32);
+DECLARE_ADDR_MATCH(page, 0x10000);
+DECLARE_ADDR_MATCH(col, 0x4000);
+
+static int write_and_test(struct pci_dev *dev, int where, u32 val)
+{
+ u32 read;
+ int count;
+
+ debugf0("setting pci %02x:%02x.%x reg=%02x value=%08x\n",
+ dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
+ where, val);
+
+ for (count = 0; count < 10; count++) {
+ if (count)
+ msleep(100);
+ pci_write_config_dword(dev, where, val);
+ pci_read_config_dword(dev, where, &read);
+
+ if (read == val)
+ return 0;
+ }
+
+ i7core_printk(KERN_ERR, "Error during set pci %02x:%02x.%x reg=%02x "
+ "write=%08x. Read=%08x\n",
+ dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
+ where, val, read);
+
+ return -EINVAL;
+}
+
+/*
+ * This routine prepares the Memory Controller for error injection.
+ * The error will be injected when some process tries to write to the
+ * memory that matches the given criteria.
+ * The criteria can be set in terms of a mask where dimm, rank, bank, page
+ * and col can be specified.
+ * A -1 value for any of the mask items will make the MCU to ignore
+ * that matching criteria for error injection.
+ *
+ * It should be noticed that the error will only happen after a write operation
+ * on a memory that matches the condition. if REPEAT_EN is not enabled at
+ * inject mask, then it will produce just one error. Otherwise, it will repeat
+ * until the injectmask would be cleaned.
+ *
+ * FIXME: This routine assumes that MAXNUMDIMMS value of MC_MAX_DOD
+ * is reliable enough to check if the MC is using the
+ * three channels. However, this is not clear at the datasheet.
+ */
+static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
+ const char *data, size_t count)
+{
+ struct i7core_pvt *pvt = mci->pvt_info;
+ u32 injectmask;
+ u64 mask = 0;
+ int rc;
+ long enable;
+
+ if (!pvt->pci_ch[pvt->inject.channel][0])
+ return 0;
+
+ rc = strict_strtoul(data, 10, &enable);
+ if ((rc < 0))
+ return 0;
+
+ if (enable) {
+ pvt->inject.enable = 1;
+ } else {
+ disable_inject(mci);
+ return count;
+ }
+
+ /* Sets pvt->inject.dimm mask */
+ if (pvt->inject.dimm < 0)
+ mask |= 1LL << 41;
+ else {
+ if (pvt->channel[pvt->inject.channel].dimms > 2)
+ mask |= (pvt->inject.dimm & 0x3LL) << 35;
+ else
+ mask |= (pvt->inject.dimm & 0x1LL) << 36;
+ }
+
+ /* Sets pvt->inject.rank mask */
+ if (pvt->inject.rank < 0)
+ mask |= 1LL << 40;
+ else {
+ if (pvt->channel[pvt->inject.channel].dimms > 2)
+ mask |= (pvt->inject.rank & 0x1LL) << 34;
+ else
+ mask |= (pvt->inject.rank & 0x3LL) << 34;
+ }
+
+ /* Sets pvt->inject.bank mask */
+ if (pvt->inject.bank < 0)
+ mask |= 1LL << 39;
+ else
+ mask |= (pvt->inject.bank & 0x15LL) << 30;
+
+ /* Sets pvt->inject.page mask */
+ if (pvt->inject.page < 0)
+ mask |= 1LL << 38;
+ else
+ mask |= (pvt->inject.page & 0xffff) << 14;
+
+ /* Sets pvt->inject.column mask */
+ if (pvt->inject.col < 0)
+ mask |= 1LL << 37;
+ else
+ mask |= (pvt->inject.col & 0x3fff);
+
+ /*
+ * bit 0: REPEAT_EN
+ * bits 1-2: MASK_HALF_CACHELINE
+ * bit 3: INJECT_ECC
+ * bit 4: INJECT_ADDR_PARITY
+ */
+
+ injectmask = (pvt->inject.type & 1) |
+ (pvt->inject.section & 0x3) << 1 |
+ (pvt->inject.type & 0x6) << (3 - 1);
+
+ /* Unlock writes to registers - this register is write only */
+ pci_write_config_dword(pvt->pci_noncore,
+ MC_CFG_CONTROL, 0x2);
+
+ write_and_test(pvt->pci_ch[pvt->inject.channel][0],
+ MC_CHANNEL_ADDR_MATCH, mask);
+ write_and_test(pvt->pci_ch[pvt->inject.channel][0],
+ MC_CHANNEL_ADDR_MATCH + 4, mask >> 32L);
+
+ write_and_test(pvt->pci_ch[pvt->inject.channel][0],
+ MC_CHANNEL_ERROR_MASK, pvt->inject.eccmask);
+
+ write_and_test(pvt->pci_ch[pvt->inject.channel][0],
+ MC_CHANNEL_ERROR_INJECT, injectmask);
+
+ /*
+ * This is something undocumented, based on my tests
+ * Without writing 8 to this register, errors aren't injected. Not sure
+ * why.
+ */
+ pci_write_config_dword(pvt->pci_noncore,
+ MC_CFG_CONTROL, 8);
+
+ debugf0("Error inject addr match 0x%016llx, ecc 0x%08x,"
+ " inject 0x%08x\n",
+ mask, pvt->inject.eccmask, injectmask);
+
+
+ return count;
+}
+
+static ssize_t i7core_inject_enable_show(struct mem_ctl_info *mci,
+ char *data)
+{
+ struct i7core_pvt *pvt = mci->pvt_info;
+ u32 injectmask;
+
+ if (!pvt->pci_ch[pvt->inject.channel][0])
+ return 0;
+
+ pci_read_config_dword(pvt->pci_ch[pvt->inject.channel][0],
+ MC_CHANNEL_ERROR_INJECT, &injectmask);
+
+ debugf0("Inject error read: 0x%018x\n", injectmask);
+
+ if (injectmask & 0x0c)
+ pvt->inject.enable = 1;
+
+ return sprintf(data, "%d\n", pvt->inject.enable);
+}
+
+#define DECLARE_COUNTER(param) \
+static ssize_t i7core_show_counter_##param( \
+ struct mem_ctl_info *mci, \
+ char *data) \
+{ \
+ struct i7core_pvt *pvt = mci->pvt_info; \
+ \
+ debugf1("%s() \n", __func__); \
+ if (!pvt->ce_count_available || (pvt->is_registered)) \
+ return sprintf(data, "data unavailable\n"); \
+ return sprintf(data, "%lu\n", \
+ pvt->udimm_ce_count[param]); \
+}
+
+#define ATTR_COUNTER(param) \
+ { \
+ .attr = { \
+ .name = __stringify(udimm##param), \
+ .mode = (S_IRUGO | S_IWUSR) \
+ }, \
+ .show = i7core_show_counter_##param \
+ }
+
+DECLARE_COUNTER(0);
+DECLARE_COUNTER(1);
+DECLARE_COUNTER(2);
+
+/*
+ * Sysfs struct
+ */
+
+
+static struct mcidev_sysfs_attribute i7core_addrmatch_attrs[] = {
+ ATTR_ADDR_MATCH(channel),
+ ATTR_ADDR_MATCH(dimm),
+ ATTR_ADDR_MATCH(rank),
+ ATTR_ADDR_MATCH(bank),
+ ATTR_ADDR_MATCH(page),
+ ATTR_ADDR_MATCH(col),
+ { .attr = { .name = NULL } }
+};
+
+static struct mcidev_sysfs_group i7core_inject_addrmatch = {
+ .name = "inject_addrmatch",
+ .mcidev_attr = i7core_addrmatch_attrs,
+};
+
+static struct mcidev_sysfs_attribute i7core_udimm_counters_attrs[] = {
+ ATTR_COUNTER(0),
+ ATTR_COUNTER(1),
+ ATTR_COUNTER(2),
+};
+
+static struct mcidev_sysfs_group i7core_udimm_counters = {
+ .name = "all_channel_counts",
+ .mcidev_attr = i7core_udimm_counters_attrs,
+};
+
+static struct mcidev_sysfs_attribute i7core_sysfs_attrs[] = {
+ {
+ .attr = {
+ .name = "inject_section",
+ .mode = (S_IRUGO | S_IWUSR)
+ },
+ .show = i7core_inject_section_show,
+ .store = i7core_inject_section_store,
+ }, {
+ .attr = {
+ .name = "inject_type",
+ .mode = (S_IRUGO | S_IWUSR)
+ },
+ .show = i7core_inject_type_show,
+ .store = i7core_inject_type_store,
+ }, {
+ .attr = {
+ .name = "inject_eccmask",
+ .mode = (S_IRUGO | S_IWUSR)
+ },
+ .show = i7core_inject_eccmask_show,
+ .store = i7core_inject_eccmask_store,
+ }, {
+ .grp = &i7core_inject_addrmatch,
+ }, {
+ .attr = {
+ .name = "inject_enable",
+ .mode = (S_IRUGO | S_IWUSR)
+ },
+ .show = i7core_inject_enable_show,
+ .store = i7core_inject_enable_store,
+ },
+ { .attr = { .name = NULL } }, /* Reserved for udimm counters */
+ { .attr = { .name = NULL } }
+};
+
+/****************************************************************************
+ Device initialization routines: put/get, init/exit
+ ****************************************************************************/
+
+/*
+ * i7core_put_devices 'put' all the devices that we have
+ * reserved via 'get'
+ */
+static void i7core_put_devices(struct i7core_dev *i7core_dev)
+{
+ int i;
+
+ debugf0(__FILE__ ": %s()\n", __func__);
+ for (i = 0; i < i7core_dev->n_devs; i++) {
+ struct pci_dev *pdev = i7core_dev->pdev[i];
+ if (!pdev)
+ continue;
+ debugf0("Removing dev %02x:%02x.%d\n",
+ pdev->bus->number,
+ PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+ pci_dev_put(pdev);
+ }
+ kfree(i7core_dev->pdev);
+ list_del(&i7core_dev->list);
+ kfree(i7core_dev);
+}
+
+static void i7core_put_all_devices(void)
+{
+ struct i7core_dev *i7core_dev, *tmp;
+
+ list_for_each_entry_safe(i7core_dev, tmp, &i7core_edac_list, list)
+ i7core_put_devices(i7core_dev);
+}
+
+static void __init i7core_xeon_pci_fixup(struct pci_id_table *table)
+{
+ struct pci_dev *pdev = NULL;
+ int i;
+ /*
+ * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core pci buses
+ * aren't announced by acpi. So, we need to use a legacy scan probing
+ * to detect them
+ */
+ while (table && table->descr) {
+ pdev = pci_get_device(PCI_VENDOR_ID_INTEL, table->descr[0].dev_id, NULL);
+ if (unlikely(!pdev)) {
+ for (i = 0; i < MAX_SOCKET_BUSES; i++)
+ pcibios_scan_specific_bus(255-i);
+ }
+ table++;
+ }
+}
+
+/*
+ * i7core_get_devices Find and perform 'get' operation on the MCH's
+ * device/functions we want to reference for this driver
+ *
+ * Need to 'get' device 16 func 1 and func 2
+ */
+int i7core_get_onedevice(struct pci_dev **prev, int devno,
+ struct pci_id_descr *dev_descr, unsigned n_devs)
+{
+ struct i7core_dev *i7core_dev;
+
+ struct pci_dev *pdev = NULL;
+ u8 bus = 0;
+ u8 socket = 0;
+
+ pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ dev_descr->dev_id, *prev);
+
+ /*
+ * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core regs
+ * is at addr 8086:2c40, instead of 8086:2c41. So, we need
+ * to probe for the alternate address in case of failure
+ */
+ if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_I7_NONCORE && !pdev)
+ pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT, *prev);
+
+ if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE && !pdev)
+ pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT,
+ *prev);
+
+ if (!pdev) {
+ if (*prev) {
+ *prev = pdev;
+ return 0;
+ }
+
+ if (dev_descr->optional)
+ return 0;
+
+ if (devno == 0)
+ return -ENODEV;
+
+ i7core_printk(KERN_ERR,
+ "Device not found: dev %02x.%d PCI ID %04x:%04x\n",
+ dev_descr->dev, dev_descr->func,
+ PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+
+ /* End of list, leave */
+ return -ENODEV;
+ }
+ bus = pdev->bus->number;
+
+ if (bus == 0x3f)
+ socket = 0;
+ else
+ socket = 255 - bus;
+
+ i7core_dev = get_i7core_dev(socket);
+ if (!i7core_dev) {
+ i7core_dev = kzalloc(sizeof(*i7core_dev), GFP_KERNEL);
+ if (!i7core_dev)
+ return -ENOMEM;
+ i7core_dev->pdev = kzalloc(sizeof(*i7core_dev->pdev) * n_devs,
+ GFP_KERNEL);
+ if (!i7core_dev->pdev) {
+ kfree(i7core_dev);
+ return -ENOMEM;
+ }
+ i7core_dev->socket = socket;
+ i7core_dev->n_devs = n_devs;
+ list_add_tail(&i7core_dev->list, &i7core_edac_list);
+ }
+
+ if (i7core_dev->pdev[devno]) {
+ i7core_printk(KERN_ERR,
+ "Duplicated device for "
+ "dev %02x:%02x.%d PCI ID %04x:%04x\n",
+ bus, dev_descr->dev, dev_descr->func,
+ PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+ pci_dev_put(pdev);
+ return -ENODEV;
+ }
+
+ i7core_dev->pdev[devno] = pdev;
+
+ /* Sanity check */
+ if (unlikely(PCI_SLOT(pdev->devfn) != dev_descr->dev ||
+ PCI_FUNC(pdev->devfn) != dev_descr->func)) {
+ i7core_printk(KERN_ERR,
+ "Device PCI ID %04x:%04x "
+ "has dev %02x:%02x.%d instead of dev %02x:%02x.%d\n",
+ PCI_VENDOR_ID_INTEL, dev_descr->dev_id,
+ bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+ bus, dev_descr->dev, dev_descr->func);
+ return -ENODEV;
+ }
+
+ /* Be sure that the device is enabled */
+ if (unlikely(pci_enable_device(pdev) < 0)) {
+ i7core_printk(KERN_ERR,
+ "Couldn't enable "
+ "dev %02x:%02x.%d PCI ID %04x:%04x\n",
+ bus, dev_descr->dev, dev_descr->func,
+ PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+ return -ENODEV;
+ }
+
+ debugf0("Detected socket %d dev %02x:%02x.%d PCI ID %04x:%04x\n",
+ socket, bus, dev_descr->dev,
+ dev_descr->func,
+ PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+
+ *prev = pdev;
+
+ return 0;
+}
+
+static int i7core_get_devices(struct pci_id_table *table)
+{
+ int i, rc;
+ struct pci_dev *pdev = NULL;
+ struct pci_id_descr *dev_descr;
+
+ while (table && table->descr) {
+ dev_descr = table->descr;
+ for (i = 0; i < table->n_devs; i++) {
+ pdev = NULL;
+ do {
+ rc = i7core_get_onedevice(&pdev, i, &dev_descr[i],
+ table->n_devs);
+ if (rc < 0) {
+ if (i == 0) {
+ i = table->n_devs;
+ break;
+ }
+ i7core_put_all_devices();
+ return -ENODEV;
+ }
+ } while (pdev);
+ }
+ table++;
+ }
+
+ return 0;
+ return 0;
+}
+
+static int mci_bind_devs(struct mem_ctl_info *mci,
+ struct i7core_dev *i7core_dev)
+{
+ struct i7core_pvt *pvt = mci->pvt_info;
+ struct pci_dev *pdev;
+ int i, func, slot;
+
+ /* Associates i7core_dev and mci for future usage */
+ pvt->i7core_dev = i7core_dev;
+ i7core_dev->mci = mci;
+
+ pvt->is_registered = 0;
+ for (i = 0; i < i7core_dev->n_devs; i++) {
+ pdev = i7core_dev->pdev[i];
+ if (!pdev)
+ continue;
+
+ func = PCI_FUNC(pdev->devfn);
+ slot = PCI_SLOT(pdev->devfn);
+ if (slot == 3) {
+ if (unlikely(func > MAX_MCR_FUNC))
+ goto error;
+ pvt->pci_mcr[func] = pdev;
+ } else if (likely(slot >= 4 && slot < 4 + NUM_CHANS)) {
+ if (unlikely(func > MAX_CHAN_FUNC))
+ goto error;
+ pvt->pci_ch[slot - 4][func] = pdev;
+ } else if (!slot && !func)
+ pvt->pci_noncore = pdev;
+ else
+ goto error;
+
+ debugf0("Associated fn %d.%d, dev = %p, socket %d\n",
+ PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+ pdev, i7core_dev->socket);
+
+ if (PCI_SLOT(pdev->devfn) == 3 &&
+ PCI_FUNC(pdev->devfn) == 2)
+ pvt->is_registered = 1;
+ }
+
+ /*
+ * Add extra nodes to count errors on udimm
+ * For registered memory, this is not needed, since the counters
+ * are already displayed at the standard locations
+ */
+ if (!pvt->is_registered)
+ i7core_sysfs_attrs[ARRAY_SIZE(i7core_sysfs_attrs)-2].grp =
+ &i7core_udimm_counters;
+
+ return 0;
+
+error:
+ i7core_printk(KERN_ERR, "Device %d, function %d "
+ "is out of the expected range\n",
+ slot, func);
+ return -EINVAL;
+}
+
+/****************************************************************************
+ Error check routines
+ ****************************************************************************/
+static void i7core_rdimm_update_csrow(struct mem_ctl_info *mci,
+ int chan, int dimm, int add)
+{
+ char *msg;
+ struct i7core_pvt *pvt = mci->pvt_info;
+ int row = pvt->csrow_map[chan][dimm], i;
+
+ for (i = 0; i < add; i++) {
+ msg = kasprintf(GFP_KERNEL, "Corrected error "
+ "(Socket=%d channel=%d dimm=%d)",
+ pvt->i7core_dev->socket, chan, dimm);
+
+ edac_mc_handle_fbd_ce(mci, row, 0, msg);
+ kfree (msg);
+ }
+}
+
+static void i7core_rdimm_update_ce_count(struct mem_ctl_info *mci,
+ int chan, int new0, int new1, int new2)
+{
+ struct i7core_pvt *pvt = mci->pvt_info;
+ int add0 = 0, add1 = 0, add2 = 0;
+ /* Updates CE counters if it is not the first time here */
+ if (pvt->ce_count_available) {
+ /* Updates CE counters */
+
+ add2 = new2 - pvt->rdimm_last_ce_count[chan][2];
+ add1 = new1 - pvt->rdimm_last_ce_count[chan][1];
+ add0 = new0 - pvt->rdimm_last_ce_count[chan][0];
+
+ if (add2 < 0)
+ add2 += 0x7fff;
+ pvt->rdimm_ce_count[chan][2] += add2;
+
+ if (add1 < 0)
+ add1 += 0x7fff;
+ pvt->rdimm_ce_count[chan][1] += add1;
+
+ if (add0 < 0)
+ add0 += 0x7fff;
+ pvt->rdimm_ce_count[chan][0] += add0;
+ } else
+ pvt->ce_count_available = 1;
+
+ /* Store the new values */
+ pvt->rdimm_last_ce_count[chan][2] = new2;
+ pvt->rdimm_last_ce_count[chan][1] = new1;
+ pvt->rdimm_last_ce_count[chan][0] = new0;
+
+ /*updated the edac core */
+ if (add0 != 0)
+ i7core_rdimm_update_csrow(mci, chan, 0, add0);
+ if (add1 != 0)
+ i7core_rdimm_update_csrow(mci, chan, 1, add1);
+ if (add2 != 0)
+ i7core_rdimm_update_csrow(mci, chan, 2, add2);
+
+}
+
+static void i7core_rdimm_check_mc_ecc_err(struct mem_ctl_info *mci)
+{
+ struct i7core_pvt *pvt = mci->pvt_info;
+ u32 rcv[3][2];
+ int i, new0, new1, new2;
+
+ /*Read DEV 3: FUN 2: MC_COR_ECC_CNT regs directly*/
+ pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_0,
+ &rcv[0][0]);
+ pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_1,
+ &rcv[0][1]);
+ pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_2,
+ &rcv[1][0]);
+ pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_3,
+ &rcv[1][1]);
+ pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_4,
+ &rcv[2][0]);
+ pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_5,
+ &rcv[2][1]);
+ for (i = 0 ; i < 3; i++) {
+ debugf3("MC_COR_ECC_CNT%d = 0x%x; MC_COR_ECC_CNT%d = 0x%x\n",
+ (i * 2), rcv[i][0], (i * 2) + 1, rcv[i][1]);
+ /*if the channel has 3 dimms*/
+ if (pvt->channel[i].dimms > 2) {
+ new0 = DIMM_BOT_COR_ERR(rcv[i][0]);
+ new1 = DIMM_TOP_COR_ERR(rcv[i][0]);
+ new2 = DIMM_BOT_COR_ERR(rcv[i][1]);
+ } else {
+ new0 = DIMM_TOP_COR_ERR(rcv[i][0]) +
+ DIMM_BOT_COR_ERR(rcv[i][0]);
+ new1 = DIMM_TOP_COR_ERR(rcv[i][1]) +
+ DIMM_BOT_COR_ERR(rcv[i][1]);
+ new2 = 0;
+ }
+
+ i7core_rdimm_update_ce_count(mci, i, new0, new1, new2);
+ }
+}
+
+/* This function is based on the device 3 function 4 registers as described on:
+ * Intel Xeon Processor 5500 Series Datasheet Volume 2
+ * http://www.intel.com/Assets/PDF/datasheet/321322.pdf
+ * also available at:
+ * http://www.arrownac.com/manufacturers/intel/s/nehalem/5500-datasheet-v2.pdf
+ */
+static void i7core_udimm_check_mc_ecc_err(struct mem_ctl_info *mci)
+{
+ struct i7core_pvt *pvt = mci->pvt_info;
+ u32 rcv1, rcv0;
+ int new0, new1, new2;
+
+ if (!pvt->pci_mcr[4]) {
+ debugf0("%s MCR registers not found\n", __func__);
+ return;
+ }
+
+ /* Corrected test errors */
+ pci_read_config_dword(pvt->pci_mcr[4], MC_TEST_ERR_RCV1, &rcv1);
+ pci_read_config_dword(pvt->pci_mcr[4], MC_TEST_ERR_RCV0, &rcv0);
+
+ /* Store the new values */
+ new2 = DIMM2_COR_ERR(rcv1);
+ new1 = DIMM1_COR_ERR(rcv0);
+ new0 = DIMM0_COR_ERR(rcv0);
+
+ /* Updates CE counters if it is not the first time here */
+ if (pvt->ce_count_available) {
+ /* Updates CE counters */
+ int add0, add1, add2;
+
+ add2 = new2 - pvt->udimm_last_ce_count[2];
+ add1 = new1 - pvt->udimm_last_ce_count[1];
+ add0 = new0 - pvt->udimm_last_ce_count[0];
+
+ if (add2 < 0)
+ add2 += 0x7fff;
+ pvt->udimm_ce_count[2] += add2;
+
+ if (add1 < 0)
+ add1 += 0x7fff;
+ pvt->udimm_ce_count[1] += add1;
+
+ if (add0 < 0)
+ add0 += 0x7fff;
+ pvt->udimm_ce_count[0] += add0;
+
+ if (add0 | add1 | add2)
+ i7core_printk(KERN_ERR, "New Corrected error(s): "
+ "dimm0: +%d, dimm1: +%d, dimm2 +%d\n",
+ add0, add1, add2);
+ } else
+ pvt->ce_count_available = 1;
+
+ /* Store the new values */
+ pvt->udimm_last_ce_count[2] = new2;
+ pvt->udimm_last_ce_count[1] = new1;
+ pvt->udimm_last_ce_count[0] = new0;
+}
+
+/*
+ * According with tables E-11 and E-12 of chapter E.3.3 of Intel 64 and IA-32
+ * Architectures Software Developer’s Manual Volume 3B.
+ * Nehalem are defined as family 0x06, model 0x1a
+ *
+ * The MCA registers used here are the following ones:
+ * struct mce field MCA Register
+ * m->status MSR_IA32_MC8_STATUS
+ * m->addr MSR_IA32_MC8_ADDR
+ * m->misc MSR_IA32_MC8_MISC
+ * In the case of Nehalem, the error information is masked at .status and .misc
+ * fields
+ */
+static void i7core_mce_output_error(struct mem_ctl_info *mci,
+ struct mce *m)
+{
+ struct i7core_pvt *pvt = mci->pvt_info;
+ char *type, *optype, *err, *msg;
+ unsigned long error = m->status & 0x1ff0000l;
+ u32 optypenum = (m->status >> 4) & 0x07;
+ u32 core_err_cnt = (m->status >> 38) && 0x7fff;
+ u32 dimm = (m->misc >> 16) & 0x3;
+ u32 channel = (m->misc >> 18) & 0x3;
+ u32 syndrome = m->misc >> 32;
+ u32 errnum = find_first_bit(&error, 32);
+ int csrow;
+
+ if (m->mcgstatus & 1)
+ type = "FATAL";
+ else
+ type = "NON_FATAL";
+
+ switch (optypenum) {
+ case 0:
+ optype = "generic undef request";
+ break;
+ case 1:
+ optype = "read error";
+ break;
+ case 2:
+ optype = "write error";
+ break;
+ case 3:
+ optype = "addr/cmd error";
+ break;
+ case 4:
+ optype = "scrubbing error";
+ break;
+ default:
+ optype = "reserved";
+ break;
+ }
+
+ switch (errnum) {
+ case 16:
+ err = "read ECC error";
+ break;
+ case 17:
+ err = "RAS ECC error";
+ break;
+ case 18:
+ err = "write parity error";
+ break;
+ case 19:
+ err = "redundacy loss";
+ break;
+ case 20:
+ err = "reserved";
+ break;
+ case 21:
+ err = "memory range error";
+ break;
+ case 22:
+ err = "RTID out of range";
+ break;
+ case 23:
+ err = "address parity error";
+ break;
+ case 24:
+ err = "byte enable parity error";
+ break;
+ default:
+ err = "unknown";
+ }
+
+ /* FIXME: should convert addr into bank and rank information */
+ msg = kasprintf(GFP_ATOMIC,
+ "%s (addr = 0x%08llx, cpu=%d, Dimm=%d, Channel=%d, "
+ "syndrome=0x%08x, count=%d, Err=%08llx:%08llx (%s: %s))\n",
+ type, (long long) m->addr, m->cpu, dimm, channel,
+ syndrome, core_err_cnt, (long long)m->status,
+ (long long)m->misc, optype, err);
+
+ debugf0("%s", msg);
+
+ csrow = pvt->csrow_map[channel][dimm];
+
+ /* Call the helper to output message */
+ if (m->mcgstatus & 1)
+ edac_mc_handle_fbd_ue(mci, csrow, 0,
+ 0 /* FIXME: should be channel here */, msg);
+ else if (!pvt->is_registered)
+ edac_mc_handle_fbd_ce(mci, csrow,
+ 0 /* FIXME: should be channel here */, msg);
+
+ kfree(msg);
+}
+
+/*
+ * i7core_check_error Retrieve and process errors reported by the
+ * hardware. Called by the Core module.
+ */
+static void i7core_check_error(struct mem_ctl_info *mci)
+{
+ struct i7core_pvt *pvt = mci->pvt_info;
+ int i;
+ unsigned count = 0;
+ struct mce *m;
+
+ /*
+ * MCE first step: Copy all mce errors into a temporary buffer
+ * We use a double buffering here, to reduce the risk of
+ * loosing an error.
+ */
+ smp_rmb();
+ count = (pvt->mce_out + MCE_LOG_LEN - pvt->mce_in)
+ % MCE_LOG_LEN;
+ if (!count)
+ goto check_ce_error;
+
+ m = pvt->mce_outentry;
+ if (pvt->mce_in + count > MCE_LOG_LEN) {
+ unsigned l = MCE_LOG_LEN - pvt->mce_in;
+
+ memcpy(m, &pvt->mce_entry[pvt->mce_in], sizeof(*m) * l);
+ smp_wmb();
+ pvt->mce_in = 0;
+ count -= l;
+ m += l;
+ }
+ memcpy(m, &pvt->mce_entry[pvt->mce_in], sizeof(*m) * count);
+ smp_wmb();
+ pvt->mce_in += count;
+
+ smp_rmb();
+ if (pvt->mce_overrun) {
+ i7core_printk(KERN_ERR, "Lost %d memory errors\n",
+ pvt->mce_overrun);
+ smp_wmb();
+ pvt->mce_overrun = 0;
+ }
+
+ /*
+ * MCE second step: parse errors and display
+ */
+ for (i = 0; i < count; i++)
+ i7core_mce_output_error(mci, &pvt->mce_outentry[i]);
+
+ /*
+ * Now, let's increment CE error counts
+ */
+check_ce_error:
+ if (!pvt->is_registered)
+ i7core_udimm_check_mc_ecc_err(mci);
+ else
+ i7core_rdimm_check_mc_ecc_err(mci);
+}
+
+/*
+ * i7core_mce_check_error Replicates mcelog routine to get errors
+ * This routine simply queues mcelog errors, and
+ * return. The error itself should be handled later
+ * by i7core_check_error.
+ * WARNING: As this routine should be called at NMI time, extra care should
+ * be taken to avoid deadlocks, and to be as fast as possible.
+ */
+static int i7core_mce_check_error(void *priv, struct mce *mce)
+{
+ struct mem_ctl_info *mci = priv;
+ struct i7core_pvt *pvt = mci->pvt_info;
+
+ /*
+ * Just let mcelog handle it if the error is
+ * outside the memory controller
+ */
+ if (((mce->status & 0xffff) >> 7) != 1)
+ return 0;
+
+ /* Bank 8 registers are the only ones that we know how to handle */
+ if (mce->bank != 8)
+ return 0;
+
+#ifdef CONFIG_SMP
+ /* Only handle if it is the right mc controller */
+ if (cpu_data(mce->cpu).phys_proc_id != pvt->i7core_dev->socket)
+ return 0;
+#endif
+
+ smp_rmb();
+ if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) {
+ smp_wmb();
+ pvt->mce_overrun++;
+ return 0;
+ }
+
+ /* Copy memory error at the ringbuffer */
+ memcpy(&pvt->mce_entry[pvt->mce_out], mce, sizeof(*mce));
+ smp_wmb();
+ pvt->mce_out = (pvt->mce_out + 1) % MCE_LOG_LEN;
+
+ /* Handle fatal errors immediately */
+ if (mce->mcgstatus & 1)
+ i7core_check_error(mci);
+
+ /* Advice mcelog that the error were handled */
+ return 1;
+}
+
+static int i7core_register_mci(struct i7core_dev *i7core_dev,
+ int num_channels, int num_csrows)
+{
+ struct mem_ctl_info *mci;
+ struct i7core_pvt *pvt;
+ int csrow = 0;
+ int rc;
+
+ /* allocate a new MC control structure */
+ mci = edac_mc_alloc(sizeof(*pvt), num_csrows, num_channels,
+ i7core_dev->socket);
+ if (unlikely(!mci))
+ return -ENOMEM;
+
+ debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
+
+ /* record ptr to the generic device */
+ mci->dev = &i7core_dev->pdev[0]->dev;
+
+ pvt = mci->pvt_info;
+ memset(pvt, 0, sizeof(*pvt));
+
+ /*
+ * FIXME: how to handle RDDR3 at MCI level? It is possible to have
+ * Mixed RDDR3/UDDR3 with Nehalem, provided that they are on different
+ * memory channels
+ */
+ mci->mtype_cap = MEM_FLAG_DDR3;
+ mci->edac_ctl_cap = EDAC_FLAG_NONE;
+ mci->edac_cap = EDAC_FLAG_NONE;
+ mci->mod_name = "i7core_edac.c";
+ mci->mod_ver = I7CORE_REVISION;
+ mci->ctl_name = kasprintf(GFP_KERNEL, "i7 core #%d",
+ i7core_dev->socket);
+ mci->dev_name = pci_name(i7core_dev->pdev[0]);
+ mci->ctl_page_to_phys = NULL;
+ mci->mc_driver_sysfs_attributes = i7core_sysfs_attrs;
+ /* Set the function pointer to an actual operation function */
+ mci->edac_check = i7core_check_error;
+
+ /* Store pci devices at mci for faster access */
+ rc = mci_bind_devs(mci, i7core_dev);
+ if (unlikely(rc < 0))
+ goto fail;
+
+ /* Get dimm basic config */
+ get_dimm_config(mci, &csrow);
+
+ /* add this new MC control structure to EDAC's list of MCs */
+ if (unlikely(edac_mc_add_mc(mci))) {
+ debugf0("MC: " __FILE__
+ ": %s(): failed edac_mc_add_mc()\n", __func__);
+ /* FIXME: perhaps some code should go here that disables error
+ * reporting if we just enabled it
+ */
+
+ rc = -EINVAL;
+ goto fail;
+ }
+
+ /* allocating generic PCI control info */
+ i7core_pci = edac_pci_create_generic_ctl(&i7core_dev->pdev[0]->dev,
+ EDAC_MOD_STR);
+ if (unlikely(!i7core_pci)) {
+ printk(KERN_WARNING
+ "%s(): Unable to create PCI control\n",
+ __func__);
+ printk(KERN_WARNING
+ "%s(): PCI error report via EDAC not setup\n",
+ __func__);
+ }
+
+ /* Default error mask is any memory */
+ pvt->inject.channel = 0;
+ pvt->inject.dimm = -1;
+ pvt->inject.rank = -1;
+ pvt->inject.bank = -1;
+ pvt->inject.page = -1;
+ pvt->inject.col = -1;
+
+ /* Registers on edac_mce in order to receive memory errors */
+ pvt->edac_mce.priv = mci;
+ pvt->edac_mce.check_error = i7core_mce_check_error;
+
+ rc = edac_mce_register(&pvt->edac_mce);
+ if (unlikely(rc < 0)) {
+ debugf0("MC: " __FILE__
+ ": %s(): failed edac_mce_register()\n", __func__);
+ }
+
+fail:
+ if (rc < 0)
+ edac_mc_free(mci);
+ return rc;
+}
+
+/*
+ * i7core_probe Probe for ONE instance of device to see if it is
+ * present.
+ * return:
+ * 0 for FOUND a device
+ * < 0 for error code
+ */
+static int __devinit i7core_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ int dev_idx = id->driver_data;
+ int rc;
+ struct i7core_dev *i7core_dev;
+
+ /*
+ * All memory controllers are allocated at the first pass.
+ */
+ if (unlikely(dev_idx >= 1))
+ return -EINVAL;
+
+ /* get the pci devices we want to reserve for our use */
+ mutex_lock(&i7core_edac_lock);
+
+ rc = i7core_get_devices(pci_dev_table);
+ if (unlikely(rc < 0))
+ goto fail0;
+
+ list_for_each_entry(i7core_dev, &i7core_edac_list, list) {
+ int channels;
+ int csrows;
+
+ /* Check the number of active and not disabled channels */
+ rc = i7core_get_active_channels(i7core_dev->socket,
+ &channels, &csrows);
+ if (unlikely(rc < 0))
+ goto fail1;
+
+ rc = i7core_register_mci(i7core_dev, channels, csrows);
+ if (unlikely(rc < 0))
+ goto fail1;
+ }
+
+ i7core_printk(KERN_INFO, "Driver loaded.\n");
+
+ mutex_unlock(&i7core_edac_lock);
+ return 0;
+
+fail1:
+ i7core_put_all_devices();
+fail0:
+ mutex_unlock(&i7core_edac_lock);
+ return rc;
+}
+
+/*
+ * i7core_remove destructor for one instance of device
+ *
+ */
+static void __devexit i7core_remove(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+ struct i7core_dev *i7core_dev, *tmp;
+
+ debugf0(__FILE__ ": %s()\n", __func__);
+
+ if (i7core_pci)
+ edac_pci_release_generic_ctl(i7core_pci);
+
+ /*
+ * we have a trouble here: pdev value for removal will be wrong, since
+ * it will point to the X58 register used to detect that the machine
+ * is a Nehalem or upper design. However, due to the way several PCI
+ * devices are grouped together to provide MC functionality, we need
+ * to use a different method for releasing the devices
+ */
+
+ mutex_lock(&i7core_edac_lock);
+ list_for_each_entry_safe(i7core_dev, tmp, &i7core_edac_list, list) {
+ mci = edac_mc_del_mc(&i7core_dev->pdev[0]->dev);
+ if (mci) {
+ struct i7core_pvt *pvt = mci->pvt_info;
+
+ i7core_dev = pvt->i7core_dev;
+ edac_mce_unregister(&pvt->edac_mce);
+ kfree(mci->ctl_name);
+ edac_mc_free(mci);
+ i7core_put_devices(i7core_dev);
+ } else {
+ i7core_printk(KERN_ERR,
+ "Couldn't find mci for socket %d\n",
+ i7core_dev->socket);
+ }
+ }
+ mutex_unlock(&i7core_edac_lock);
+}
+
+MODULE_DEVICE_TABLE(pci, i7core_pci_tbl);
+
+/*
+ * i7core_driver pci_driver structure for this module
+ *
+ */
+static struct pci_driver i7core_driver = {
+ .name = "i7core_edac",
+ .probe = i7core_probe,
+ .remove = __devexit_p(i7core_remove),
+ .id_table = i7core_pci_tbl,
+};
+
+/*
+ * i7core_init Module entry function
+ * Try to initialize this module for its devices
+ */
+static int __init i7core_init(void)
+{
+ int pci_rc;
+
+ debugf2("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* Ensure that the OPSTATE is set correctly for POLL or NMI */
+ opstate_init();
+
+ i7core_xeon_pci_fixup(pci_dev_table);
+
+ pci_rc = pci_register_driver(&i7core_driver);
+
+ if (pci_rc >= 0)
+ return 0;
+
+ i7core_printk(KERN_ERR, "Failed to register device with error %d.\n",
+ pci_rc);
+
+ return pci_rc;
+}
+
+/*
+ * i7core_exit() Module exit function
+ * Unregister the driver
+ */
+static void __exit i7core_exit(void)
+{
+ debugf2("MC: " __FILE__ ": %s()\n", __func__);
+ pci_unregister_driver(&i7core_driver);
+}
+
+module_init(i7core_init);
+module_exit(i7core_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
+MODULE_DESCRIPTION("MC Driver for Intel i7 Core memory controllers - "
+ I7CORE_REVISION);
+
+module_param(edac_op_state, int, 0444);
+MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index 6c1886b..52ca09b 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -229,7 +229,7 @@
pdata->edac_idx = edac_pci_idx++;
- res = of_address_to_resource(op->node, 0, &r);
+ res = of_address_to_resource(op->dev.of_node, 0, &r);
if (res) {
printk(KERN_ERR "%s: Unable to get resource for "
"PCI err regs\n", __func__);
@@ -274,7 +274,7 @@
}
if (edac_op_state == EDAC_OPSTATE_INT) {
- pdata->irq = irq_of_parse_and_map(op->node, 0);
+ pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
res = devm_request_irq(&op->dev, pdata->irq,
mpc85xx_pci_isr, IRQF_DISABLED,
"[EDAC] PCI err", pci);
@@ -529,7 +529,7 @@
edac_dev->ctl_name = pdata->name;
edac_dev->dev_name = pdata->name;
- res = of_address_to_resource(op->node, 0, &r);
+ res = of_address_to_resource(op->dev.of_node, 0, &r);
if (res) {
printk(KERN_ERR "%s: Unable to get resource for "
"L2 err regs\n", __func__);
@@ -576,7 +576,7 @@
}
if (edac_op_state == EDAC_OPSTATE_INT) {
- pdata->irq = irq_of_parse_and_map(op->node, 0);
+ pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
res = devm_request_irq(&op->dev, pdata->irq,
mpc85xx_l2_isr, IRQF_DISABLED,
"[EDAC] L2 err", edac_dev);
@@ -978,7 +978,7 @@
mci->ctl_name = pdata->name;
mci->dev_name = pdata->name;
- res = of_address_to_resource(op->node, 0, &r);
+ res = of_address_to_resource(op->dev.of_node, 0, &r);
if (res) {
printk(KERN_ERR "%s: Unable to get resource for MC err regs\n",
__func__);
@@ -1052,7 +1052,7 @@
out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_SBE, 0x10000);
/* register interrupts */
- pdata->irq = irq_of_parse_and_map(op->node, 0);
+ pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
res = devm_request_irq(&op->dev, pdata->irq,
mpc85xx_mc_isr,
IRQF_DISABLED | IRQF_SHARED,
diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c
index 9d6f678..e78839e 100644
--- a/drivers/edac/ppc4xx_edac.c
+++ b/drivers/edac/ppc4xx_edac.c
@@ -1022,7 +1022,7 @@
int status = 0;
const u32 memcheck = (mcopt1 & SDRAM_MCOPT1_MCHK_MASK);
struct ppc4xx_edac_pdata *pdata = NULL;
- const struct device_node *np = op->node;
+ const struct device_node *np = op->dev.of_node;
if (match == NULL)
return -EINVAL;
@@ -1113,7 +1113,7 @@
int status = 0;
int ded_irq, sec_irq;
struct ppc4xx_edac_pdata *pdata = mci->pvt_info;
- struct device_node *np = op->node;
+ struct device_node *np = op->dev.of_node;
ded_irq = irq_of_parse_and_map(np, INTMAP_ECCDED_INDEX);
sec_irq = irq_of_parse_and_map(np, INTMAP_ECCSEC_INDEX);
@@ -1243,7 +1243,7 @@
int status = 0;
u32 mcopt1, memcheck;
dcr_host_t dcr_host;
- const struct device_node *np = op->node;
+ const struct device_node *np = op->dev.of_node;
struct mem_ctl_info *mci = NULL;
static int ppc4xx_edac_instance;
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c
index 9dcb304..371713f 100644
--- a/drivers/firewire/core-card.c
+++ b/drivers/firewire/core-card.c
@@ -231,7 +231,7 @@
static void fw_card_bm_work(struct work_struct *work)
{
struct fw_card *card = container_of(work, struct fw_card, work.work);
- struct fw_device *root_device;
+ struct fw_device *root_device, *irm_device;
struct fw_node *root_node;
unsigned long flags;
int root_id, new_root_id, irm_id, local_id;
@@ -239,6 +239,7 @@
bool do_reset = false;
bool root_device_is_running;
bool root_device_is_cmc;
+ bool irm_is_1394_1995_only;
spin_lock_irqsave(&card->lock, flags);
@@ -248,12 +249,18 @@
}
generation = card->generation;
+
root_node = card->root_node;
fw_node_get(root_node);
root_device = root_node->data;
root_device_is_running = root_device &&
atomic_read(&root_device->state) == FW_DEVICE_RUNNING;
root_device_is_cmc = root_device && root_device->cmc;
+
+ irm_device = card->irm_node->data;
+ irm_is_1394_1995_only = irm_device && irm_device->config_rom &&
+ (irm_device->config_rom[2] & 0x000000f0) == 0;
+
root_id = root_node->node_id;
irm_id = card->irm_node->node_id;
local_id = card->local_node->node_id;
@@ -276,8 +283,15 @@
if (!card->irm_node->link_on) {
new_root_id = local_id;
- fw_notify("IRM has link off, making local node (%02x) root.\n",
- new_root_id);
+ fw_notify("%s, making local node (%02x) root.\n",
+ "IRM has link off", new_root_id);
+ goto pick_me;
+ }
+
+ if (irm_is_1394_1995_only) {
+ new_root_id = local_id;
+ fw_notify("%s, making local node (%02x) root.\n",
+ "IRM is not 1394a compliant", new_root_id);
goto pick_me;
}
@@ -316,8 +330,8 @@
* root, and thus, IRM.
*/
new_root_id = local_id;
- fw_notify("BM lock failed, making local node (%02x) root.\n",
- new_root_id);
+ fw_notify("%s, making local node (%02x) root.\n",
+ "BM lock failed", new_root_id);
goto pick_me;
}
} else if (card->bm_generation != generation) {
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 724038d..7face91 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1,5 +1,5 @@
#
-# GPIO infrastructure and expanders
+# platform-neutral GPIO infrastructure and expanders
#
config ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 51c3cdd..e53dcff 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -1,4 +1,8 @@
-# gpio support: dedicated expander chips, etc
+# generic gpio support: dedicated expander chips, etc
+#
+# NOTE: platform-specific GPIO drivers don't belong in the
+# drivers/gpio directory; put them with other platform setup
+# code, IRQ controllers, board init, etc.
ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 994d23b..57cea01 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1840,8 +1840,10 @@
ret = copy_from_user(clips, clips_ptr,
num_clips * sizeof(*clips));
- if (ret)
+ if (ret) {
+ ret = -EFAULT;
goto out_err2;
+ }
}
if (fb->funcs->dirty) {
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 7644019..9b2a541 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -860,19 +860,24 @@
}
}
-void drm_kms_helper_poll_init(struct drm_device *dev)
+void drm_kms_helper_poll_disable(struct drm_device *dev)
{
- struct drm_connector *connector;
+ if (!dev->mode_config.poll_enabled)
+ return;
+ delayed_slow_work_cancel(&dev->mode_config.output_poll_slow_work);
+}
+EXPORT_SYMBOL(drm_kms_helper_poll_disable);
+
+void drm_kms_helper_poll_enable(struct drm_device *dev)
+{
bool poll = false;
+ struct drm_connector *connector;
int ret;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
if (connector->polled)
poll = true;
}
- slow_work_register_user(THIS_MODULE);
- delayed_slow_work_init(&dev->mode_config.output_poll_slow_work,
- &output_poll_ops);
if (poll) {
ret = delayed_slow_work_enqueue(&dev->mode_config.output_poll_slow_work, DRM_OUTPUT_POLL_PERIOD);
@@ -880,11 +885,22 @@
DRM_ERROR("delayed enqueue failed %d\n", ret);
}
}
+EXPORT_SYMBOL(drm_kms_helper_poll_enable);
+
+void drm_kms_helper_poll_init(struct drm_device *dev)
+{
+ slow_work_register_user(THIS_MODULE);
+ delayed_slow_work_init(&dev->mode_config.output_poll_slow_work,
+ &output_poll_ops);
+ dev->mode_config.poll_enabled = true;
+
+ drm_kms_helper_poll_enable(dev);
+}
EXPORT_SYMBOL(drm_kms_helper_poll_init);
void drm_kms_helper_poll_fini(struct drm_device *dev)
{
- delayed_slow_work_cancel(&dev->mode_config.output_poll_slow_work);
+ drm_kms_helper_poll_disable(dev);
slow_work_unregister_user(THIS_MODULE);
}
EXPORT_SYMBOL(drm_kms_helper_poll_fini);
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index b3779d2..1f2cc6b 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -146,7 +146,7 @@
cvt = 1;
break;
case 'R':
- if (!cvt)
+ if (cvt)
rb = 1;
break;
case 'm':
@@ -264,7 +264,7 @@
int drm_fb_helper_panic(struct notifier_block *n, unsigned long ununsed,
void *panic_str)
{
- DRM_ERROR("panic occurred, switching back to text console\n");
+ printk(KERN_ERR "panic occurred, switching back to text console\n");
return drm_fb_helper_force_kernel_mode();
return 0;
}
@@ -1024,11 +1024,18 @@
}
create_mode:
- mode = drm_cvt_mode(fb_helper_conn->connector->dev, cmdline_mode->xres,
- cmdline_mode->yres,
- cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
- cmdline_mode->rb, cmdline_mode->interlace,
- cmdline_mode->margins);
+ if (cmdline_mode->cvt)
+ mode = drm_cvt_mode(fb_helper_conn->connector->dev,
+ cmdline_mode->xres, cmdline_mode->yres,
+ cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
+ cmdline_mode->rb, cmdline_mode->interlace,
+ cmdline_mode->margins);
+ else
+ mode = drm_gtf_mode(fb_helper_conn->connector->dev,
+ cmdline_mode->xres, cmdline_mode->yres,
+ cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
+ cmdline_mode->interlace,
+ cmdline_mode->margins);
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
list_add(&mode->head, &fb_helper_conn->connector->modes);
return mode;
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index e50ae3c..f00c5ae 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1322,12 +1322,14 @@
struct drm_device *dev = pci_get_drvdata(pdev);
pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
if (state == VGA_SWITCHEROO_ON) {
- printk(KERN_INFO "i915: switched off\n");
+ printk(KERN_INFO "i915: switched on\n");
/* i915 resume handler doesn't set to D0 */
pci_set_power_state(dev->pdev, PCI_D0);
i915_resume(dev);
+ drm_kms_helper_poll_enable(dev);
} else {
printk(KERN_ERR "i915: switched off\n");
+ drm_kms_helper_poll_disable(dev);
i915_suspend(dev, pmm);
}
}
@@ -1402,13 +1404,13 @@
/* if we have > 1 VGA cards, then disable the radeon VGA resources */
ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode);
if (ret)
- goto destroy_ringbuffer;
+ goto cleanup_ringbuffer;
ret = vga_switcheroo_register_client(dev->pdev,
i915_switcheroo_set_state,
i915_switcheroo_can_switch);
if (ret)
- goto destroy_ringbuffer;
+ goto cleanup_vga_client;
/* IIR "flip pending" bit means done if this bit is set */
if (IS_GEN3(dev) && (I915_READ(ECOSKPD) & ECO_FLIP_DONE))
@@ -1418,7 +1420,7 @@
ret = drm_irq_install(dev);
if (ret)
- goto destroy_ringbuffer;
+ goto cleanup_vga_switcheroo;
/* Always safe in the mode setting case. */
/* FIXME: do pre/post-mode set stuff in core KMS code */
@@ -1430,11 +1432,20 @@
I915_WRITE(INSTPM, (1 << 5) | (1 << 21));
- intel_fbdev_init(dev);
+ ret = intel_fbdev_init(dev);
+ if (ret)
+ goto cleanup_irq;
+
drm_kms_helper_poll_init(dev);
return 0;
-destroy_ringbuffer:
+cleanup_irq:
+ drm_irq_uninstall(dev);
+cleanup_vga_switcheroo:
+ vga_switcheroo_unregister_client(dev->pdev);
+cleanup_vga_client:
+ vga_client_register(dev->pdev, NULL, NULL, NULL);
+cleanup_ringbuffer:
mutex_lock(&dev->struct_mutex);
i915_gem_cleanup_ringbuffer(dev);
mutex_unlock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 21e217d..d147ab2 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -278,6 +278,7 @@
struct mem_block *agp_heap;
unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
int vblank_pipe;
+ int num_pipe;
/* For hangcheck timer */
#define DRM_I915_HANGCHECK_PERIOD 75 /* in jiffies */
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 9ded3da..0743858 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2239,7 +2239,7 @@
mapping = inode->i_mapping;
for (i = 0; i < page_count; i++) {
page = read_cache_page_gfp(mapping, i,
- mapping_gfp_mask (mapping) |
+ GFP_HIGHUSER |
__GFP_COLD |
gfpmask);
if (IS_ERR(page))
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3acb766..68dcf36 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5509,7 +5509,6 @@
void intel_modeset_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- int num_pipe;
int i;
drm_mode_config_init(dev);
@@ -5539,13 +5538,13 @@
dev->mode_config.fb_base = pci_resource_start(dev->pdev, 0);
if (IS_MOBILE(dev) || IS_I9XX(dev))
- num_pipe = 2;
+ dev_priv->num_pipe = 2;
else
- num_pipe = 1;
+ dev_priv->num_pipe = 1;
DRM_DEBUG_KMS("%d display pipe%s available.\n",
- num_pipe, num_pipe > 1 ? "s" : "");
+ dev_priv->num_pipe, dev_priv->num_pipe > 1 ? "s" : "");
- for (i = 0; i < num_pipe; i++) {
+ for (i = 0; i < dev_priv->num_pipe; i++) {
intel_crtc_init(dev, i);
}
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index f8c76e6..c3c5052 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -245,6 +245,7 @@
{
struct intel_fbdev *ifbdev;
drm_i915_private_t *dev_priv = dev->dev_private;
+ int ret;
ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL);
if (!ifbdev)
@@ -253,8 +254,13 @@
dev_priv->fbdev = ifbdev;
ifbdev->helper.funcs = &intel_fb_helper_funcs;
- drm_fb_helper_init(dev, &ifbdev->helper, 2,
- INTELFB_CONN_LIMIT);
+ ret = drm_fb_helper_init(dev, &ifbdev->helper,
+ dev_priv->num_pipe,
+ INTELFB_CONN_LIMIT);
+ if (ret) {
+ kfree(ifbdev);
+ return ret;
+ }
drm_fb_helper_single_add_all_connectors(&ifbdev->helper);
drm_fb_helper_initial_config(&ifbdev->helper, 32);
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c
index e13f6af..d4bcca8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_acpi.c
+++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c
@@ -34,7 +34,7 @@
static struct nouveau_dsm_priv {
bool dsm_detected;
acpi_handle dhandle;
- acpi_handle dsm_handle;
+ acpi_handle rom_handle;
} nouveau_dsm_priv;
static const char nouveau_dsm_muid[] = {
@@ -107,9 +107,9 @@
static int nouveau_dsm_switchto(enum vga_switcheroo_client_id id)
{
if (id == VGA_SWITCHEROO_IGD)
- return nouveau_dsm_switch_mux(nouveau_dsm_priv.dsm_handle, NOUVEAU_DSM_LED_STAMINA);
+ return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_STAMINA);
else
- return nouveau_dsm_switch_mux(nouveau_dsm_priv.dsm_handle, NOUVEAU_DSM_LED_SPEED);
+ return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_SPEED);
}
static int nouveau_dsm_power_state(enum vga_switcheroo_client_id id,
@@ -118,7 +118,7 @@
if (id == VGA_SWITCHEROO_IGD)
return 0;
- return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dsm_handle, state);
+ return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dhandle, state);
}
static int nouveau_dsm_init(void)
@@ -151,18 +151,18 @@
dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
if (!dhandle)
return false;
+
status = acpi_get_handle(dhandle, "_DSM", &nvidia_handle);
if (ACPI_FAILURE(status)) {
return false;
}
- ret= nouveau_dsm(nvidia_handle, NOUVEAU_DSM_SUPPORTED,
- NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &result);
+ ret = nouveau_dsm(dhandle, NOUVEAU_DSM_SUPPORTED,
+ NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &result);
if (ret < 0)
return false;
nouveau_dsm_priv.dhandle = dhandle;
- nouveau_dsm_priv.dsm_handle = nvidia_handle;
return true;
}
@@ -173,6 +173,7 @@
struct pci_dev *pdev = NULL;
int has_dsm = 0;
int vga_count = 0;
+
while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
vga_count++;
@@ -180,7 +181,7 @@
}
if (vga_count == 2 && has_dsm) {
- acpi_get_name(nouveau_dsm_priv.dsm_handle, ACPI_FULL_PATHNAME, &buffer);
+ acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, &buffer);
printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n",
acpi_method_name);
nouveau_dsm_priv.dsm_detected = true;
@@ -204,3 +205,57 @@
{
vga_switcheroo_unregister_handler();
}
+
+/* retrieve the ROM in 4k blocks */
+static int nouveau_rom_call(acpi_handle rom_handle, uint8_t *bios,
+ int offset, int len)
+{
+ acpi_status status;
+ union acpi_object rom_arg_elements[2], *obj;
+ struct acpi_object_list rom_arg;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
+
+ rom_arg.count = 2;
+ rom_arg.pointer = &rom_arg_elements[0];
+
+ rom_arg_elements[0].type = ACPI_TYPE_INTEGER;
+ rom_arg_elements[0].integer.value = offset;
+
+ rom_arg_elements[1].type = ACPI_TYPE_INTEGER;
+ rom_arg_elements[1].integer.value = len;
+
+ status = acpi_evaluate_object(rom_handle, NULL, &rom_arg, &buffer);
+ if (ACPI_FAILURE(status)) {
+ printk(KERN_INFO "failed to evaluate ROM got %s\n", acpi_format_exception(status));
+ return -ENODEV;
+ }
+ obj = (union acpi_object *)buffer.pointer;
+ memcpy(bios+offset, obj->buffer.pointer, len);
+ kfree(buffer.pointer);
+ return len;
+}
+
+bool nouveau_acpi_rom_supported(struct pci_dev *pdev)
+{
+ acpi_status status;
+ acpi_handle dhandle, rom_handle;
+
+ if (!nouveau_dsm_priv.dsm_detected)
+ return false;
+
+ dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
+ if (!dhandle)
+ return false;
+
+ status = acpi_get_handle(dhandle, "_ROM", &rom_handle);
+ if (ACPI_FAILURE(status))
+ return false;
+
+ nouveau_dsm_priv.rom_handle = rom_handle;
+ return true;
+}
+
+int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len)
+{
+ return nouveau_rom_call(nouveau_dsm_priv.rom_handle, bios, offset, len);
+}
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index e7e69cc..fc924b6 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -178,6 +178,25 @@
pci_disable_rom(dev->pdev);
}
+static void load_vbios_acpi(struct drm_device *dev, uint8_t *data)
+{
+ int i;
+ int ret;
+ int size = 64 * 1024;
+
+ if (!nouveau_acpi_rom_supported(dev->pdev))
+ return;
+
+ for (i = 0; i < (size / ROM_BIOS_PAGE); i++) {
+ ret = nouveau_acpi_get_bios_chunk(data,
+ (i * ROM_BIOS_PAGE),
+ ROM_BIOS_PAGE);
+ if (ret <= 0)
+ break;
+ }
+ return;
+}
+
struct methods {
const char desc[8];
void (*loadbios)(struct drm_device *, uint8_t *);
@@ -191,6 +210,7 @@
};
static struct methods nv50_methods[] = {
+ { "ACPI", load_vbios_acpi, true },
{ "PRAMIN", load_vbios_pramin, true },
{ "PROM", load_vbios_prom, false },
{ "PCIROM", load_vbios_pci, true },
@@ -814,7 +834,7 @@
if (i2c_index == 0x81)
i2c_index = (dcb->i2c_default_indices & 0xf0) >> 4;
- if (i2c_index > DCB_MAX_NUM_I2C_ENTRIES) {
+ if (i2c_index >= DCB_MAX_NUM_I2C_ENTRIES) {
NV_ERROR(dev, "invalid i2c_index 0x%x\n", i2c_index);
return NULL;
}
@@ -2807,7 +2827,10 @@
BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry);
- nv50_gpio_set(bios->dev, gpio->tag, gpio->state_default);
+ BIOSLOG(bios, "0x%04X: set gpio 0x%02x, state %d\n",
+ offset, gpio->tag, gpio->state_default);
+ if (bios->execute)
+ nv50_gpio_set(bios->dev, gpio->tag, gpio->state_default);
/* The NVIDIA binary driver doesn't appear to actually do
* any of this, my VBIOS does however.
@@ -3897,7 +3920,8 @@
static uint8_t *
bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent,
- uint16_t record, int record_len, int record_nr)
+ uint16_t record, int record_len, int record_nr,
+ bool match_link)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nvbios *bios = &dev_priv->vbios;
@@ -3905,12 +3929,28 @@
uint16_t table;
int i, v;
+ switch (dcbent->type) {
+ case OUTPUT_TMDS:
+ case OUTPUT_LVDS:
+ case OUTPUT_DP:
+ break;
+ default:
+ match_link = false;
+ break;
+ }
+
for (i = 0; i < record_nr; i++, record += record_len) {
table = ROM16(bios->data[record]);
if (!table)
continue;
entry = ROM32(bios->data[table]);
+ if (match_link) {
+ v = (entry & 0x00c00000) >> 22;
+ if (!(v & dcbent->sorconf.link))
+ continue;
+ }
+
v = (entry & 0x000f0000) >> 16;
if (!(v & dcbent->or))
continue;
@@ -3952,7 +3992,7 @@
*length = table[4];
return bios_output_config_match(dev, dcbent,
bios->display.dp_table_ptr + table[1],
- table[2], table[3]);
+ table[2], table[3], table[0] >= 0x21);
}
int
@@ -4041,7 +4081,7 @@
dcbent->type, dcbent->location, dcbent->or);
otable = bios_output_config_match(dev, dcbent, table[1] +
bios->display.script_table_ptr,
- table[2], table[3]);
+ table[2], table[3], table[0] >= 0x21);
if (!otable) {
NV_ERROR(dev, "Couldn't find matching output script table\n");
return 1;
@@ -5533,12 +5573,6 @@
entry->bus = (conn >> 16) & 0xf;
entry->location = (conn >> 20) & 0x3;
entry->or = (conn >> 24) & 0xf;
- /*
- * Normal entries consist of a single bit, but dual link has the
- * next most significant bit set too
- */
- entry->duallink_possible =
- ((1 << (ffs(entry->or) - 1)) * 3 == entry->or);
switch (entry->type) {
case OUTPUT_ANALOG:
@@ -5622,6 +5656,16 @@
break;
}
+ if (dcb->version < 0x40) {
+ /* Normal entries consist of a single bit, but dual link has
+ * the next most significant bit set too
+ */
+ entry->duallink_possible =
+ ((1 << (ffs(entry->or) - 1)) * 3 == entry->or);
+ } else {
+ entry->duallink_possible = (entry->sorconf.link == 3);
+ }
+
/* unsure what DCB version introduces this, 3.0? */
if (conf & 0x100000)
entry->i2c_upper_default = true;
@@ -6205,6 +6249,30 @@
nouveau_i2c_fini(dev, entry);
}
+static bool
+nouveau_bios_posted(struct drm_device *dev)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ bool was_locked;
+ unsigned htotal;
+
+ if (dev_priv->chipset >= NV_50) {
+ if (NVReadVgaCrtc(dev, 0, 0x00) == 0 &&
+ NVReadVgaCrtc(dev, 0, 0x1a) == 0)
+ return false;
+ return true;
+ }
+
+ was_locked = NVLockVgaCrtcs(dev, false);
+ htotal = NVReadVgaCrtc(dev, 0, 0x06);
+ htotal |= (NVReadVgaCrtc(dev, 0, 0x07) & 0x01) << 8;
+ htotal |= (NVReadVgaCrtc(dev, 0, 0x07) & 0x20) << 4;
+ htotal |= (NVReadVgaCrtc(dev, 0, 0x25) & 0x01) << 10;
+ htotal |= (NVReadVgaCrtc(dev, 0, 0x41) & 0x01) << 11;
+ NVLockVgaCrtcs(dev, was_locked);
+ return (htotal != 0);
+}
+
int
nouveau_bios_init(struct drm_device *dev)
{
@@ -6239,11 +6307,9 @@
bios->execute = false;
/* ... unless card isn't POSTed already */
- if (dev_priv->card_type >= NV_10 &&
- NVReadVgaCrtc(dev, 0, 0x00) == 0 &&
- NVReadVgaCrtc(dev, 0, 0x1a) == 0) {
+ if (!nouveau_bios_posted(dev)) {
NV_INFO(dev, "Adaptor not initialised\n");
- if (dev_priv->card_type < NV_50) {
+ if (dev_priv->card_type < NV_40) {
NV_ERROR(dev, "Unable to POST this chipset\n");
return -ENODEV;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 266b0ff..149ed22 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -432,24 +432,27 @@
}
static struct drm_display_mode *
-nouveau_connector_native_mode(struct nouveau_connector *connector)
+nouveau_connector_native_mode(struct drm_connector *connector)
{
- struct drm_device *dev = connector->base.dev;
+ struct drm_connector_helper_funcs *helper = connector->helper_private;
+ struct nouveau_connector *nv_connector = nouveau_connector(connector);
+ struct drm_device *dev = connector->dev;
struct drm_display_mode *mode, *largest = NULL;
int high_w = 0, high_h = 0, high_v = 0;
- /* Use preferred mode if there is one.. */
- list_for_each_entry(mode, &connector->base.probed_modes, head) {
+ list_for_each_entry(mode, &nv_connector->base.probed_modes, head) {
+ if (helper->mode_valid(connector, mode) != MODE_OK)
+ continue;
+
+ /* Use preferred mode if there is one.. */
if (mode->type & DRM_MODE_TYPE_PREFERRED) {
NV_DEBUG_KMS(dev, "native mode from preferred\n");
return drm_mode_duplicate(dev, mode);
}
- }
- /* Otherwise, take the resolution with the largest width, then height,
- * then vertical refresh
- */
- list_for_each_entry(mode, &connector->base.probed_modes, head) {
+ /* Otherwise, take the resolution with the largest width, then
+ * height, then vertical refresh
+ */
if (mode->hdisplay < high_w)
continue;
@@ -553,7 +556,7 @@
*/
if (!nv_connector->native_mode)
nv_connector->native_mode =
- nouveau_connector_native_mode(nv_connector);
+ nouveau_connector_native_mode(connector);
if (ret == 0 && nv_connector->native_mode) {
struct drm_display_mode *mode;
@@ -584,9 +587,9 @@
switch (nv_encoder->dcb->type) {
case OUTPUT_LVDS:
- BUG_ON(!nv_connector->native_mode);
- if (mode->hdisplay > nv_connector->native_mode->hdisplay ||
- mode->vdisplay > nv_connector->native_mode->vdisplay)
+ if (nv_connector->native_mode &&
+ (mode->hdisplay > nv_connector->native_mode->hdisplay ||
+ mode->vdisplay > nv_connector->native_mode->vdisplay))
return MODE_PANEL;
min_clock = 0;
@@ -594,8 +597,7 @@
break;
case OUTPUT_TMDS:
if ((dev_priv->card_type >= NV_50 && !nouveau_duallink) ||
- (dev_priv->card_type < NV_50 &&
- !nv_encoder->dcb->duallink_possible))
+ !nv_encoder->dcb->duallink_possible)
max_clock = 165000;
else
max_clock = 330000;
@@ -729,7 +731,7 @@
if (ret == 0)
goto out;
nv_connector->detected_encoder = nv_encoder;
- nv_connector->native_mode = nouveau_connector_native_mode(nv_connector);
+ nv_connector->native_mode = nouveau_connector_native_mode(connector);
list_for_each_entry_safe(mode, temp, &connector->probed_modes, head)
drm_mode_remove(connector, mode);
diff --git a/drivers/gpu/drm/nouveau/nouveau_crtc.h b/drivers/gpu/drm/nouveau/nouveau_crtc.h
index 49fa7b2..cb1ce2a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_crtc.h
+++ b/drivers/gpu/drm/nouveau/nouveau_crtc.h
@@ -40,6 +40,8 @@
int sharpness;
int last_dpms;
+ int cursor_saved_x, cursor_saved_y;
+
struct {
int cpp;
bool blanked;
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c
index c6079e3..2737704 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.c
@@ -175,6 +175,13 @@
nouveau_bo_unpin(nouveau_fb->nvbo);
}
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+
+ nouveau_bo_unmap(nv_crtc->cursor.nvbo);
+ nouveau_bo_unpin(nv_crtc->cursor.nvbo);
+ }
+
NV_INFO(dev, "Evicting buffers...\n");
ttm_bo_evict_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
@@ -314,12 +321,34 @@
nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM);
}
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+ int ret;
+
+ ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
+ if (!ret)
+ ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
+ if (ret)
+ NV_ERROR(dev, "Could not pin/map cursor.\n");
+ }
+
if (dev_priv->card_type < NV_50) {
nv04_display_restore(dev);
NVLockVgaCrtcs(dev, false);
} else
nv50_display_init(dev);
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+
+ nv_crtc->cursor.set_offset(nv_crtc,
+ nv_crtc->cursor.nvbo->bo.offset -
+ dev_priv->vm_vram_base);
+
+ nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x,
+ nv_crtc->cursor_saved_y);
+ }
+
/* Force CLUT to get re-loaded during modeset */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 5b13443..c697191 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -851,12 +851,17 @@
extern int nouveau_dma_wait(struct nouveau_channel *, int slots, int size);
/* nouveau_acpi.c */
+#define ROM_BIOS_PAGE 4096
#if defined(CONFIG_ACPI)
void nouveau_register_dsm_handler(void);
void nouveau_unregister_dsm_handler(void);
+int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len);
+bool nouveau_acpi_rom_supported(struct pci_dev *pdev);
#else
static inline void nouveau_register_dsm_handler(void) {}
static inline void nouveau_unregister_dsm_handler(void) {}
+static inline bool nouveau_acpi_rom_supported(struct pci_dev *pdev) { return false; }
+static inline int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) { return -EINVAL; }
#endif
/* nouveau_backlight.c */
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index fd4a2df..c9a4a0d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -377,6 +377,7 @@
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_fbdev *nfbdev;
+ int ret;
nfbdev = kzalloc(sizeof(struct nouveau_fbdev), GFP_KERNEL);
if (!nfbdev)
@@ -386,7 +387,12 @@
dev_priv->nfbdev = nfbdev;
nfbdev->helper.funcs = &nouveau_fbcon_helper_funcs;
- drm_fb_helper_init(dev, &nfbdev->helper, 2, 4);
+ ret = drm_fb_helper_init(dev, &nfbdev->helper, 2, 4);
+ if (ret) {
+ kfree(nfbdev);
+ return ret;
+ }
+
drm_fb_helper_single_add_all_connectors(&nfbdev->helper);
drm_fb_helper_initial_config(&nfbdev->helper, 32);
return 0;
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c
index 775a701..c1fd42b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c
@@ -540,7 +540,8 @@
dev_priv->vram_size = nv_rd32(dev, NV04_FIFO_DATA);
dev_priv->vram_size &= NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK;
if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac)
- dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10) << 12;
+ dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10);
+ dev_priv->vram_sys_base <<= 12;
}
NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20));
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
index e632339..b02a231 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -376,12 +376,15 @@
static void nouveau_switcheroo_set_state(struct pci_dev *pdev,
enum vga_switcheroo_state state)
{
+ struct drm_device *dev = pci_get_drvdata(pdev);
pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
if (state == VGA_SWITCHEROO_ON) {
printk(KERN_ERR "VGA switcheroo: switched nouveau on\n");
nouveau_pci_resume(pdev);
+ drm_kms_helper_poll_enable(dev);
} else {
printk(KERN_ERR "VGA switcheroo: switched nouveau off\n");
+ drm_kms_helper_poll_disable(dev);
nouveau_pci_suspend(pdev, pmm);
}
}
@@ -776,29 +779,24 @@
return ret;
}
- /* map larger RAMIN aperture on NV40 cards */
- dev_priv->ramin = NULL;
+ /* Map PRAMIN BAR, or on older cards, the aperture withing BAR0 */
if (dev_priv->card_type >= NV_40) {
int ramin_bar = 2;
if (pci_resource_len(dev->pdev, ramin_bar) == 0)
ramin_bar = 3;
dev_priv->ramin_size = pci_resource_len(dev->pdev, ramin_bar);
- dev_priv->ramin = ioremap(
- pci_resource_start(dev->pdev, ramin_bar),
+ dev_priv->ramin =
+ ioremap(pci_resource_start(dev->pdev, ramin_bar),
dev_priv->ramin_size);
if (!dev_priv->ramin) {
- NV_ERROR(dev, "Failed to init RAMIN mapping, "
- "limited instance memory available\n");
+ NV_ERROR(dev, "Failed to PRAMIN BAR");
+ return -ENOMEM;
}
- }
-
- /* On older cards (or if the above failed), create a map covering
- * the BAR0 PRAMIN aperture */
- if (!dev_priv->ramin) {
+ } else {
dev_priv->ramin_size = 1 * 1024 * 1024;
dev_priv->ramin = ioremap(mmio_start_offs + NV_RAMIN,
- dev_priv->ramin_size);
+ dev_priv->ramin_size);
if (!dev_priv->ramin) {
NV_ERROR(dev, "Failed to map BAR0 PRAMIN.\n");
return -ENOMEM;
@@ -913,6 +911,9 @@
case NOUVEAU_GETPARAM_VM_VRAM_BASE:
getparam->value = dev_priv->vm_vram_base;
break;
+ case NOUVEAU_GETPARAM_PTIMER_TIME:
+ getparam->value = dev_priv->engine.timer.read(dev);
+ break;
case NOUVEAU_GETPARAM_GRAPH_UNITS:
/* NV40 and NV50 versions are quite different, but register
* address is the same. User is supposed to know the card
diff --git a/drivers/gpu/drm/nouveau/nv04_cursor.c b/drivers/gpu/drm/nouveau/nv04_cursor.c
index 89a91b9..aaf3de3 100644
--- a/drivers/gpu/drm/nouveau/nv04_cursor.c
+++ b/drivers/gpu/drm/nouveau/nv04_cursor.c
@@ -20,6 +20,7 @@
static void
nv04_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y)
{
+ nv_crtc->cursor_saved_x = x; nv_crtc->cursor_saved_y = y;
NVWriteRAMDAC(nv_crtc->base.dev, nv_crtc->index,
NV_PRAMDAC_CU_START_POS,
XLATE(y, 0, NV_PRAMDAC_CU_START_POS_Y) |
diff --git a/drivers/gpu/drm/nouveau/nv50_cursor.c b/drivers/gpu/drm/nouveau/nv50_cursor.c
index 753e723..03ad7ab 100644
--- a/drivers/gpu/drm/nouveau/nv50_cursor.c
+++ b/drivers/gpu/drm/nouveau/nv50_cursor.c
@@ -107,6 +107,7 @@
{
struct drm_device *dev = nv_crtc->base.dev;
+ nv_crtc->cursor_saved_x = x; nv_crtc->cursor_saved_y = y;
nv_wr32(dev, NV50_PDISPLAY_CURSOR_USER_POS(nv_crtc->index),
((y & 0xFFFF) << 16) | (x & 0xFFFF));
/* Needed to make the cursor move. */
diff --git a/drivers/gpu/drm/nouveau/nv50_fb.c b/drivers/gpu/drm/nouveau/nv50_fb.c
index a95e694..32611bd 100644
--- a/drivers/gpu/drm/nouveau/nv50_fb.c
+++ b/drivers/gpu/drm/nouveau/nv50_fb.c
@@ -6,10 +6,16 @@
int
nv50_fb_init(struct drm_device *dev)
{
- /* This is needed to get meaningful information from 100c90
- * on traps. No idea what these values mean exactly. */
struct drm_nouveau_private *dev_priv = dev->dev_private;
+ /* Not a clue what this is exactly. Without pointing it at a
+ * scratch page, VRAM->GART blits with M2MF (as in DDX DFS)
+ * cause IOMMU "read from address 0" errors (rh#561267)
+ */
+ nv_wr32(dev, 0x100c08, dev_priv->gart_info.sg_dummy_bus >> 8);
+
+ /* This is needed to get meaningful information from 100c90
+ * on traps. No idea what these values mean exactly. */
switch (dev_priv->chipset) {
case 0x50:
nv_wr32(dev, 0x100c90, 0x0707ff);
diff --git a/drivers/gpu/drm/nouveau/nv50_gpio.c b/drivers/gpu/drm/nouveau/nv50_gpio.c
index c61782b..bb47ad7 100644
--- a/drivers/gpu/drm/nouveau/nv50_gpio.c
+++ b/drivers/gpu/drm/nouveau/nv50_gpio.c
@@ -31,7 +31,7 @@
{
const uint32_t nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 };
- if (gpio->line > 32)
+ if (gpio->line >= 32)
return -EINVAL;
*reg = nv50_gpio_reg[gpio->line >> 3];
diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c
index b11eaf9..812778d 100644
--- a/drivers/gpu/drm/nouveau/nv50_sor.c
+++ b/drivers/gpu/drm/nouveau/nv50_sor.c
@@ -274,7 +274,6 @@
int
nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)
{
- struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_encoder *nv_encoder = NULL;
struct drm_encoder *encoder;
bool dum;
@@ -324,11 +323,7 @@
int or = nv_encoder->or, link = !(entry->dpconf.sor.link & 1);
uint32_t tmp;
- if (dev_priv->chipset < 0x90 ||
- dev_priv->chipset == 0x92 || dev_priv->chipset == 0xa0)
- tmp = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_C(or));
- else
- tmp = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_C(or));
+ tmp = nv_rd32(dev, 0x61c700 + (or * 0x800));
switch ((tmp & 0x00000f00) >> 8) {
case 8:
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
index 3c91312..84b1f27 100644
--- a/drivers/gpu/drm/radeon/Makefile
+++ b/drivers/gpu/drm/radeon/Makefile
@@ -33,6 +33,9 @@
$(obj)/r600_reg_safe.h: $(src)/reg_srcs/r600 $(obj)/mkregtable
$(call if_changed,mkregtable)
+$(obj)/evergreen_reg_safe.h: $(src)/reg_srcs/evergreen $(obj)/mkregtable
+ $(call if_changed,mkregtable)
+
$(obj)/r100.o: $(obj)/r100_reg_safe.h $(obj)/rn50_reg_safe.h
$(obj)/r200.o: $(obj)/r200_reg_safe.h
@@ -47,6 +50,8 @@
$(obj)/r600_cs.o: $(obj)/r600_reg_safe.h
+$(obj)/evergreen_cs.o: $(obj)/evergreen_reg_safe.h
+
radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o \
radeon_irq.o r300_cmdbuf.o r600_cp.o
# add KMS driver
@@ -60,7 +65,7 @@
rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \
r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \
r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \
- evergreen.o
+ evergreen.o evergreen_cs.o
radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index f3f2827..8c2d647 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -498,7 +498,7 @@
if ((rdev->family == CHIP_RS600) ||
(rdev->family == CHIP_RS690) ||
(rdev->family == CHIP_RS740))
- pll->flags |= (RADEON_PLL_USE_FRAC_FB_DIV |
+ pll->flags |= (/*RADEON_PLL_USE_FRAC_FB_DIV |*/
RADEON_PLL_PREFER_CLOSEST_LOWER);
if (ASIC_IS_DCE32(rdev) && mode->clock > 200000) /* range limits??? */
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 8c8e4d3..1caf625 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -41,7 +41,18 @@
void evergreen_pm_misc(struct radeon_device *rdev)
{
+ int req_ps_idx = rdev->pm.requested_power_state_index;
+ int req_cm_idx = rdev->pm.requested_clock_mode_index;
+ struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx];
+ struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;
+ if ((voltage->type == VOLTAGE_SW) && voltage->voltage) {
+ if (voltage->voltage != rdev->pm.current_vddc) {
+ radeon_atom_set_voltage(rdev, voltage->voltage);
+ rdev->pm.current_vddc = voltage->voltage;
+ DRM_DEBUG("Setting: v: %d\n", voltage->voltage);
+ }
+ }
}
void evergreen_pm_prepare(struct radeon_device *rdev)
@@ -596,7 +607,7 @@
WREG32(MC_VM_FB_LOCATION, tmp);
WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8));
WREG32(HDP_NONSURFACE_INFO, (2 << 7));
- WREG32(HDP_NONSURFACE_SIZE, (rdev->mc.mc_vram_size - 1) | 0x3FF);
+ WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF);
if (rdev->flags & RADEON_IS_AGP) {
WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 16);
WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 16);
@@ -1211,11 +1222,11 @@
ps_thread_count = 128;
sq_thread_resource_mgmt = NUM_PS_THREADS(ps_thread_count);
- sq_thread_resource_mgmt |= NUM_VS_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8;
- sq_thread_resource_mgmt |= NUM_GS_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8;
- sq_thread_resource_mgmt |= NUM_ES_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8;
- sq_thread_resource_mgmt_2 = NUM_HS_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8;
- sq_thread_resource_mgmt_2 |= NUM_LS_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8;
+ sq_thread_resource_mgmt |= NUM_VS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8);
+ sq_thread_resource_mgmt |= NUM_GS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8);
+ sq_thread_resource_mgmt |= NUM_ES_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8);
+ sq_thread_resource_mgmt_2 = NUM_HS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8);
+ sq_thread_resource_mgmt_2 |= NUM_LS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8);
sq_stack_resource_mgmt_1 = NUM_PS_STACK_ENTRIES((rdev->config.evergreen.max_stack_entries * 1) / 6);
sq_stack_resource_mgmt_1 |= NUM_VS_STACK_ENTRIES((rdev->config.evergreen.max_stack_entries * 1) / 6);
@@ -1249,6 +1260,9 @@
WREG32(VGT_GS_VERTEX_REUSE, 16);
WREG32(PA_SC_LINE_STIPPLE_STATE, 0);
+ WREG32(VGT_VERTEX_REUSE_BLOCK_CNTL, 14);
+ WREG32(VGT_OUT_DEALLOC_CNTL, 16);
+
WREG32(CB_PERF_CTR0_SEL_0, 0);
WREG32(CB_PERF_CTR0_SEL_1, 0);
WREG32(CB_PERF_CTR1_SEL_0, 0);
@@ -1258,6 +1272,26 @@
WREG32(CB_PERF_CTR3_SEL_0, 0);
WREG32(CB_PERF_CTR3_SEL_1, 0);
+ /* clear render buffer base addresses */
+ WREG32(CB_COLOR0_BASE, 0);
+ WREG32(CB_COLOR1_BASE, 0);
+ WREG32(CB_COLOR2_BASE, 0);
+ WREG32(CB_COLOR3_BASE, 0);
+ WREG32(CB_COLOR4_BASE, 0);
+ WREG32(CB_COLOR5_BASE, 0);
+ WREG32(CB_COLOR6_BASE, 0);
+ WREG32(CB_COLOR7_BASE, 0);
+ WREG32(CB_COLOR8_BASE, 0);
+ WREG32(CB_COLOR9_BASE, 0);
+ WREG32(CB_COLOR10_BASE, 0);
+ WREG32(CB_COLOR11_BASE, 0);
+
+ /* set the shader const cache sizes to 0 */
+ for (i = SQ_ALU_CONST_BUFFER_SIZE_PS_0; i < 0x28200; i += 4)
+ WREG32(i, 0);
+ for (i = SQ_ALU_CONST_BUFFER_SIZE_HS_0; i < 0x29000; i += 4)
+ WREG32(i, 0);
+
hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL);
WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl);
@@ -2148,7 +2182,7 @@
if (r)
return r;
- rdev->accel_working = false;
+ rdev->accel_working = true;
r = evergreen_startup(rdev);
if (r) {
dev_err(rdev->dev, "disabling GPU acceleration\n");
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c
new file mode 100644
index 0000000..010963d
--- /dev/null
+++ b/drivers/gpu/drm/radeon/evergreen_cs.c
@@ -0,0 +1,1356 @@
+/*
+ * Copyright 2010 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ * Alex Deucher
+ * Jerome Glisse
+ */
+#include "drmP.h"
+#include "radeon.h"
+#include "evergreend.h"
+#include "evergreen_reg_safe.h"
+
+static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
+ struct radeon_cs_reloc **cs_reloc);
+
+struct evergreen_cs_track {
+ u32 group_size;
+ u32 nbanks;
+ u32 npipes;
+ /* value we track */
+ u32 nsamples;
+ u32 cb_color_base_last[12];
+ struct radeon_bo *cb_color_bo[12];
+ u32 cb_color_bo_offset[12];
+ struct radeon_bo *cb_color_fmask_bo[8];
+ struct radeon_bo *cb_color_cmask_bo[8];
+ u32 cb_color_info[12];
+ u32 cb_color_view[12];
+ u32 cb_color_pitch_idx[12];
+ u32 cb_color_slice_idx[12];
+ u32 cb_color_dim_idx[12];
+ u32 cb_color_dim[12];
+ u32 cb_color_pitch[12];
+ u32 cb_color_slice[12];
+ u32 cb_color_cmask_slice[8];
+ u32 cb_color_fmask_slice[8];
+ u32 cb_target_mask;
+ u32 cb_shader_mask;
+ u32 vgt_strmout_config;
+ u32 vgt_strmout_buffer_config;
+ u32 db_depth_control;
+ u32 db_depth_view;
+ u32 db_depth_size;
+ u32 db_depth_size_idx;
+ u32 db_z_info;
+ u32 db_z_idx;
+ u32 db_z_read_offset;
+ u32 db_z_write_offset;
+ struct radeon_bo *db_z_read_bo;
+ struct radeon_bo *db_z_write_bo;
+ u32 db_s_info;
+ u32 db_s_idx;
+ u32 db_s_read_offset;
+ u32 db_s_write_offset;
+ struct radeon_bo *db_s_read_bo;
+ struct radeon_bo *db_s_write_bo;
+};
+
+static void evergreen_cs_track_init(struct evergreen_cs_track *track)
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ track->cb_color_fmask_bo[i] = NULL;
+ track->cb_color_cmask_bo[i] = NULL;
+ track->cb_color_cmask_slice[i] = 0;
+ track->cb_color_fmask_slice[i] = 0;
+ }
+
+ for (i = 0; i < 12; i++) {
+ track->cb_color_base_last[i] = 0;
+ track->cb_color_bo[i] = NULL;
+ track->cb_color_bo_offset[i] = 0xFFFFFFFF;
+ track->cb_color_info[i] = 0;
+ track->cb_color_view[i] = 0;
+ track->cb_color_pitch_idx[i] = 0;
+ track->cb_color_slice_idx[i] = 0;
+ track->cb_color_dim[i] = 0;
+ track->cb_color_pitch[i] = 0;
+ track->cb_color_slice[i] = 0;
+ track->cb_color_dim[i] = 0;
+ }
+ track->cb_target_mask = 0xFFFFFFFF;
+ track->cb_shader_mask = 0xFFFFFFFF;
+
+ track->db_depth_view = 0xFFFFC000;
+ track->db_depth_size = 0xFFFFFFFF;
+ track->db_depth_size_idx = 0;
+ track->db_depth_control = 0xFFFFFFFF;
+ track->db_z_info = 0xFFFFFFFF;
+ track->db_z_idx = 0xFFFFFFFF;
+ track->db_z_read_offset = 0xFFFFFFFF;
+ track->db_z_write_offset = 0xFFFFFFFF;
+ track->db_z_read_bo = NULL;
+ track->db_z_write_bo = NULL;
+ track->db_s_info = 0xFFFFFFFF;
+ track->db_s_idx = 0xFFFFFFFF;
+ track->db_s_read_offset = 0xFFFFFFFF;
+ track->db_s_write_offset = 0xFFFFFFFF;
+ track->db_s_read_bo = NULL;
+ track->db_s_write_bo = NULL;
+}
+
+static inline int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
+{
+ /* XXX fill in */
+ return 0;
+}
+
+static int evergreen_cs_track_check(struct radeon_cs_parser *p)
+{
+ struct evergreen_cs_track *track = p->track;
+
+ /* we don't support stream out buffer yet */
+ if (track->vgt_strmout_config || track->vgt_strmout_buffer_config) {
+ dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n");
+ return -EINVAL;
+ }
+
+ /* XXX fill in */
+ return 0;
+}
+
+/**
+ * evergreen_cs_packet_parse() - parse cp packet and point ib index to next packet
+ * @parser: parser structure holding parsing context.
+ * @pkt: where to store packet informations
+ *
+ * Assume that chunk_ib_index is properly set. Will return -EINVAL
+ * if packet is bigger than remaining ib size. or if packets is unknown.
+ **/
+int evergreen_cs_packet_parse(struct radeon_cs_parser *p,
+ struct radeon_cs_packet *pkt,
+ unsigned idx)
+{
+ struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
+ uint32_t header;
+
+ if (idx >= ib_chunk->length_dw) {
+ DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
+ idx, ib_chunk->length_dw);
+ return -EINVAL;
+ }
+ header = radeon_get_ib_value(p, idx);
+ pkt->idx = idx;
+ pkt->type = CP_PACKET_GET_TYPE(header);
+ pkt->count = CP_PACKET_GET_COUNT(header);
+ pkt->one_reg_wr = 0;
+ switch (pkt->type) {
+ case PACKET_TYPE0:
+ pkt->reg = CP_PACKET0_GET_REG(header);
+ break;
+ case PACKET_TYPE3:
+ pkt->opcode = CP_PACKET3_GET_OPCODE(header);
+ break;
+ case PACKET_TYPE2:
+ pkt->count = -1;
+ break;
+ default:
+ DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx);
+ return -EINVAL;
+ }
+ if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) {
+ DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n",
+ pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/**
+ * evergreen_cs_packet_next_reloc() - parse next packet which should be reloc packet3
+ * @parser: parser structure holding parsing context.
+ * @data: pointer to relocation data
+ * @offset_start: starting offset
+ * @offset_mask: offset mask (to align start offset on)
+ * @reloc: reloc informations
+ *
+ * Check next packet is relocation packet3, do bo validation and compute
+ * GPU offset using the provided start.
+ **/
+static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
+ struct radeon_cs_reloc **cs_reloc)
+{
+ struct radeon_cs_chunk *relocs_chunk;
+ struct radeon_cs_packet p3reloc;
+ unsigned idx;
+ int r;
+
+ if (p->chunk_relocs_idx == -1) {
+ DRM_ERROR("No relocation chunk !\n");
+ return -EINVAL;
+ }
+ *cs_reloc = NULL;
+ relocs_chunk = &p->chunks[p->chunk_relocs_idx];
+ r = evergreen_cs_packet_parse(p, &p3reloc, p->idx);
+ if (r) {
+ return r;
+ }
+ p->idx += p3reloc.count + 2;
+ if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
+ DRM_ERROR("No packet3 for relocation for packet at %d.\n",
+ p3reloc.idx);
+ return -EINVAL;
+ }
+ idx = radeon_get_ib_value(p, p3reloc.idx + 1);
+ if (idx >= relocs_chunk->length_dw) {
+ DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
+ idx, relocs_chunk->length_dw);
+ return -EINVAL;
+ }
+ /* FIXME: we assume reloc size is 4 dwords */
+ *cs_reloc = p->relocs_ptr[(idx / 4)];
+ return 0;
+}
+
+/**
+ * evergreen_cs_packet_next_is_pkt3_nop() - test if next packet is packet3 nop for reloc
+ * @parser: parser structure holding parsing context.
+ *
+ * Check next packet is relocation packet3, do bo validation and compute
+ * GPU offset using the provided start.
+ **/
+static inline int evergreen_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
+{
+ struct radeon_cs_packet p3reloc;
+ int r;
+
+ r = evergreen_cs_packet_parse(p, &p3reloc, p->idx);
+ if (r) {
+ return 0;
+ }
+ if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
+ return 0;
+ }
+ return 1;
+}
+
+/**
+ * evergreen_cs_packet_next_vline() - parse userspace VLINE packet
+ * @parser: parser structure holding parsing context.
+ *
+ * Userspace sends a special sequence for VLINE waits.
+ * PACKET0 - VLINE_START_END + value
+ * PACKET3 - WAIT_REG_MEM poll vline status reg
+ * RELOC (P3) - crtc_id in reloc.
+ *
+ * This function parses this and relocates the VLINE START END
+ * and WAIT_REG_MEM packets to the correct crtc.
+ * It also detects a switched off crtc and nulls out the
+ * wait in that case.
+ */
+static int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p)
+{
+ struct drm_mode_object *obj;
+ struct drm_crtc *crtc;
+ struct radeon_crtc *radeon_crtc;
+ struct radeon_cs_packet p3reloc, wait_reg_mem;
+ int crtc_id;
+ int r;
+ uint32_t header, h_idx, reg, wait_reg_mem_info;
+ volatile uint32_t *ib;
+
+ ib = p->ib->ptr;
+
+ /* parse the WAIT_REG_MEM */
+ r = evergreen_cs_packet_parse(p, &wait_reg_mem, p->idx);
+ if (r)
+ return r;
+
+ /* check its a WAIT_REG_MEM */
+ if (wait_reg_mem.type != PACKET_TYPE3 ||
+ wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
+ DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");
+ r = -EINVAL;
+ return r;
+ }
+
+ wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
+ /* bit 4 is reg (0) or mem (1) */
+ if (wait_reg_mem_info & 0x10) {
+ DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n");
+ r = -EINVAL;
+ return r;
+ }
+ /* waiting for value to be equal */
+ if ((wait_reg_mem_info & 0x7) != 0x3) {
+ DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
+ r = -EINVAL;
+ return r;
+ }
+ if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != EVERGREEN_VLINE_STATUS) {
+ DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
+ r = -EINVAL;
+ return r;
+ }
+
+ if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != EVERGREEN_VLINE_STAT) {
+ DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
+ r = -EINVAL;
+ return r;
+ }
+
+ /* jump over the NOP */
+ r = evergreen_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2);
+ if (r)
+ return r;
+
+ h_idx = p->idx - 2;
+ p->idx += wait_reg_mem.count + 2;
+ p->idx += p3reloc.count + 2;
+
+ header = radeon_get_ib_value(p, h_idx);
+ crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
+ reg = CP_PACKET0_GET_REG(header);
+ mutex_lock(&p->rdev->ddev->mode_config.mutex);
+ obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
+ if (!obj) {
+ DRM_ERROR("cannot find crtc %d\n", crtc_id);
+ r = -EINVAL;
+ goto out;
+ }
+ crtc = obj_to_crtc(obj);
+ radeon_crtc = to_radeon_crtc(crtc);
+ crtc_id = radeon_crtc->crtc_id;
+
+ if (!crtc->enabled) {
+ /* if the CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */
+ ib[h_idx + 2] = PACKET2(0);
+ ib[h_idx + 3] = PACKET2(0);
+ ib[h_idx + 4] = PACKET2(0);
+ ib[h_idx + 5] = PACKET2(0);
+ ib[h_idx + 6] = PACKET2(0);
+ ib[h_idx + 7] = PACKET2(0);
+ ib[h_idx + 8] = PACKET2(0);
+ } else {
+ switch (reg) {
+ case EVERGREEN_VLINE_START_END:
+ header &= ~R600_CP_PACKET0_REG_MASK;
+ header |= (EVERGREEN_VLINE_START_END + radeon_crtc->crtc_offset) >> 2;
+ ib[h_idx] = header;
+ ib[h_idx + 4] = (EVERGREEN_VLINE_STATUS + radeon_crtc->crtc_offset) >> 2;
+ break;
+ default:
+ DRM_ERROR("unknown crtc reloc\n");
+ r = -EINVAL;
+ goto out;
+ }
+ }
+out:
+ mutex_unlock(&p->rdev->ddev->mode_config.mutex);
+ return r;
+}
+
+static int evergreen_packet0_check(struct radeon_cs_parser *p,
+ struct radeon_cs_packet *pkt,
+ unsigned idx, unsigned reg)
+{
+ int r;
+
+ switch (reg) {
+ case EVERGREEN_VLINE_START_END:
+ r = evergreen_cs_packet_parse_vline(p);
+ if (r) {
+ DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+ idx, reg);
+ return r;
+ }
+ break;
+ default:
+ printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
+ reg, idx);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int evergreen_cs_parse_packet0(struct radeon_cs_parser *p,
+ struct radeon_cs_packet *pkt)
+{
+ unsigned reg, i;
+ unsigned idx;
+ int r;
+
+ idx = pkt->idx + 1;
+ reg = pkt->reg;
+ for (i = 0; i <= pkt->count; i++, idx++, reg += 4) {
+ r = evergreen_packet0_check(p, pkt, idx, reg);
+ if (r) {
+ return r;
+ }
+ }
+ return 0;
+}
+
+/**
+ * evergreen_cs_check_reg() - check if register is authorized or not
+ * @parser: parser structure holding parsing context
+ * @reg: register we are testing
+ * @idx: index into the cs buffer
+ *
+ * This function will test against evergreen_reg_safe_bm and return 0
+ * if register is safe. If register is not flag as safe this function
+ * will test it against a list of register needind special handling.
+ */
+static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
+{
+ struct evergreen_cs_track *track = (struct evergreen_cs_track *)p->track;
+ struct radeon_cs_reloc *reloc;
+ u32 last_reg = ARRAY_SIZE(evergreen_reg_safe_bm);
+ u32 m, i, tmp, *ib;
+ int r;
+
+ i = (reg >> 7);
+ if (i > last_reg) {
+ dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
+ return -EINVAL;
+ }
+ m = 1 << ((reg >> 2) & 31);
+ if (!(evergreen_reg_safe_bm[i] & m))
+ return 0;
+ ib = p->ib->ptr;
+ switch (reg) {
+ /* force following reg to 0 in an attemp to disable out buffer
+ * which will need us to better understand how it works to perform
+ * security check on it (Jerome)
+ */
+ case SQ_ESGS_RING_SIZE:
+ case SQ_GSVS_RING_SIZE:
+ case SQ_ESTMP_RING_SIZE:
+ case SQ_GSTMP_RING_SIZE:
+ case SQ_HSTMP_RING_SIZE:
+ case SQ_LSTMP_RING_SIZE:
+ case SQ_PSTMP_RING_SIZE:
+ case SQ_VSTMP_RING_SIZE:
+ case SQ_ESGS_RING_ITEMSIZE:
+ case SQ_ESTMP_RING_ITEMSIZE:
+ case SQ_GSTMP_RING_ITEMSIZE:
+ case SQ_GSVS_RING_ITEMSIZE:
+ case SQ_GS_VERT_ITEMSIZE:
+ case SQ_GS_VERT_ITEMSIZE_1:
+ case SQ_GS_VERT_ITEMSIZE_2:
+ case SQ_GS_VERT_ITEMSIZE_3:
+ case SQ_GSVS_RING_OFFSET_1:
+ case SQ_GSVS_RING_OFFSET_2:
+ case SQ_GSVS_RING_OFFSET_3:
+ case SQ_HSTMP_RING_ITEMSIZE:
+ case SQ_LSTMP_RING_ITEMSIZE:
+ case SQ_PSTMP_RING_ITEMSIZE:
+ case SQ_VSTMP_RING_ITEMSIZE:
+ case VGT_TF_RING_SIZE:
+ /* get value to populate the IB don't remove */
+ tmp =radeon_get_ib_value(p, idx);
+ ib[idx] = 0;
+ break;
+ case DB_DEPTH_CONTROL:
+ track->db_depth_control = radeon_get_ib_value(p, idx);
+ break;
+ case DB_Z_INFO:
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ dev_warn(p->dev, "bad SET_CONTEXT_REG "
+ "0x%04X\n", reg);
+ return -EINVAL;
+ }
+ track->db_z_info = radeon_get_ib_value(p, idx);
+ ib[idx] &= ~Z_ARRAY_MODE(0xf);
+ track->db_z_info &= ~Z_ARRAY_MODE(0xf);
+ if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
+ ib[idx] |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+ track->db_z_info |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+ } else {
+ ib[idx] |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+ track->db_z_info |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+ }
+ break;
+ case DB_STENCIL_INFO:
+ track->db_s_info = radeon_get_ib_value(p, idx);
+ break;
+ case DB_DEPTH_VIEW:
+ track->db_depth_view = radeon_get_ib_value(p, idx);
+ break;
+ case DB_DEPTH_SIZE:
+ track->db_depth_size = radeon_get_ib_value(p, idx);
+ track->db_depth_size_idx = idx;
+ break;
+ case DB_Z_READ_BASE:
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ dev_warn(p->dev, "bad SET_CONTEXT_REG "
+ "0x%04X\n", reg);
+ return -EINVAL;
+ }
+ track->db_z_read_offset = radeon_get_ib_value(p, idx);
+ ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+ track->db_z_read_bo = reloc->robj;
+ break;
+ case DB_Z_WRITE_BASE:
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ dev_warn(p->dev, "bad SET_CONTEXT_REG "
+ "0x%04X\n", reg);
+ return -EINVAL;
+ }
+ track->db_z_write_offset = radeon_get_ib_value(p, idx);
+ ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+ track->db_z_write_bo = reloc->robj;
+ break;
+ case DB_STENCIL_READ_BASE:
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ dev_warn(p->dev, "bad SET_CONTEXT_REG "
+ "0x%04X\n", reg);
+ return -EINVAL;
+ }
+ track->db_s_read_offset = radeon_get_ib_value(p, idx);
+ ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+ track->db_s_read_bo = reloc->robj;
+ break;
+ case DB_STENCIL_WRITE_BASE:
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ dev_warn(p->dev, "bad SET_CONTEXT_REG "
+ "0x%04X\n", reg);
+ return -EINVAL;
+ }
+ track->db_s_write_offset = radeon_get_ib_value(p, idx);
+ ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+ track->db_s_write_bo = reloc->robj;
+ break;
+ case VGT_STRMOUT_CONFIG:
+ track->vgt_strmout_config = radeon_get_ib_value(p, idx);
+ break;
+ case VGT_STRMOUT_BUFFER_CONFIG:
+ track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx);
+ break;
+ case CB_TARGET_MASK:
+ track->cb_target_mask = radeon_get_ib_value(p, idx);
+ break;
+ case CB_SHADER_MASK:
+ track->cb_shader_mask = radeon_get_ib_value(p, idx);
+ break;
+ case PA_SC_AA_CONFIG:
+ tmp = radeon_get_ib_value(p, idx) & MSAA_NUM_SAMPLES_MASK;
+ track->nsamples = 1 << tmp;
+ break;
+ case CB_COLOR0_VIEW:
+ case CB_COLOR1_VIEW:
+ case CB_COLOR2_VIEW:
+ case CB_COLOR3_VIEW:
+ case CB_COLOR4_VIEW:
+ case CB_COLOR5_VIEW:
+ case CB_COLOR6_VIEW:
+ case CB_COLOR7_VIEW:
+ tmp = (reg - CB_COLOR0_VIEW) / 0x3c;
+ track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);
+ break;
+ case CB_COLOR8_VIEW:
+ case CB_COLOR9_VIEW:
+ case CB_COLOR10_VIEW:
+ case CB_COLOR11_VIEW:
+ tmp = ((reg - CB_COLOR8_VIEW) / 0x1c) + 8;
+ track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);
+ break;
+ case CB_COLOR0_INFO:
+ case CB_COLOR1_INFO:
+ case CB_COLOR2_INFO:
+ case CB_COLOR3_INFO:
+ case CB_COLOR4_INFO:
+ case CB_COLOR5_INFO:
+ case CB_COLOR6_INFO:
+ case CB_COLOR7_INFO:
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ dev_warn(p->dev, "bad SET_CONTEXT_REG "
+ "0x%04X\n", reg);
+ return -EINVAL;
+ }
+ tmp = (reg - CB_COLOR0_INFO) / 0x3c;
+ track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
+ if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
+ ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+ track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+ } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
+ ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+ track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+ }
+ break;
+ case CB_COLOR8_INFO:
+ case CB_COLOR9_INFO:
+ case CB_COLOR10_INFO:
+ case CB_COLOR11_INFO:
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ dev_warn(p->dev, "bad SET_CONTEXT_REG "
+ "0x%04X\n", reg);
+ return -EINVAL;
+ }
+ tmp = ((reg - CB_COLOR8_INFO) / 0x1c) + 8;
+ track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
+ if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
+ ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+ track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+ } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
+ ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+ track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+ }
+ break;
+ case CB_COLOR0_PITCH:
+ case CB_COLOR1_PITCH:
+ case CB_COLOR2_PITCH:
+ case CB_COLOR3_PITCH:
+ case CB_COLOR4_PITCH:
+ case CB_COLOR5_PITCH:
+ case CB_COLOR6_PITCH:
+ case CB_COLOR7_PITCH:
+ tmp = (reg - CB_COLOR0_PITCH) / 0x3c;
+ track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx);
+ track->cb_color_pitch_idx[tmp] = idx;
+ break;
+ case CB_COLOR8_PITCH:
+ case CB_COLOR9_PITCH:
+ case CB_COLOR10_PITCH:
+ case CB_COLOR11_PITCH:
+ tmp = ((reg - CB_COLOR8_PITCH) / 0x1c) + 8;
+ track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx);
+ track->cb_color_pitch_idx[tmp] = idx;
+ break;
+ case CB_COLOR0_SLICE:
+ case CB_COLOR1_SLICE:
+ case CB_COLOR2_SLICE:
+ case CB_COLOR3_SLICE:
+ case CB_COLOR4_SLICE:
+ case CB_COLOR5_SLICE:
+ case CB_COLOR6_SLICE:
+ case CB_COLOR7_SLICE:
+ tmp = (reg - CB_COLOR0_SLICE) / 0x3c;
+ track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx);
+ track->cb_color_slice_idx[tmp] = idx;
+ break;
+ case CB_COLOR8_SLICE:
+ case CB_COLOR9_SLICE:
+ case CB_COLOR10_SLICE:
+ case CB_COLOR11_SLICE:
+ tmp = ((reg - CB_COLOR8_SLICE) / 0x1c) + 8;
+ track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx);
+ track->cb_color_slice_idx[tmp] = idx;
+ break;
+ case CB_COLOR0_ATTRIB:
+ case CB_COLOR1_ATTRIB:
+ case CB_COLOR2_ATTRIB:
+ case CB_COLOR3_ATTRIB:
+ case CB_COLOR4_ATTRIB:
+ case CB_COLOR5_ATTRIB:
+ case CB_COLOR6_ATTRIB:
+ case CB_COLOR7_ATTRIB:
+ case CB_COLOR8_ATTRIB:
+ case CB_COLOR9_ATTRIB:
+ case CB_COLOR10_ATTRIB:
+ case CB_COLOR11_ATTRIB:
+ break;
+ case CB_COLOR0_DIM:
+ case CB_COLOR1_DIM:
+ case CB_COLOR2_DIM:
+ case CB_COLOR3_DIM:
+ case CB_COLOR4_DIM:
+ case CB_COLOR5_DIM:
+ case CB_COLOR6_DIM:
+ case CB_COLOR7_DIM:
+ tmp = (reg - CB_COLOR0_DIM) / 0x3c;
+ track->cb_color_dim[tmp] = radeon_get_ib_value(p, idx);
+ track->cb_color_dim_idx[tmp] = idx;
+ break;
+ case CB_COLOR8_DIM:
+ case CB_COLOR9_DIM:
+ case CB_COLOR10_DIM:
+ case CB_COLOR11_DIM:
+ tmp = ((reg - CB_COLOR8_DIM) / 0x1c) + 8;
+ track->cb_color_dim[tmp] = radeon_get_ib_value(p, idx);
+ track->cb_color_dim_idx[tmp] = idx;
+ break;
+ case CB_COLOR0_FMASK:
+ case CB_COLOR1_FMASK:
+ case CB_COLOR2_FMASK:
+ case CB_COLOR3_FMASK:
+ case CB_COLOR4_FMASK:
+ case CB_COLOR5_FMASK:
+ case CB_COLOR6_FMASK:
+ case CB_COLOR7_FMASK:
+ tmp = (reg - CB_COLOR0_FMASK) / 0x3c;
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
+ return -EINVAL;
+ }
+ ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+ track->cb_color_fmask_bo[tmp] = reloc->robj;
+ break;
+ case CB_COLOR0_CMASK:
+ case CB_COLOR1_CMASK:
+ case CB_COLOR2_CMASK:
+ case CB_COLOR3_CMASK:
+ case CB_COLOR4_CMASK:
+ case CB_COLOR5_CMASK:
+ case CB_COLOR6_CMASK:
+ case CB_COLOR7_CMASK:
+ tmp = (reg - CB_COLOR0_CMASK) / 0x3c;
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
+ return -EINVAL;
+ }
+ ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+ track->cb_color_cmask_bo[tmp] = reloc->robj;
+ break;
+ case CB_COLOR0_FMASK_SLICE:
+ case CB_COLOR1_FMASK_SLICE:
+ case CB_COLOR2_FMASK_SLICE:
+ case CB_COLOR3_FMASK_SLICE:
+ case CB_COLOR4_FMASK_SLICE:
+ case CB_COLOR5_FMASK_SLICE:
+ case CB_COLOR6_FMASK_SLICE:
+ case CB_COLOR7_FMASK_SLICE:
+ tmp = (reg - CB_COLOR0_FMASK_SLICE) / 0x3c;
+ track->cb_color_fmask_slice[tmp] = radeon_get_ib_value(p, idx);
+ break;
+ case CB_COLOR0_CMASK_SLICE:
+ case CB_COLOR1_CMASK_SLICE:
+ case CB_COLOR2_CMASK_SLICE:
+ case CB_COLOR3_CMASK_SLICE:
+ case CB_COLOR4_CMASK_SLICE:
+ case CB_COLOR5_CMASK_SLICE:
+ case CB_COLOR6_CMASK_SLICE:
+ case CB_COLOR7_CMASK_SLICE:
+ tmp = (reg - CB_COLOR0_CMASK_SLICE) / 0x3c;
+ track->cb_color_cmask_slice[tmp] = radeon_get_ib_value(p, idx);
+ break;
+ case CB_COLOR0_BASE:
+ case CB_COLOR1_BASE:
+ case CB_COLOR2_BASE:
+ case CB_COLOR3_BASE:
+ case CB_COLOR4_BASE:
+ case CB_COLOR5_BASE:
+ case CB_COLOR6_BASE:
+ case CB_COLOR7_BASE:
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ dev_warn(p->dev, "bad SET_CONTEXT_REG "
+ "0x%04X\n", reg);
+ return -EINVAL;
+ }
+ tmp = (reg - CB_COLOR0_BASE) / 0x3c;
+ track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);
+ ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+ track->cb_color_base_last[tmp] = ib[idx];
+ track->cb_color_bo[tmp] = reloc->robj;
+ break;
+ case CB_COLOR8_BASE:
+ case CB_COLOR9_BASE:
+ case CB_COLOR10_BASE:
+ case CB_COLOR11_BASE:
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ dev_warn(p->dev, "bad SET_CONTEXT_REG "
+ "0x%04X\n", reg);
+ return -EINVAL;
+ }
+ tmp = ((reg - CB_COLOR8_BASE) / 0x1c) + 8;
+ track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);
+ ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+ track->cb_color_base_last[tmp] = ib[idx];
+ track->cb_color_bo[tmp] = reloc->robj;
+ break;
+ case CB_IMMED0_BASE:
+ case CB_IMMED1_BASE:
+ case CB_IMMED2_BASE:
+ case CB_IMMED3_BASE:
+ case CB_IMMED4_BASE:
+ case CB_IMMED5_BASE:
+ case CB_IMMED6_BASE:
+ case CB_IMMED7_BASE:
+ case CB_IMMED8_BASE:
+ case CB_IMMED9_BASE:
+ case CB_IMMED10_BASE:
+ case CB_IMMED11_BASE:
+ case DB_HTILE_DATA_BASE:
+ case SQ_PGM_START_FS:
+ case SQ_PGM_START_ES:
+ case SQ_PGM_START_VS:
+ case SQ_PGM_START_GS:
+ case SQ_PGM_START_PS:
+ case SQ_PGM_START_HS:
+ case SQ_PGM_START_LS:
+ case GDS_ADDR_BASE:
+ case SQ_CONST_MEM_BASE:
+ case SQ_ALU_CONST_CACHE_GS_0:
+ case SQ_ALU_CONST_CACHE_GS_1:
+ case SQ_ALU_CONST_CACHE_GS_2:
+ case SQ_ALU_CONST_CACHE_GS_3:
+ case SQ_ALU_CONST_CACHE_GS_4:
+ case SQ_ALU_CONST_CACHE_GS_5:
+ case SQ_ALU_CONST_CACHE_GS_6:
+ case SQ_ALU_CONST_CACHE_GS_7:
+ case SQ_ALU_CONST_CACHE_GS_8:
+ case SQ_ALU_CONST_CACHE_GS_9:
+ case SQ_ALU_CONST_CACHE_GS_10:
+ case SQ_ALU_CONST_CACHE_GS_11:
+ case SQ_ALU_CONST_CACHE_GS_12:
+ case SQ_ALU_CONST_CACHE_GS_13:
+ case SQ_ALU_CONST_CACHE_GS_14:
+ case SQ_ALU_CONST_CACHE_GS_15:
+ case SQ_ALU_CONST_CACHE_PS_0:
+ case SQ_ALU_CONST_CACHE_PS_1:
+ case SQ_ALU_CONST_CACHE_PS_2:
+ case SQ_ALU_CONST_CACHE_PS_3:
+ case SQ_ALU_CONST_CACHE_PS_4:
+ case SQ_ALU_CONST_CACHE_PS_5:
+ case SQ_ALU_CONST_CACHE_PS_6:
+ case SQ_ALU_CONST_CACHE_PS_7:
+ case SQ_ALU_CONST_CACHE_PS_8:
+ case SQ_ALU_CONST_CACHE_PS_9:
+ case SQ_ALU_CONST_CACHE_PS_10:
+ case SQ_ALU_CONST_CACHE_PS_11:
+ case SQ_ALU_CONST_CACHE_PS_12:
+ case SQ_ALU_CONST_CACHE_PS_13:
+ case SQ_ALU_CONST_CACHE_PS_14:
+ case SQ_ALU_CONST_CACHE_PS_15:
+ case SQ_ALU_CONST_CACHE_VS_0:
+ case SQ_ALU_CONST_CACHE_VS_1:
+ case SQ_ALU_CONST_CACHE_VS_2:
+ case SQ_ALU_CONST_CACHE_VS_3:
+ case SQ_ALU_CONST_CACHE_VS_4:
+ case SQ_ALU_CONST_CACHE_VS_5:
+ case SQ_ALU_CONST_CACHE_VS_6:
+ case SQ_ALU_CONST_CACHE_VS_7:
+ case SQ_ALU_CONST_CACHE_VS_8:
+ case SQ_ALU_CONST_CACHE_VS_9:
+ case SQ_ALU_CONST_CACHE_VS_10:
+ case SQ_ALU_CONST_CACHE_VS_11:
+ case SQ_ALU_CONST_CACHE_VS_12:
+ case SQ_ALU_CONST_CACHE_VS_13:
+ case SQ_ALU_CONST_CACHE_VS_14:
+ case SQ_ALU_CONST_CACHE_VS_15:
+ case SQ_ALU_CONST_CACHE_HS_0:
+ case SQ_ALU_CONST_CACHE_HS_1:
+ case SQ_ALU_CONST_CACHE_HS_2:
+ case SQ_ALU_CONST_CACHE_HS_3:
+ case SQ_ALU_CONST_CACHE_HS_4:
+ case SQ_ALU_CONST_CACHE_HS_5:
+ case SQ_ALU_CONST_CACHE_HS_6:
+ case SQ_ALU_CONST_CACHE_HS_7:
+ case SQ_ALU_CONST_CACHE_HS_8:
+ case SQ_ALU_CONST_CACHE_HS_9:
+ case SQ_ALU_CONST_CACHE_HS_10:
+ case SQ_ALU_CONST_CACHE_HS_11:
+ case SQ_ALU_CONST_CACHE_HS_12:
+ case SQ_ALU_CONST_CACHE_HS_13:
+ case SQ_ALU_CONST_CACHE_HS_14:
+ case SQ_ALU_CONST_CACHE_HS_15:
+ case SQ_ALU_CONST_CACHE_LS_0:
+ case SQ_ALU_CONST_CACHE_LS_1:
+ case SQ_ALU_CONST_CACHE_LS_2:
+ case SQ_ALU_CONST_CACHE_LS_3:
+ case SQ_ALU_CONST_CACHE_LS_4:
+ case SQ_ALU_CONST_CACHE_LS_5:
+ case SQ_ALU_CONST_CACHE_LS_6:
+ case SQ_ALU_CONST_CACHE_LS_7:
+ case SQ_ALU_CONST_CACHE_LS_8:
+ case SQ_ALU_CONST_CACHE_LS_9:
+ case SQ_ALU_CONST_CACHE_LS_10:
+ case SQ_ALU_CONST_CACHE_LS_11:
+ case SQ_ALU_CONST_CACHE_LS_12:
+ case SQ_ALU_CONST_CACHE_LS_13:
+ case SQ_ALU_CONST_CACHE_LS_14:
+ case SQ_ALU_CONST_CACHE_LS_15:
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ dev_warn(p->dev, "bad SET_CONTEXT_REG "
+ "0x%04X\n", reg);
+ return -EINVAL;
+ }
+ ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+ break;
+ default:
+ dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/**
+ * evergreen_check_texture_resource() - check if register is authorized or not
+ * @p: parser structure holding parsing context
+ * @idx: index into the cs buffer
+ * @texture: texture's bo structure
+ * @mipmap: mipmap's bo structure
+ *
+ * This function will check that the resource has valid field and that
+ * the texture and mipmap bo object are big enough to cover this resource.
+ */
+static inline int evergreen_check_texture_resource(struct radeon_cs_parser *p, u32 idx,
+ struct radeon_bo *texture,
+ struct radeon_bo *mipmap)
+{
+ /* XXX fill in */
+ return 0;
+}
+
+static int evergreen_packet3_check(struct radeon_cs_parser *p,
+ struct radeon_cs_packet *pkt)
+{
+ struct radeon_cs_reloc *reloc;
+ struct evergreen_cs_track *track;
+ volatile u32 *ib;
+ unsigned idx;
+ unsigned i;
+ unsigned start_reg, end_reg, reg;
+ int r;
+ u32 idx_value;
+
+ track = (struct evergreen_cs_track *)p->track;
+ ib = p->ib->ptr;
+ idx = pkt->idx + 1;
+ idx_value = radeon_get_ib_value(p, idx);
+
+ switch (pkt->opcode) {
+ case PACKET3_CONTEXT_CONTROL:
+ if (pkt->count != 1) {
+ DRM_ERROR("bad CONTEXT_CONTROL\n");
+ return -EINVAL;
+ }
+ break;
+ case PACKET3_INDEX_TYPE:
+ case PACKET3_NUM_INSTANCES:
+ case PACKET3_CLEAR_STATE:
+ if (pkt->count) {
+ DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n");
+ return -EINVAL;
+ }
+ break;
+ case PACKET3_INDEX_BASE:
+ if (pkt->count != 1) {
+ DRM_ERROR("bad INDEX_BASE\n");
+ return -EINVAL;
+ }
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ DRM_ERROR("bad INDEX_BASE\n");
+ return -EINVAL;
+ }
+ ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+ ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+ r = evergreen_cs_track_check(p);
+ if (r) {
+ dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
+ return r;
+ }
+ break;
+ case PACKET3_DRAW_INDEX:
+ if (pkt->count != 3) {
+ DRM_ERROR("bad DRAW_INDEX\n");
+ return -EINVAL;
+ }
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ DRM_ERROR("bad DRAW_INDEX\n");
+ return -EINVAL;
+ }
+ ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+ ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+ r = evergreen_cs_track_check(p);
+ if (r) {
+ dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
+ return r;
+ }
+ break;
+ case PACKET3_DRAW_INDEX_2:
+ if (pkt->count != 4) {
+ DRM_ERROR("bad DRAW_INDEX_2\n");
+ return -EINVAL;
+ }
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ DRM_ERROR("bad DRAW_INDEX_2\n");
+ return -EINVAL;
+ }
+ ib[idx+1] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+ ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+ r = evergreen_cs_track_check(p);
+ if (r) {
+ dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
+ return r;
+ }
+ break;
+ case PACKET3_DRAW_INDEX_AUTO:
+ if (pkt->count != 1) {
+ DRM_ERROR("bad DRAW_INDEX_AUTO\n");
+ return -EINVAL;
+ }
+ r = evergreen_cs_track_check(p);
+ if (r) {
+ dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
+ return r;
+ }
+ break;
+ case PACKET3_DRAW_INDEX_MULTI_AUTO:
+ if (pkt->count != 2) {
+ DRM_ERROR("bad DRAW_INDEX_MULTI_AUTO\n");
+ return -EINVAL;
+ }
+ r = evergreen_cs_track_check(p);
+ if (r) {
+ dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
+ return r;
+ }
+ break;
+ case PACKET3_DRAW_INDEX_IMMD:
+ if (pkt->count < 2) {
+ DRM_ERROR("bad DRAW_INDEX_IMMD\n");
+ return -EINVAL;
+ }
+ r = evergreen_cs_track_check(p);
+ if (r) {
+ dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
+ return r;
+ }
+ break;
+ case PACKET3_DRAW_INDEX_OFFSET:
+ if (pkt->count != 2) {
+ DRM_ERROR("bad DRAW_INDEX_OFFSET\n");
+ return -EINVAL;
+ }
+ r = evergreen_cs_track_check(p);
+ if (r) {
+ dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
+ return r;
+ }
+ break;
+ case PACKET3_DRAW_INDEX_OFFSET_2:
+ if (pkt->count != 3) {
+ DRM_ERROR("bad DRAW_INDEX_OFFSET_2\n");
+ return -EINVAL;
+ }
+ r = evergreen_cs_track_check(p);
+ if (r) {
+ dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
+ return r;
+ }
+ break;
+ case PACKET3_WAIT_REG_MEM:
+ if (pkt->count != 5) {
+ DRM_ERROR("bad WAIT_REG_MEM\n");
+ return -EINVAL;
+ }
+ /* bit 4 is reg (0) or mem (1) */
+ if (idx_value & 0x10) {
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ DRM_ERROR("bad WAIT_REG_MEM\n");
+ return -EINVAL;
+ }
+ ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+ ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+ }
+ break;
+ case PACKET3_SURFACE_SYNC:
+ if (pkt->count != 3) {
+ DRM_ERROR("bad SURFACE_SYNC\n");
+ return -EINVAL;
+ }
+ /* 0xffffffff/0x0 is flush all cache flag */
+ if (radeon_get_ib_value(p, idx + 1) != 0xffffffff ||
+ radeon_get_ib_value(p, idx + 2) != 0) {
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ DRM_ERROR("bad SURFACE_SYNC\n");
+ return -EINVAL;
+ }
+ ib[idx+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+ }
+ break;
+ case PACKET3_EVENT_WRITE:
+ if (pkt->count != 2 && pkt->count != 0) {
+ DRM_ERROR("bad EVENT_WRITE\n");
+ return -EINVAL;
+ }
+ if (pkt->count) {
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ DRM_ERROR("bad EVENT_WRITE\n");
+ return -EINVAL;
+ }
+ ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+ ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+ }
+ break;
+ case PACKET3_EVENT_WRITE_EOP:
+ if (pkt->count != 4) {
+ DRM_ERROR("bad EVENT_WRITE_EOP\n");
+ return -EINVAL;
+ }
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ DRM_ERROR("bad EVENT_WRITE_EOP\n");
+ return -EINVAL;
+ }
+ ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+ ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+ break;
+ case PACKET3_EVENT_WRITE_EOS:
+ if (pkt->count != 3) {
+ DRM_ERROR("bad EVENT_WRITE_EOS\n");
+ return -EINVAL;
+ }
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ DRM_ERROR("bad EVENT_WRITE_EOS\n");
+ return -EINVAL;
+ }
+ ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+ ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+ break;
+ case PACKET3_SET_CONFIG_REG:
+ start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START;
+ end_reg = 4 * pkt->count + start_reg - 4;
+ if ((start_reg < PACKET3_SET_CONFIG_REG_START) ||
+ (start_reg >= PACKET3_SET_CONFIG_REG_END) ||
+ (end_reg >= PACKET3_SET_CONFIG_REG_END)) {
+ DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n");
+ return -EINVAL;
+ }
+ for (i = 0; i < pkt->count; i++) {
+ reg = start_reg + (4 * i);
+ r = evergreen_cs_check_reg(p, reg, idx+1+i);
+ if (r)
+ return r;
+ }
+ break;
+ case PACKET3_SET_CONTEXT_REG:
+ start_reg = (idx_value << 2) + PACKET3_SET_CONTEXT_REG_START;
+ end_reg = 4 * pkt->count + start_reg - 4;
+ if ((start_reg < PACKET3_SET_CONTEXT_REG_START) ||
+ (start_reg >= PACKET3_SET_CONTEXT_REG_END) ||
+ (end_reg >= PACKET3_SET_CONTEXT_REG_END)) {
+ DRM_ERROR("bad PACKET3_SET_CONTEXT_REG\n");
+ return -EINVAL;
+ }
+ for (i = 0; i < pkt->count; i++) {
+ reg = start_reg + (4 * i);
+ r = evergreen_cs_check_reg(p, reg, idx+1+i);
+ if (r)
+ return r;
+ }
+ break;
+ case PACKET3_SET_RESOURCE:
+ if (pkt->count % 8) {
+ DRM_ERROR("bad SET_RESOURCE\n");
+ return -EINVAL;
+ }
+ start_reg = (idx_value << 2) + PACKET3_SET_RESOURCE_START;
+ end_reg = 4 * pkt->count + start_reg - 4;
+ if ((start_reg < PACKET3_SET_RESOURCE_START) ||
+ (start_reg >= PACKET3_SET_RESOURCE_END) ||
+ (end_reg >= PACKET3_SET_RESOURCE_END)) {
+ DRM_ERROR("bad SET_RESOURCE\n");
+ return -EINVAL;
+ }
+ for (i = 0; i < (pkt->count / 8); i++) {
+ struct radeon_bo *texture, *mipmap;
+ u32 size, offset;
+
+ switch (G__SQ_CONSTANT_TYPE(radeon_get_ib_value(p, idx+1+(i*8)+7))) {
+ case SQ_TEX_VTX_VALID_TEXTURE:
+ /* tex base */
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ DRM_ERROR("bad SET_RESOURCE (tex)\n");
+ return -EINVAL;
+ }
+ ib[idx+1+(i*8)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+ if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+ ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+ else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+ ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+ texture = reloc->robj;
+ /* tex mip base */
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ DRM_ERROR("bad SET_RESOURCE (tex)\n");
+ return -EINVAL;
+ }
+ ib[idx+1+(i*8)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+ mipmap = reloc->robj;
+ r = evergreen_check_texture_resource(p, idx+1+(i*8),
+ texture, mipmap);
+ if (r)
+ return r;
+ break;
+ case SQ_TEX_VTX_VALID_BUFFER:
+ /* vtx base */
+ r = evergreen_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ DRM_ERROR("bad SET_RESOURCE (vtx)\n");
+ return -EINVAL;
+ }
+ offset = radeon_get_ib_value(p, idx+1+(i*8)+0);
+ size = radeon_get_ib_value(p, idx+1+(i*8)+1);
+ if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) {
+ /* force size to size of the buffer */
+ dev_warn(p->dev, "vbo resource seems too big for the bo\n");
+ ib[idx+1+(i*8)+1] = radeon_bo_size(reloc->robj);
+ }
+ ib[idx+1+(i*8)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff);
+ ib[idx+1+(i*8)+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+ break;
+ case SQ_TEX_VTX_INVALID_TEXTURE:
+ case SQ_TEX_VTX_INVALID_BUFFER:
+ default:
+ DRM_ERROR("bad SET_RESOURCE\n");
+ return -EINVAL;
+ }
+ }
+ break;
+ case PACKET3_SET_ALU_CONST:
+ /* XXX fix me ALU const buffers only */
+ break;
+ case PACKET3_SET_BOOL_CONST:
+ start_reg = (idx_value << 2) + PACKET3_SET_BOOL_CONST_START;
+ end_reg = 4 * pkt->count + start_reg - 4;
+ if ((start_reg < PACKET3_SET_BOOL_CONST_START) ||
+ (start_reg >= PACKET3_SET_BOOL_CONST_END) ||
+ (end_reg >= PACKET3_SET_BOOL_CONST_END)) {
+ DRM_ERROR("bad SET_BOOL_CONST\n");
+ return -EINVAL;
+ }
+ break;
+ case PACKET3_SET_LOOP_CONST:
+ start_reg = (idx_value << 2) + PACKET3_SET_LOOP_CONST_START;
+ end_reg = 4 * pkt->count + start_reg - 4;
+ if ((start_reg < PACKET3_SET_LOOP_CONST_START) ||
+ (start_reg >= PACKET3_SET_LOOP_CONST_END) ||
+ (end_reg >= PACKET3_SET_LOOP_CONST_END)) {
+ DRM_ERROR("bad SET_LOOP_CONST\n");
+ return -EINVAL;
+ }
+ break;
+ case PACKET3_SET_CTL_CONST:
+ start_reg = (idx_value << 2) + PACKET3_SET_CTL_CONST_START;
+ end_reg = 4 * pkt->count + start_reg - 4;
+ if ((start_reg < PACKET3_SET_CTL_CONST_START) ||
+ (start_reg >= PACKET3_SET_CTL_CONST_END) ||
+ (end_reg >= PACKET3_SET_CTL_CONST_END)) {
+ DRM_ERROR("bad SET_CTL_CONST\n");
+ return -EINVAL;
+ }
+ break;
+ case PACKET3_SET_SAMPLER:
+ if (pkt->count % 3) {
+ DRM_ERROR("bad SET_SAMPLER\n");
+ return -EINVAL;
+ }
+ start_reg = (idx_value << 2) + PACKET3_SET_SAMPLER_START;
+ end_reg = 4 * pkt->count + start_reg - 4;
+ if ((start_reg < PACKET3_SET_SAMPLER_START) ||
+ (start_reg >= PACKET3_SET_SAMPLER_END) ||
+ (end_reg >= PACKET3_SET_SAMPLER_END)) {
+ DRM_ERROR("bad SET_SAMPLER\n");
+ return -EINVAL;
+ }
+ break;
+ case PACKET3_NOP:
+ break;
+ default:
+ DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int evergreen_cs_parse(struct radeon_cs_parser *p)
+{
+ struct radeon_cs_packet pkt;
+ struct evergreen_cs_track *track;
+ int r;
+
+ if (p->track == NULL) {
+ /* initialize tracker, we are in kms */
+ track = kzalloc(sizeof(*track), GFP_KERNEL);
+ if (track == NULL)
+ return -ENOMEM;
+ evergreen_cs_track_init(track);
+ track->npipes = p->rdev->config.evergreen.tiling_npipes;
+ track->nbanks = p->rdev->config.evergreen.tiling_nbanks;
+ track->group_size = p->rdev->config.evergreen.tiling_group_size;
+ p->track = track;
+ }
+ do {
+ r = evergreen_cs_packet_parse(p, &pkt, p->idx);
+ if (r) {
+ kfree(p->track);
+ p->track = NULL;
+ return r;
+ }
+ p->idx += pkt.count + 2;
+ switch (pkt.type) {
+ case PACKET_TYPE0:
+ r = evergreen_cs_parse_packet0(p, &pkt);
+ break;
+ case PACKET_TYPE2:
+ break;
+ case PACKET_TYPE3:
+ r = evergreen_packet3_check(p, &pkt);
+ break;
+ default:
+ DRM_ERROR("Unknown packet type %d !\n", pkt.type);
+ kfree(p->track);
+ p->track = NULL;
+ return -EINVAL;
+ }
+ if (r) {
+ kfree(p->track);
+ p->track = NULL;
+ return r;
+ }
+ } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
+#if 0
+ for (r = 0; r < p->ib->length_dw; r++) {
+ printk(KERN_INFO "%05d 0x%08X\n", r, p->ib->ptr[r]);
+ mdelay(1);
+ }
+#endif
+ kfree(p->track);
+ p->track = NULL;
+ return 0;
+}
+
diff --git a/drivers/gpu/drm/radeon/evergreen_reg.h b/drivers/gpu/drm/radeon/evergreen_reg.h
index af86af8..e028c1c 100644
--- a/drivers/gpu/drm/radeon/evergreen_reg.h
+++ b/drivers/gpu/drm/radeon/evergreen_reg.h
@@ -151,6 +151,9 @@
#define EVERGREEN_DATA_FORMAT 0x6b00
# define EVERGREEN_INTERLEAVE_EN (1 << 0)
#define EVERGREEN_DESKTOP_HEIGHT 0x6b04
+#define EVERGREEN_VLINE_START_END 0x6b08
+#define EVERGREEN_VLINE_STATUS 0x6bb8
+# define EVERGREEN_VLINE_STAT (1 << 12)
#define EVERGREEN_VIEWPORT_START 0x6d70
#define EVERGREEN_VIEWPORT_SIZE 0x6d74
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h
index 93e9e17ad..a1cd621 100644
--- a/drivers/gpu/drm/radeon/evergreend.h
+++ b/drivers/gpu/drm/radeon/evergreend.h
@@ -218,6 +218,8 @@
#define CLIP_VTX_REORDER_ENA (1 << 0)
#define NUM_CLIP_SEQ(x) ((x) << 1)
#define PA_SC_AA_CONFIG 0x28C04
+#define MSAA_NUM_SAMPLES_SHIFT 0
+#define MSAA_NUM_SAMPLES_MASK 0x3
#define PA_SC_CLIPRECT_RULE 0x2820C
#define PA_SC_EDGERULE 0x28230
#define PA_SC_FIFO_SIZE 0x8BCC
@@ -553,4 +555,469 @@
# define DC_HPDx_RX_INT_TIMER(x) ((x) << 16)
# define DC_HPDx_EN (1 << 28)
+/*
+ * PM4
+ */
+#define PACKET_TYPE0 0
+#define PACKET_TYPE1 1
+#define PACKET_TYPE2 2
+#define PACKET_TYPE3 3
+
+#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3)
+#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF)
+#define CP_PACKET0_GET_REG(h) (((h) & 0xFFFF) << 2)
+#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
+#define PACKET0(reg, n) ((PACKET_TYPE0 << 30) | \
+ (((reg) >> 2) & 0xFFFF) | \
+ ((n) & 0x3FFF) << 16)
+#define CP_PACKET2 0x80000000
+#define PACKET2_PAD_SHIFT 0
+#define PACKET2_PAD_MASK (0x3fffffff << 0)
+
+#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v)))
+
+#define PACKET3(op, n) ((PACKET_TYPE3 << 30) | \
+ (((op) & 0xFF) << 8) | \
+ ((n) & 0x3FFF) << 16)
+
+/* Packet 3 types */
+#define PACKET3_NOP 0x10
+#define PACKET3_SET_BASE 0x11
+#define PACKET3_CLEAR_STATE 0x12
+#define PACKET3_INDIRECT_BUFFER_SIZE 0x13
+#define PACKET3_DISPATCH_DIRECT 0x15
+#define PACKET3_DISPATCH_INDIRECT 0x16
+#define PACKET3_INDIRECT_BUFFER_END 0x17
+#define PACKET3_SET_PREDICATION 0x20
+#define PACKET3_REG_RMW 0x21
+#define PACKET3_COND_EXEC 0x22
+#define PACKET3_PRED_EXEC 0x23
+#define PACKET3_DRAW_INDIRECT 0x24
+#define PACKET3_DRAW_INDEX_INDIRECT 0x25
+#define PACKET3_INDEX_BASE 0x26
+#define PACKET3_DRAW_INDEX_2 0x27
+#define PACKET3_CONTEXT_CONTROL 0x28
+#define PACKET3_DRAW_INDEX_OFFSET 0x29
+#define PACKET3_INDEX_TYPE 0x2A
+#define PACKET3_DRAW_INDEX 0x2B
+#define PACKET3_DRAW_INDEX_AUTO 0x2D
+#define PACKET3_DRAW_INDEX_IMMD 0x2E
+#define PACKET3_NUM_INSTANCES 0x2F
+#define PACKET3_DRAW_INDEX_MULTI_AUTO 0x30
+#define PACKET3_STRMOUT_BUFFER_UPDATE 0x34
+#define PACKET3_DRAW_INDEX_OFFSET_2 0x35
+#define PACKET3_DRAW_INDEX_MULTI_ELEMENT 0x36
+#define PACKET3_MEM_SEMAPHORE 0x39
+#define PACKET3_MPEG_INDEX 0x3A
+#define PACKET3_WAIT_REG_MEM 0x3C
+#define PACKET3_MEM_WRITE 0x3D
+#define PACKET3_INDIRECT_BUFFER 0x32
+#define PACKET3_SURFACE_SYNC 0x43
+# define PACKET3_CB0_DEST_BASE_ENA (1 << 6)
+# define PACKET3_CB1_DEST_BASE_ENA (1 << 7)
+# define PACKET3_CB2_DEST_BASE_ENA (1 << 8)
+# define PACKET3_CB3_DEST_BASE_ENA (1 << 9)
+# define PACKET3_CB4_DEST_BASE_ENA (1 << 10)
+# define PACKET3_CB5_DEST_BASE_ENA (1 << 11)
+# define PACKET3_CB6_DEST_BASE_ENA (1 << 12)
+# define PACKET3_CB7_DEST_BASE_ENA (1 << 13)
+# define PACKET3_DB_DEST_BASE_ENA (1 << 14)
+# define PACKET3_CB8_DEST_BASE_ENA (1 << 15)
+# define PACKET3_CB9_DEST_BASE_ENA (1 << 16)
+# define PACKET3_CB10_DEST_BASE_ENA (1 << 17)
+# define PACKET3_CB11_DEST_BASE_ENA (1 << 17)
+# define PACKET3_FULL_CACHE_ENA (1 << 20)
+# define PACKET3_TC_ACTION_ENA (1 << 23)
+# define PACKET3_VC_ACTION_ENA (1 << 24)
+# define PACKET3_CB_ACTION_ENA (1 << 25)
+# define PACKET3_DB_ACTION_ENA (1 << 26)
+# define PACKET3_SH_ACTION_ENA (1 << 27)
+# define PACKET3_SMX_ACTION_ENA (1 << 28)
+#define PACKET3_ME_INITIALIZE 0x44
+#define PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16)
+#define PACKET3_COND_WRITE 0x45
+#define PACKET3_EVENT_WRITE 0x46
+#define PACKET3_EVENT_WRITE_EOP 0x47
+#define PACKET3_EVENT_WRITE_EOS 0x48
+#define PACKET3_PREAMBLE_CNTL 0x4A
+#define PACKET3_RB_OFFSET 0x4B
+#define PACKET3_ALU_PS_CONST_BUFFER_COPY 0x4C
+#define PACKET3_ALU_VS_CONST_BUFFER_COPY 0x4D
+#define PACKET3_ALU_PS_CONST_UPDATE 0x4E
+#define PACKET3_ALU_VS_CONST_UPDATE 0x4F
+#define PACKET3_ONE_REG_WRITE 0x57
+#define PACKET3_SET_CONFIG_REG 0x68
+#define PACKET3_SET_CONFIG_REG_START 0x00008000
+#define PACKET3_SET_CONFIG_REG_END 0x0000ac00
+#define PACKET3_SET_CONTEXT_REG 0x69
+#define PACKET3_SET_CONTEXT_REG_START 0x00028000
+#define PACKET3_SET_CONTEXT_REG_END 0x00029000
+#define PACKET3_SET_ALU_CONST 0x6A
+/* alu const buffers only; no reg file */
+#define PACKET3_SET_BOOL_CONST 0x6B
+#define PACKET3_SET_BOOL_CONST_START 0x0003a500
+#define PACKET3_SET_BOOL_CONST_END 0x0003a518
+#define PACKET3_SET_LOOP_CONST 0x6C
+#define PACKET3_SET_LOOP_CONST_START 0x0003a200
+#define PACKET3_SET_LOOP_CONST_END 0x0003a500
+#define PACKET3_SET_RESOURCE 0x6D
+#define PACKET3_SET_RESOURCE_START 0x00030000
+#define PACKET3_SET_RESOURCE_END 0x00038000
+#define PACKET3_SET_SAMPLER 0x6E
+#define PACKET3_SET_SAMPLER_START 0x0003c000
+#define PACKET3_SET_SAMPLER_END 0x0003c600
+#define PACKET3_SET_CTL_CONST 0x6F
+#define PACKET3_SET_CTL_CONST_START 0x0003cff0
+#define PACKET3_SET_CTL_CONST_END 0x0003ff0c
+#define PACKET3_SET_RESOURCE_OFFSET 0x70
+#define PACKET3_SET_ALU_CONST_VS 0x71
+#define PACKET3_SET_ALU_CONST_DI 0x72
+#define PACKET3_SET_CONTEXT_REG_INDIRECT 0x73
+#define PACKET3_SET_RESOURCE_INDIRECT 0x74
+#define PACKET3_SET_APPEND_CNT 0x75
+
+#define SQ_RESOURCE_CONSTANT_WORD7_0 0x3001c
+#define S__SQ_CONSTANT_TYPE(x) (((x) & 3) << 30)
+#define G__SQ_CONSTANT_TYPE(x) (((x) >> 30) & 3)
+#define SQ_TEX_VTX_INVALID_TEXTURE 0x0
+#define SQ_TEX_VTX_INVALID_BUFFER 0x1
+#define SQ_TEX_VTX_VALID_TEXTURE 0x2
+#define SQ_TEX_VTX_VALID_BUFFER 0x3
+
+#define SQ_CONST_MEM_BASE 0x8df8
+
+#define SQ_ESGS_RING_SIZE 0x8c44
+#define SQ_GSVS_RING_SIZE 0x8c4c
+#define SQ_ESTMP_RING_SIZE 0x8c54
+#define SQ_GSTMP_RING_SIZE 0x8c5c
+#define SQ_VSTMP_RING_SIZE 0x8c64
+#define SQ_PSTMP_RING_SIZE 0x8c6c
+#define SQ_LSTMP_RING_SIZE 0x8e14
+#define SQ_HSTMP_RING_SIZE 0x8e1c
+#define VGT_TF_RING_SIZE 0x8988
+
+#define SQ_ESGS_RING_ITEMSIZE 0x28900
+#define SQ_GSVS_RING_ITEMSIZE 0x28904
+#define SQ_ESTMP_RING_ITEMSIZE 0x28908
+#define SQ_GSTMP_RING_ITEMSIZE 0x2890c
+#define SQ_VSTMP_RING_ITEMSIZE 0x28910
+#define SQ_PSTMP_RING_ITEMSIZE 0x28914
+#define SQ_LSTMP_RING_ITEMSIZE 0x28830
+#define SQ_HSTMP_RING_ITEMSIZE 0x28834
+
+#define SQ_GS_VERT_ITEMSIZE 0x2891c
+#define SQ_GS_VERT_ITEMSIZE_1 0x28920
+#define SQ_GS_VERT_ITEMSIZE_2 0x28924
+#define SQ_GS_VERT_ITEMSIZE_3 0x28928
+#define SQ_GSVS_RING_OFFSET_1 0x2892c
+#define SQ_GSVS_RING_OFFSET_2 0x28930
+#define SQ_GSVS_RING_OFFSET_3 0x28934
+
+#define SQ_ALU_CONST_BUFFER_SIZE_PS_0 0x28140
+#define SQ_ALU_CONST_BUFFER_SIZE_HS_0 0x28f80
+
+#define SQ_ALU_CONST_CACHE_PS_0 0x28940
+#define SQ_ALU_CONST_CACHE_PS_1 0x28944
+#define SQ_ALU_CONST_CACHE_PS_2 0x28948
+#define SQ_ALU_CONST_CACHE_PS_3 0x2894c
+#define SQ_ALU_CONST_CACHE_PS_4 0x28950
+#define SQ_ALU_CONST_CACHE_PS_5 0x28954
+#define SQ_ALU_CONST_CACHE_PS_6 0x28958
+#define SQ_ALU_CONST_CACHE_PS_7 0x2895c
+#define SQ_ALU_CONST_CACHE_PS_8 0x28960
+#define SQ_ALU_CONST_CACHE_PS_9 0x28964
+#define SQ_ALU_CONST_CACHE_PS_10 0x28968
+#define SQ_ALU_CONST_CACHE_PS_11 0x2896c
+#define SQ_ALU_CONST_CACHE_PS_12 0x28970
+#define SQ_ALU_CONST_CACHE_PS_13 0x28974
+#define SQ_ALU_CONST_CACHE_PS_14 0x28978
+#define SQ_ALU_CONST_CACHE_PS_15 0x2897c
+#define SQ_ALU_CONST_CACHE_VS_0 0x28980
+#define SQ_ALU_CONST_CACHE_VS_1 0x28984
+#define SQ_ALU_CONST_CACHE_VS_2 0x28988
+#define SQ_ALU_CONST_CACHE_VS_3 0x2898c
+#define SQ_ALU_CONST_CACHE_VS_4 0x28990
+#define SQ_ALU_CONST_CACHE_VS_5 0x28994
+#define SQ_ALU_CONST_CACHE_VS_6 0x28998
+#define SQ_ALU_CONST_CACHE_VS_7 0x2899c
+#define SQ_ALU_CONST_CACHE_VS_8 0x289a0
+#define SQ_ALU_CONST_CACHE_VS_9 0x289a4
+#define SQ_ALU_CONST_CACHE_VS_10 0x289a8
+#define SQ_ALU_CONST_CACHE_VS_11 0x289ac
+#define SQ_ALU_CONST_CACHE_VS_12 0x289b0
+#define SQ_ALU_CONST_CACHE_VS_13 0x289b4
+#define SQ_ALU_CONST_CACHE_VS_14 0x289b8
+#define SQ_ALU_CONST_CACHE_VS_15 0x289bc
+#define SQ_ALU_CONST_CACHE_GS_0 0x289c0
+#define SQ_ALU_CONST_CACHE_GS_1 0x289c4
+#define SQ_ALU_CONST_CACHE_GS_2 0x289c8
+#define SQ_ALU_CONST_CACHE_GS_3 0x289cc
+#define SQ_ALU_CONST_CACHE_GS_4 0x289d0
+#define SQ_ALU_CONST_CACHE_GS_5 0x289d4
+#define SQ_ALU_CONST_CACHE_GS_6 0x289d8
+#define SQ_ALU_CONST_CACHE_GS_7 0x289dc
+#define SQ_ALU_CONST_CACHE_GS_8 0x289e0
+#define SQ_ALU_CONST_CACHE_GS_9 0x289e4
+#define SQ_ALU_CONST_CACHE_GS_10 0x289e8
+#define SQ_ALU_CONST_CACHE_GS_11 0x289ec
+#define SQ_ALU_CONST_CACHE_GS_12 0x289f0
+#define SQ_ALU_CONST_CACHE_GS_13 0x289f4
+#define SQ_ALU_CONST_CACHE_GS_14 0x289f8
+#define SQ_ALU_CONST_CACHE_GS_15 0x289fc
+#define SQ_ALU_CONST_CACHE_HS_0 0x28f00
+#define SQ_ALU_CONST_CACHE_HS_1 0x28f04
+#define SQ_ALU_CONST_CACHE_HS_2 0x28f08
+#define SQ_ALU_CONST_CACHE_HS_3 0x28f0c
+#define SQ_ALU_CONST_CACHE_HS_4 0x28f10
+#define SQ_ALU_CONST_CACHE_HS_5 0x28f14
+#define SQ_ALU_CONST_CACHE_HS_6 0x28f18
+#define SQ_ALU_CONST_CACHE_HS_7 0x28f1c
+#define SQ_ALU_CONST_CACHE_HS_8 0x28f20
+#define SQ_ALU_CONST_CACHE_HS_9 0x28f24
+#define SQ_ALU_CONST_CACHE_HS_10 0x28f28
+#define SQ_ALU_CONST_CACHE_HS_11 0x28f2c
+#define SQ_ALU_CONST_CACHE_HS_12 0x28f30
+#define SQ_ALU_CONST_CACHE_HS_13 0x28f34
+#define SQ_ALU_CONST_CACHE_HS_14 0x28f38
+#define SQ_ALU_CONST_CACHE_HS_15 0x28f3c
+#define SQ_ALU_CONST_CACHE_LS_0 0x28f40
+#define SQ_ALU_CONST_CACHE_LS_1 0x28f44
+#define SQ_ALU_CONST_CACHE_LS_2 0x28f48
+#define SQ_ALU_CONST_CACHE_LS_3 0x28f4c
+#define SQ_ALU_CONST_CACHE_LS_4 0x28f50
+#define SQ_ALU_CONST_CACHE_LS_5 0x28f54
+#define SQ_ALU_CONST_CACHE_LS_6 0x28f58
+#define SQ_ALU_CONST_CACHE_LS_7 0x28f5c
+#define SQ_ALU_CONST_CACHE_LS_8 0x28f60
+#define SQ_ALU_CONST_CACHE_LS_9 0x28f64
+#define SQ_ALU_CONST_CACHE_LS_10 0x28f68
+#define SQ_ALU_CONST_CACHE_LS_11 0x28f6c
+#define SQ_ALU_CONST_CACHE_LS_12 0x28f70
+#define SQ_ALU_CONST_CACHE_LS_13 0x28f74
+#define SQ_ALU_CONST_CACHE_LS_14 0x28f78
+#define SQ_ALU_CONST_CACHE_LS_15 0x28f7c
+
+#define DB_DEPTH_CONTROL 0x28800
+#define DB_DEPTH_VIEW 0x28008
+#define DB_HTILE_DATA_BASE 0x28014
+#define DB_Z_INFO 0x28040
+# define Z_ARRAY_MODE(x) ((x) << 4)
+#define DB_STENCIL_INFO 0x28044
+#define DB_Z_READ_BASE 0x28048
+#define DB_STENCIL_READ_BASE 0x2804c
+#define DB_Z_WRITE_BASE 0x28050
+#define DB_STENCIL_WRITE_BASE 0x28054
+#define DB_DEPTH_SIZE 0x28058
+
+#define SQ_PGM_START_PS 0x28840
+#define SQ_PGM_START_VS 0x2885c
+#define SQ_PGM_START_GS 0x28874
+#define SQ_PGM_START_ES 0x2888c
+#define SQ_PGM_START_FS 0x288a4
+#define SQ_PGM_START_HS 0x288b8
+#define SQ_PGM_START_LS 0x288d0
+
+#define VGT_STRMOUT_CONFIG 0x28b94
+#define VGT_STRMOUT_BUFFER_CONFIG 0x28b98
+
+#define CB_TARGET_MASK 0x28238
+#define CB_SHADER_MASK 0x2823c
+
+#define GDS_ADDR_BASE 0x28720
+
+#define CB_IMMED0_BASE 0x28b9c
+#define CB_IMMED1_BASE 0x28ba0
+#define CB_IMMED2_BASE 0x28ba4
+#define CB_IMMED3_BASE 0x28ba8
+#define CB_IMMED4_BASE 0x28bac
+#define CB_IMMED5_BASE 0x28bb0
+#define CB_IMMED6_BASE 0x28bb4
+#define CB_IMMED7_BASE 0x28bb8
+#define CB_IMMED8_BASE 0x28bbc
+#define CB_IMMED9_BASE 0x28bc0
+#define CB_IMMED10_BASE 0x28bc4
+#define CB_IMMED11_BASE 0x28bc8
+
+/* all 12 CB blocks have these regs */
+#define CB_COLOR0_BASE 0x28c60
+#define CB_COLOR0_PITCH 0x28c64
+#define CB_COLOR0_SLICE 0x28c68
+#define CB_COLOR0_VIEW 0x28c6c
+#define CB_COLOR0_INFO 0x28c70
+# define CB_ARRAY_MODE(x) ((x) << 8)
+# define ARRAY_LINEAR_GENERAL 0
+# define ARRAY_LINEAR_ALIGNED 1
+# define ARRAY_1D_TILED_THIN1 2
+# define ARRAY_2D_TILED_THIN1 4
+#define CB_COLOR0_ATTRIB 0x28c74
+#define CB_COLOR0_DIM 0x28c78
+/* only CB0-7 blocks have these regs */
+#define CB_COLOR0_CMASK 0x28c7c
+#define CB_COLOR0_CMASK_SLICE 0x28c80
+#define CB_COLOR0_FMASK 0x28c84
+#define CB_COLOR0_FMASK_SLICE 0x28c88
+#define CB_COLOR0_CLEAR_WORD0 0x28c8c
+#define CB_COLOR0_CLEAR_WORD1 0x28c90
+#define CB_COLOR0_CLEAR_WORD2 0x28c94
+#define CB_COLOR0_CLEAR_WORD3 0x28c98
+
+#define CB_COLOR1_BASE 0x28c9c
+#define CB_COLOR2_BASE 0x28cd8
+#define CB_COLOR3_BASE 0x28d14
+#define CB_COLOR4_BASE 0x28d50
+#define CB_COLOR5_BASE 0x28d8c
+#define CB_COLOR6_BASE 0x28dc8
+#define CB_COLOR7_BASE 0x28e04
+#define CB_COLOR8_BASE 0x28e40
+#define CB_COLOR9_BASE 0x28e5c
+#define CB_COLOR10_BASE 0x28e78
+#define CB_COLOR11_BASE 0x28e94
+
+#define CB_COLOR1_PITCH 0x28ca0
+#define CB_COLOR2_PITCH 0x28cdc
+#define CB_COLOR3_PITCH 0x28d18
+#define CB_COLOR4_PITCH 0x28d54
+#define CB_COLOR5_PITCH 0x28d90
+#define CB_COLOR6_PITCH 0x28dcc
+#define CB_COLOR7_PITCH 0x28e08
+#define CB_COLOR8_PITCH 0x28e44
+#define CB_COLOR9_PITCH 0x28e60
+#define CB_COLOR10_PITCH 0x28e7c
+#define CB_COLOR11_PITCH 0x28e98
+
+#define CB_COLOR1_SLICE 0x28ca4
+#define CB_COLOR2_SLICE 0x28ce0
+#define CB_COLOR3_SLICE 0x28d1c
+#define CB_COLOR4_SLICE 0x28d58
+#define CB_COLOR5_SLICE 0x28d94
+#define CB_COLOR6_SLICE 0x28dd0
+#define CB_COLOR7_SLICE 0x28e0c
+#define CB_COLOR8_SLICE 0x28e48
+#define CB_COLOR9_SLICE 0x28e64
+#define CB_COLOR10_SLICE 0x28e80
+#define CB_COLOR11_SLICE 0x28e9c
+
+#define CB_COLOR1_VIEW 0x28ca8
+#define CB_COLOR2_VIEW 0x28ce4
+#define CB_COLOR3_VIEW 0x28d20
+#define CB_COLOR4_VIEW 0x28d5c
+#define CB_COLOR5_VIEW 0x28d98
+#define CB_COLOR6_VIEW 0x28dd4
+#define CB_COLOR7_VIEW 0x28e10
+#define CB_COLOR8_VIEW 0x28e4c
+#define CB_COLOR9_VIEW 0x28e68
+#define CB_COLOR10_VIEW 0x28e84
+#define CB_COLOR11_VIEW 0x28ea0
+
+#define CB_COLOR1_INFO 0x28cac
+#define CB_COLOR2_INFO 0x28ce8
+#define CB_COLOR3_INFO 0x28d24
+#define CB_COLOR4_INFO 0x28d60
+#define CB_COLOR5_INFO 0x28d9c
+#define CB_COLOR6_INFO 0x28dd8
+#define CB_COLOR7_INFO 0x28e14
+#define CB_COLOR8_INFO 0x28e50
+#define CB_COLOR9_INFO 0x28e6c
+#define CB_COLOR10_INFO 0x28e88
+#define CB_COLOR11_INFO 0x28ea4
+
+#define CB_COLOR1_ATTRIB 0x28cb0
+#define CB_COLOR2_ATTRIB 0x28cec
+#define CB_COLOR3_ATTRIB 0x28d28
+#define CB_COLOR4_ATTRIB 0x28d64
+#define CB_COLOR5_ATTRIB 0x28da0
+#define CB_COLOR6_ATTRIB 0x28ddc
+#define CB_COLOR7_ATTRIB 0x28e18
+#define CB_COLOR8_ATTRIB 0x28e54
+#define CB_COLOR9_ATTRIB 0x28e70
+#define CB_COLOR10_ATTRIB 0x28e8c
+#define CB_COLOR11_ATTRIB 0x28ea8
+
+#define CB_COLOR1_DIM 0x28cb4
+#define CB_COLOR2_DIM 0x28cf0
+#define CB_COLOR3_DIM 0x28d2c
+#define CB_COLOR4_DIM 0x28d68
+#define CB_COLOR5_DIM 0x28da4
+#define CB_COLOR6_DIM 0x28de0
+#define CB_COLOR7_DIM 0x28e1c
+#define CB_COLOR8_DIM 0x28e58
+#define CB_COLOR9_DIM 0x28e74
+#define CB_COLOR10_DIM 0x28e90
+#define CB_COLOR11_DIM 0x28eac
+
+#define CB_COLOR1_CMASK 0x28cb8
+#define CB_COLOR2_CMASK 0x28cf4
+#define CB_COLOR3_CMASK 0x28d30
+#define CB_COLOR4_CMASK 0x28d6c
+#define CB_COLOR5_CMASK 0x28da8
+#define CB_COLOR6_CMASK 0x28de4
+#define CB_COLOR7_CMASK 0x28e20
+
+#define CB_COLOR1_CMASK_SLICE 0x28cbc
+#define CB_COLOR2_CMASK_SLICE 0x28cf8
+#define CB_COLOR3_CMASK_SLICE 0x28d34
+#define CB_COLOR4_CMASK_SLICE 0x28d70
+#define CB_COLOR5_CMASK_SLICE 0x28dac
+#define CB_COLOR6_CMASK_SLICE 0x28de8
+#define CB_COLOR7_CMASK_SLICE 0x28e24
+
+#define CB_COLOR1_FMASK 0x28cc0
+#define CB_COLOR2_FMASK 0x28cfc
+#define CB_COLOR3_FMASK 0x28d38
+#define CB_COLOR4_FMASK 0x28d74
+#define CB_COLOR5_FMASK 0x28db0
+#define CB_COLOR6_FMASK 0x28dec
+#define CB_COLOR7_FMASK 0x28e28
+
+#define CB_COLOR1_FMASK_SLICE 0x28cc4
+#define CB_COLOR2_FMASK_SLICE 0x28d00
+#define CB_COLOR3_FMASK_SLICE 0x28d3c
+#define CB_COLOR4_FMASK_SLICE 0x28d78
+#define CB_COLOR5_FMASK_SLICE 0x28db4
+#define CB_COLOR6_FMASK_SLICE 0x28df0
+#define CB_COLOR7_FMASK_SLICE 0x28e2c
+
+#define CB_COLOR1_CLEAR_WORD0 0x28cc8
+#define CB_COLOR2_CLEAR_WORD0 0x28d04
+#define CB_COLOR3_CLEAR_WORD0 0x28d40
+#define CB_COLOR4_CLEAR_WORD0 0x28d7c
+#define CB_COLOR5_CLEAR_WORD0 0x28db8
+#define CB_COLOR6_CLEAR_WORD0 0x28df4
+#define CB_COLOR7_CLEAR_WORD0 0x28e30
+
+#define CB_COLOR1_CLEAR_WORD1 0x28ccc
+#define CB_COLOR2_CLEAR_WORD1 0x28d08
+#define CB_COLOR3_CLEAR_WORD1 0x28d44
+#define CB_COLOR4_CLEAR_WORD1 0x28d80
+#define CB_COLOR5_CLEAR_WORD1 0x28dbc
+#define CB_COLOR6_CLEAR_WORD1 0x28df8
+#define CB_COLOR7_CLEAR_WORD1 0x28e34
+
+#define CB_COLOR1_CLEAR_WORD2 0x28cd0
+#define CB_COLOR2_CLEAR_WORD2 0x28d0c
+#define CB_COLOR3_CLEAR_WORD2 0x28d48
+#define CB_COLOR4_CLEAR_WORD2 0x28d84
+#define CB_COLOR5_CLEAR_WORD2 0x28dc0
+#define CB_COLOR6_CLEAR_WORD2 0x28dfc
+#define CB_COLOR7_CLEAR_WORD2 0x28e38
+
+#define CB_COLOR1_CLEAR_WORD3 0x28cd4
+#define CB_COLOR2_CLEAR_WORD3 0x28d10
+#define CB_COLOR3_CLEAR_WORD3 0x28d4c
+#define CB_COLOR4_CLEAR_WORD3 0x28d88
+#define CB_COLOR5_CLEAR_WORD3 0x28dc4
+#define CB_COLOR6_CLEAR_WORD3 0x28e00
+#define CB_COLOR7_CLEAR_WORD3 0x28e3c
+
+#define SQ_TEX_RESOURCE_WORD0_0 0x30000
+#define SQ_TEX_RESOURCE_WORD1_0 0x30004
+# define TEX_ARRAY_MODE(x) ((x) << 28)
+#define SQ_TEX_RESOURCE_WORD2_0 0x30008
+#define SQ_TEX_RESOURCE_WORD3_0 0x3000C
+#define SQ_TEX_RESOURCE_WORD4_0 0x30010
+#define SQ_TEX_RESOURCE_WORD5_0 0x30014
+#define SQ_TEX_RESOURCE_WORD6_0 0x30018
+#define SQ_TEX_RESOURCE_WORD7_0 0x3001c
+
+
#endif
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index cc004b0..3970e62 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -162,6 +162,11 @@
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
+ /* mid sh */
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
/* high sh */
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
@@ -172,6 +177,11 @@
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
+ /* mid mh */
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
/* high mh */
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
@@ -1618,6 +1628,7 @@
case RADEON_TXFORMAT_RGB332:
case RADEON_TXFORMAT_Y8:
track->textures[i].cpp = 1;
+ track->textures[i].compress_format = R100_TRACK_COMP_NONE;
break;
case RADEON_TXFORMAT_AI88:
case RADEON_TXFORMAT_ARGB1555:
@@ -1629,12 +1640,14 @@
case RADEON_TXFORMAT_LDUDV655:
case RADEON_TXFORMAT_DUDV88:
track->textures[i].cpp = 2;
+ track->textures[i].compress_format = R100_TRACK_COMP_NONE;
break;
case RADEON_TXFORMAT_ARGB8888:
case RADEON_TXFORMAT_RGBA8888:
case RADEON_TXFORMAT_SHADOW32:
case RADEON_TXFORMAT_LDUDUV8888:
track->textures[i].cpp = 4;
+ track->textures[i].compress_format = R100_TRACK_COMP_NONE;
break;
case RADEON_TXFORMAT_DXT1:
track->textures[i].cpp = 1;
@@ -2594,12 +2607,6 @@
int surf_index = reg * 16;
int flags = 0;
- /* r100/r200 divide by 16 */
- if (rdev->family < CHIP_R300)
- flags = pitch / 16;
- else
- flags = pitch / 8;
-
if (rdev->family <= CHIP_RS200) {
if ((tiling_flags & (RADEON_TILING_MACRO|RADEON_TILING_MICRO))
== (RADEON_TILING_MACRO|RADEON_TILING_MICRO))
@@ -2623,6 +2630,20 @@
if (tiling_flags & RADEON_TILING_SWAP_32BIT)
flags |= RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP;
+ /* when we aren't tiling the pitch seems to needs to be furtherdivided down. - tested on power5 + rn50 server */
+ if (tiling_flags & (RADEON_TILING_SWAP_16BIT | RADEON_TILING_SWAP_32BIT)) {
+ if (!(tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO)))
+ if (ASIC_IS_RN50(rdev))
+ pitch /= 16;
+ }
+
+ /* r100/r200 divide by 16 */
+ if (rdev->family < CHIP_R300)
+ flags |= pitch / 16;
+ else
+ flags |= pitch / 8;
+
+
DRM_DEBUG("writing surface %d %d %x %x\n", reg, flags, offset, offset+obj_size-1);
WREG32(RADEON_SURFACE0_INFO + surf_index, flags);
WREG32(RADEON_SURFACE0_LOWER_BOUND + surf_index, offset);
@@ -3137,33 +3158,6 @@
DRM_ERROR("compress format %d\n", t->compress_format);
}
-static int r100_cs_track_cube(struct radeon_device *rdev,
- struct r100_cs_track *track, unsigned idx)
-{
- unsigned face, w, h;
- struct radeon_bo *cube_robj;
- unsigned long size;
-
- for (face = 0; face < 5; face++) {
- cube_robj = track->textures[idx].cube_info[face].robj;
- w = track->textures[idx].cube_info[face].width;
- h = track->textures[idx].cube_info[face].height;
-
- size = w * h;
- size *= track->textures[idx].cpp;
-
- size += track->textures[idx].cube_info[face].offset;
-
- if (size > radeon_bo_size(cube_robj)) {
- DRM_ERROR("Cube texture offset greater than object size %lu %lu\n",
- size, radeon_bo_size(cube_robj));
- r100_cs_track_texture_print(&track->textures[idx]);
- return -1;
- }
- }
- return 0;
-}
-
static int r100_track_compress_size(int compress_format, int w, int h)
{
int block_width, block_height, block_bytes;
@@ -3194,6 +3188,37 @@
return sz;
}
+static int r100_cs_track_cube(struct radeon_device *rdev,
+ struct r100_cs_track *track, unsigned idx)
+{
+ unsigned face, w, h;
+ struct radeon_bo *cube_robj;
+ unsigned long size;
+ unsigned compress_format = track->textures[idx].compress_format;
+
+ for (face = 0; face < 5; face++) {
+ cube_robj = track->textures[idx].cube_info[face].robj;
+ w = track->textures[idx].cube_info[face].width;
+ h = track->textures[idx].cube_info[face].height;
+
+ if (compress_format) {
+ size = r100_track_compress_size(compress_format, w, h);
+ } else
+ size = w * h;
+ size *= track->textures[idx].cpp;
+
+ size += track->textures[idx].cube_info[face].offset;
+
+ if (size > radeon_bo_size(cube_robj)) {
+ DRM_ERROR("Cube texture offset greater than object size %lu %lu\n",
+ size, radeon_bo_size(cube_robj));
+ r100_cs_track_texture_print(&track->textures[idx]);
+ return -1;
+ }
+ }
+ return 0;
+}
+
static int r100_cs_track_texture_check(struct radeon_device *rdev,
struct r100_cs_track *track)
{
diff --git a/drivers/gpu/drm/radeon/r200.c b/drivers/gpu/drm/radeon/r200.c
index 85617c3..0266d72 100644
--- a/drivers/gpu/drm/radeon/r200.c
+++ b/drivers/gpu/drm/radeon/r200.c
@@ -415,6 +415,8 @@
/* 2D, 3D, CUBE */
switch (tmp) {
case 0:
+ case 3:
+ case 4:
case 5:
case 6:
case 7:
@@ -450,6 +452,7 @@
case R200_TXFORMAT_RGB332:
case R200_TXFORMAT_Y8:
track->textures[i].cpp = 1;
+ track->textures[i].compress_format = R100_TRACK_COMP_NONE;
break;
case R200_TXFORMAT_AI88:
case R200_TXFORMAT_ARGB1555:
@@ -461,6 +464,7 @@
case R200_TXFORMAT_DVDU88:
case R200_TXFORMAT_AVYU4444:
track->textures[i].cpp = 2;
+ track->textures[i].compress_format = R100_TRACK_COMP_NONE;
break;
case R200_TXFORMAT_ARGB8888:
case R200_TXFORMAT_RGBA8888:
@@ -468,6 +472,7 @@
case R200_TXFORMAT_BGR111110:
case R200_TXFORMAT_LDVDU8888:
track->textures[i].cpp = 4;
+ track->textures[i].compress_format = R100_TRACK_COMP_NONE;
break;
case R200_TXFORMAT_DXT1:
track->textures[i].cpp = 1;
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index b2f9efe..7e81db5 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -881,6 +881,7 @@
case R300_TX_FORMAT_Y4X4:
case R300_TX_FORMAT_Z3Y3X2:
track->textures[i].cpp = 1;
+ track->textures[i].compress_format = R100_TRACK_COMP_NONE;
break;
case R300_TX_FORMAT_X16:
case R300_TX_FORMAT_Y8X8:
@@ -892,6 +893,7 @@
case R300_TX_FORMAT_B8G8_B8G8:
case R300_TX_FORMAT_G8R8_G8B8:
track->textures[i].cpp = 2;
+ track->textures[i].compress_format = R100_TRACK_COMP_NONE;
break;
case R300_TX_FORMAT_Y16X16:
case R300_TX_FORMAT_Z11Y11X10:
@@ -902,14 +904,17 @@
case R300_TX_FORMAT_FL_I32:
case 0x1e:
track->textures[i].cpp = 4;
+ track->textures[i].compress_format = R100_TRACK_COMP_NONE;
break;
case R300_TX_FORMAT_W16Z16Y16X16:
case R300_TX_FORMAT_FL_R16G16B16A16:
case R300_TX_FORMAT_FL_I32A32:
track->textures[i].cpp = 8;
+ track->textures[i].compress_format = R100_TRACK_COMP_NONE;
break;
case R300_TX_FORMAT_FL_R32G32B32A32:
track->textures[i].cpp = 16;
+ track->textures[i].compress_format = R100_TRACK_COMP_NONE;
break;
case R300_TX_FORMAT_DXT1:
track->textures[i].cpp = 1;
diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c
index 4415a5e..e6c8914 100644
--- a/drivers/gpu/drm/radeon/r420.c
+++ b/drivers/gpu/drm/radeon/r420.c
@@ -45,9 +45,14 @@
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0;
/* low sh */
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 0;
- rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1;
+ rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
+ /* mid sh */
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 1;
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
/* high sh */
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
@@ -58,6 +63,11 @@
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
+ /* mid mh */
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
/* high mh */
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 44e96a2..3d6645c 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -130,9 +130,14 @@
break;
}
}
- } else
- rdev->pm.requested_power_state_index =
- rdev->pm.current_power_state_index - 1;
+ } else {
+ if (rdev->pm.current_power_state_index == 0)
+ rdev->pm.requested_power_state_index =
+ rdev->pm.num_power_states - 1;
+ else
+ rdev->pm.requested_power_state_index =
+ rdev->pm.current_power_state_index - 1;
+ }
}
rdev->pm.requested_clock_mode_index = 0;
/* don't use the power state if crtcs are active and no display flag is set */
@@ -291,6 +296,11 @@
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
+ /* mid sh */
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
/* high sh */
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 1;
@@ -301,6 +311,11 @@
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
+ /* mid mh */
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
/* high mh */
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 1;
@@ -317,6 +332,11 @@
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
+ /* mid sh */
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 1;
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 1;
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
/* high sh */
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 1;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 2;
@@ -327,6 +347,11 @@
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 1;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
+ /* mid mh */
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 1;
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 1;
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
/* high mh */
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 1;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 2;
@@ -343,6 +368,11 @@
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 2;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
+ /* mid sh */
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 2;
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 2;
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
/* high sh */
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 2;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 3;
@@ -353,6 +383,11 @@
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
+ /* mid mh */
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 2;
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
/* high mh */
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 2;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 3;
@@ -375,6 +410,11 @@
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
+ /* mid sh */
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
/* high sh */
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
@@ -385,6 +425,11 @@
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
+ /* mid mh */
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
/* high mh */
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
@@ -401,7 +446,12 @@
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 1;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
- rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 1;
+ rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
+ /* mid sh */
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 1;
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 1;
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1;
/* high sh */
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 1;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 1;
@@ -411,7 +461,12 @@
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 2;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 2;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
- rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 1;
+ rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
+ /* low mh */
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 2;
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 2;
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1;
/* high mh */
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 2;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 2;
@@ -430,14 +485,30 @@
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx =
r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
- rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 1;
+ rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
} else {
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx =
r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx =
r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
- rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 1;
+ rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
+ }
+ /* mid sh */
+ if (rdev->flags & RADEON_IS_MOBILITY) {
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx =
+ r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx =
+ r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1;
+ } else {
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx =
+ r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx =
+ r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1;
}
/* high sh */
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx =
@@ -453,14 +524,30 @@
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx =
r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
- rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 2;
+ rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
} else {
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx =
r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx =
r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
- rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 1;
+ rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
+ }
+ /* mid mh */
+ if (rdev->flags & RADEON_IS_MOBILITY) {
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx =
+ r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx =
+ r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1;
+ } else {
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx =
+ r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx =
+ r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+ rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1;
}
/* high mh */
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx =
@@ -475,7 +562,18 @@
void r600_pm_misc(struct radeon_device *rdev)
{
+ int req_ps_idx = rdev->pm.requested_power_state_index;
+ int req_cm_idx = rdev->pm.requested_clock_mode_index;
+ struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx];
+ struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;
+ if ((voltage->type == VOLTAGE_SW) && voltage->voltage) {
+ if (voltage->voltage != rdev->pm.current_vddc) {
+ radeon_atom_set_voltage(rdev, voltage->voltage);
+ rdev->pm.current_vddc = voltage->voltage;
+ DRM_DEBUG("Setting: v: %d\n", voltage->voltage);
+ }
+ }
}
bool r600_gui_idle(struct radeon_device *rdev)
@@ -1004,7 +1102,7 @@
WREG32(MC_VM_FB_LOCATION, tmp);
WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8));
WREG32(HDP_NONSURFACE_INFO, (2 << 7));
- WREG32(HDP_NONSURFACE_SIZE, rdev->mc.mc_vram_size | 0x3FF);
+ WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF);
if (rdev->flags & RADEON_IS_AGP) {
WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 22);
WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 22);
@@ -1126,8 +1224,10 @@
rdev->mc.visible_vram_size = rdev->mc.aper_size;
r600_vram_gtt_location(rdev, &rdev->mc);
- if (rdev->flags & RADEON_IS_IGP)
+ if (rdev->flags & RADEON_IS_IGP) {
+ rs690_pm_info(rdev);
rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
+ }
radeon_update_bandwidth_info(rdev);
return 0;
}
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 669feb6..ab61aaa 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -176,6 +176,8 @@
void radeon_pm_resume(struct radeon_device *rdev);
void radeon_combios_get_power_modes(struct radeon_device *rdev);
void radeon_atombios_get_power_modes(struct radeon_device *rdev);
+void radeon_atom_set_voltage(struct radeon_device *rdev, u16 level);
+void rs690_pm_info(struct radeon_device *rdev);
/*
* Fences.
@@ -618,7 +620,8 @@
DYNPM_STATE_DISABLED,
DYNPM_STATE_MINIMUM,
DYNPM_STATE_PAUSED,
- DYNPM_STATE_ACTIVE
+ DYNPM_STATE_ACTIVE,
+ DYNPM_STATE_SUSPENDED,
};
enum radeon_dynpm_action {
DYNPM_ACTION_NONE,
@@ -647,15 +650,18 @@
PM_PROFILE_DEFAULT,
PM_PROFILE_AUTO,
PM_PROFILE_LOW,
+ PM_PROFILE_MID,
PM_PROFILE_HIGH,
};
#define PM_PROFILE_DEFAULT_IDX 0
#define PM_PROFILE_LOW_SH_IDX 1
-#define PM_PROFILE_HIGH_SH_IDX 2
-#define PM_PROFILE_LOW_MH_IDX 3
-#define PM_PROFILE_HIGH_MH_IDX 4
-#define PM_PROFILE_MAX 5
+#define PM_PROFILE_MID_SH_IDX 2
+#define PM_PROFILE_HIGH_SH_IDX 3
+#define PM_PROFILE_LOW_MH_IDX 4
+#define PM_PROFILE_MID_MH_IDX 5
+#define PM_PROFILE_HIGH_MH_IDX 6
+#define PM_PROFILE_MAX 7
struct radeon_pm_profile {
int dpms_off_ps_idx;
@@ -744,6 +750,7 @@
int default_power_state_index;
u32 current_sclk;
u32 current_mclk;
+ u32 current_vddc;
struct radeon_i2c_chan *i2c_bus;
/* selected pm method */
enum radeon_pm_method pm_method;
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index e57df08..646f96f 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -724,8 +724,8 @@
.irq_set = &evergreen_irq_set,
.irq_process = &evergreen_irq_process,
.get_vblank_counter = &evergreen_get_vblank_counter,
- .fence_ring_emit = NULL,
- .cs_parse = NULL,
+ .fence_ring_emit = &r600_fence_ring_emit,
+ .cs_parse = &evergreen_cs_parse,
.copy_blit = NULL,
.copy_dma = NULL,
.copy = NULL,
@@ -780,6 +780,13 @@
case CHIP_R423:
case CHIP_RV410:
rdev->asic = &r420_asic;
+ /* handle macs */
+ if (rdev->bios == NULL) {
+ rdev->asic->get_engine_clock = &radeon_legacy_get_engine_clock;
+ rdev->asic->set_engine_clock = &radeon_legacy_set_engine_clock;
+ rdev->asic->get_memory_clock = &radeon_legacy_get_memory_clock;
+ rdev->asic->set_memory_clock = NULL;
+ }
break;
case CHIP_RS400:
case CHIP_RS480:
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index 5c40a3d..c0bbaa6 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -314,6 +314,7 @@
u32 evergreen_get_vblank_counter(struct radeon_device *rdev, int crtc);
int evergreen_irq_set(struct radeon_device *rdev);
int evergreen_irq_process(struct radeon_device *rdev);
+extern int evergreen_cs_parse(struct radeon_cs_parser *p);
extern void evergreen_pm_misc(struct radeon_device *rdev);
extern void evergreen_pm_prepare(struct radeon_device *rdev);
extern void evergreen_pm_finish(struct radeon_device *rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index 24ea683..99bd8a9 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -1538,7 +1538,8 @@
rdev->pm.power_state[state_index].pcie_lanes =
power_info->info.asPowerPlayInfo[i].ucNumPciELanes;
misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo);
- if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
+ if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
+ (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
rdev->pm.power_state[state_index].clock_info[0].voltage.type =
VOLTAGE_GPIO;
rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
@@ -1605,7 +1606,8 @@
power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes;
misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo);
misc2 = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo2);
- if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
+ if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
+ (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
rdev->pm.power_state[state_index].clock_info[0].voltage.type =
VOLTAGE_GPIO;
rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
@@ -1679,7 +1681,8 @@
power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes;
misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo);
misc2 = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo2);
- if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
+ if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
+ (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
rdev->pm.power_state[state_index].clock_info[0].voltage.type =
VOLTAGE_GPIO;
rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
@@ -1755,9 +1758,22 @@
rdev->pm.power_state[state_index].misc2 = 0;
}
} else {
+ int fw_index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
+ uint8_t fw_frev, fw_crev;
+ uint16_t fw_data_offset, vddc = 0;
+ union firmware_info *firmware_info;
+ ATOM_PPLIB_THERMALCONTROLLER *controller = &power_info->info_4.sThermalController;
+
+ if (atom_parse_data_header(mode_info->atom_context, fw_index, NULL,
+ &fw_frev, &fw_crev, &fw_data_offset)) {
+ firmware_info =
+ (union firmware_info *)(mode_info->atom_context->bios +
+ fw_data_offset);
+ vddc = firmware_info->info_14.usBootUpVDDCVoltage;
+ }
+
/* add the i2c bus for thermal/fan chip */
/* no support for internal controller yet */
- ATOM_PPLIB_THERMALCONTROLLER *controller = &power_info->info_4.sThermalController;
if (controller->ucType > 0) {
if ((controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) ||
(controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) ||
@@ -1817,10 +1833,7 @@
/* skip invalid modes */
if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)
continue;
- rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
- VOLTAGE_SW;
- rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
- clock_info->usVDDC;
+ /* voltage works differently on IGPs */
mode_index++;
} else if (ASIC_IS_DCE4(rdev)) {
struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO *clock_info =
@@ -1904,6 +1917,16 @@
rdev->pm.default_power_state_index = state_index;
rdev->pm.power_state[state_index].default_clock_mode =
&rdev->pm.power_state[state_index].clock_info[mode_index - 1];
+ /* patch the table values with the default slck/mclk from firmware info */
+ for (j = 0; j < mode_index; j++) {
+ rdev->pm.power_state[state_index].clock_info[j].mclk =
+ rdev->clock.default_mclk;
+ rdev->pm.power_state[state_index].clock_info[j].sclk =
+ rdev->clock.default_sclk;
+ if (vddc)
+ rdev->pm.power_state[state_index].clock_info[j].voltage.voltage =
+ vddc;
+ }
}
state_index++;
}
@@ -1943,6 +1966,7 @@
rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
rdev->pm.current_clock_mode_index = 0;
+ rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
}
void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable)
@@ -1998,6 +2022,42 @@
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
}
+union set_voltage {
+ struct _SET_VOLTAGE_PS_ALLOCATION alloc;
+ struct _SET_VOLTAGE_PARAMETERS v1;
+ struct _SET_VOLTAGE_PARAMETERS_V2 v2;
+};
+
+void radeon_atom_set_voltage(struct radeon_device *rdev, u16 level)
+{
+ union set_voltage args;
+ int index = GetIndexIntoMasterTable(COMMAND, SetVoltage);
+ u8 frev, crev, volt_index = level;
+
+ if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+ return;
+
+ switch (crev) {
+ case 1:
+ args.v1.ucVoltageType = SET_VOLTAGE_TYPE_ASIC_VDDC;
+ args.v1.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_ALL_SOURCE;
+ args.v1.ucVoltageIndex = volt_index;
+ break;
+ case 2:
+ args.v2.ucVoltageType = SET_VOLTAGE_TYPE_ASIC_VDDC;
+ args.v2.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_SET_VOLTAGE;
+ args.v2.usVoltageLevel = cpu_to_le16(level);
+ break;
+ default:
+ DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+ return;
+ }
+
+ atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+
+
void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev)
{
struct radeon_device *rdev = dev->dev_private;
diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c
index fbba938..2c92137 100644
--- a/drivers/gpu/drm/radeon/radeon_bios.c
+++ b/drivers/gpu/drm/radeon/radeon_bios.c
@@ -48,6 +48,10 @@
resource_size_t vram_base;
resource_size_t size = 256 * 1024; /* ??? */
+ if (!(rdev->flags & RADEON_IS_IGP))
+ if (!radeon_card_posted(rdev))
+ return false;
+
rdev->bios = NULL;
vram_base = drm_get_resource_start(rdev->ddev, 0);
bios = ioremap(vram_base, size);
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index 7b5e10d..d1c1d8d 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -1411,6 +1411,11 @@
rdev->mode_info.connector_table = CT_IMAC_G5_ISIGHT;
} else
#endif /* CONFIG_PPC_PMAC */
+#ifdef CONFIG_PPC64
+ if (ASIC_IS_RN50(rdev))
+ rdev->mode_info.connector_table = CT_RN50_POWER;
+ else
+#endif
rdev->mode_info.connector_table = CT_GENERIC;
}
@@ -1853,6 +1858,33 @@
CONNECTOR_OBJECT_ID_SVIDEO,
&hpd);
break;
+ case CT_RN50_POWER:
+ DRM_INFO("Connector Table: %d (rn50-power)\n",
+ rdev->mode_info.connector_table);
+ /* VGA - primary dac */
+ ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
+ hpd.hpd = RADEON_HPD_NONE;
+ radeon_add_legacy_encoder(dev,
+ radeon_get_encoder_id(dev,
+ ATOM_DEVICE_CRT1_SUPPORT,
+ 1),
+ ATOM_DEVICE_CRT1_SUPPORT);
+ radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_CRT1_SUPPORT,
+ DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
+ CONNECTOR_OBJECT_ID_VGA,
+ &hpd);
+ ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC);
+ hpd.hpd = RADEON_HPD_NONE;
+ radeon_add_legacy_encoder(dev,
+ radeon_get_encoder_id(dev,
+ ATOM_DEVICE_CRT2_SUPPORT,
+ 2),
+ ATOM_DEVICE_CRT2_SUPPORT);
+ radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT,
+ DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
+ CONNECTOR_OBJECT_ID_VGA,
+ &hpd);
+ break;
default:
DRM_INFO("Connector table: %d (invalid)\n",
rdev->mode_info.connector_table);
@@ -1906,15 +1938,6 @@
return false;
}
- /* Some RV100 cards with 2 VGA ports show up with DVI+VGA */
- if (dev->pdev->device == 0x5159 &&
- dev->pdev->subsystem_vendor == 0x1002 &&
- dev->pdev->subsystem_device == 0x013a) {
- if (*legacy_connector == CONNECTOR_DVI_I_LEGACY)
- *legacy_connector = CONNECTOR_CRT_LEGACY;
-
- }
-
/* X300 card with extra non-existent DVI port */
if (dev->pdev->device == 0x5B60 &&
dev->pdev->subsystem_vendor == 0x17af &&
@@ -2026,6 +2049,7 @@
combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC);
break;
default:
+ ddc_i2c.valid = false;
break;
}
@@ -2339,6 +2363,7 @@
if (RBIOS8(tv_info + 6) == 'T') {
if (radeon_apply_legacy_tv_quirks(dev)) {
hpd.hpd = RADEON_HPD_NONE;
+ ddc_i2c.valid = false;
radeon_add_legacy_encoder(dev,
radeon_get_encoder_id
(dev,
@@ -2454,7 +2479,12 @@
rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk;
rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk;
rdev->pm.power_state[state_index].default_clock_mode = &rdev->pm.power_state[state_index].clock_info[0];
- rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
+ if ((state_index > 0) &&
+ (rdev->pm.power_state[0].clock_info[0].voltage.type == VOLTAGE_GPIO))
+ rdev->pm.power_state[state_index].clock_info[0].voltage =
+ rdev->pm.power_state[0].clock_info[0].voltage;
+ else
+ rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
rdev->pm.power_state[state_index].pcie_lanes = 16;
rdev->pm.power_state[state_index].flags = 0;
rdev->pm.default_power_state_index = state_index;
@@ -3012,6 +3042,14 @@
combios_write_ram_size(dev);
}
+ /* quirk for rs4xx HP nx6125 laptop to make it resume
+ * - it hangs on resume inside the dynclk 1 table.
+ */
+ if (rdev->family == CHIP_RS480 &&
+ rdev->pdev->subsystem_vendor == 0x103c &&
+ rdev->pdev->subsystem_device == 0x308b)
+ return;
+
/* DYN CLK 1 */
table = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE);
if (table)
diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c
index b7023ff..4eb67c0 100644
--- a/drivers/gpu/drm/radeon/radeon_cursor.c
+++ b/drivers/gpu/drm/radeon/radeon_cursor.c
@@ -194,7 +194,7 @@
fail:
drm_gem_object_unreference_unlocked(obj);
- return 0;
+ return ret;
}
int radeon_crtc_cursor_move(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index fdc3fdf7..5f31731 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -546,8 +546,10 @@
/* don't suspend or resume card normally */
rdev->powered_down = false;
radeon_resume_kms(dev);
+ drm_kms_helper_poll_enable(dev);
} else {
printk(KERN_INFO "radeon: switched off\n");
+ drm_kms_helper_poll_disable(dev);
radeon_suspend_kms(dev, pmm);
/* don't suspend or resume card normally */
rdev->powered_down = true;
@@ -711,6 +713,7 @@
{
struct radeon_device *rdev;
struct drm_crtc *crtc;
+ struct drm_connector *connector;
int r;
if (dev == NULL || dev->dev_private == NULL) {
@@ -723,6 +726,12 @@
if (rdev->powered_down)
return 0;
+
+ /* turn off display hw */
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
+ }
+
/* unpin the front buffers */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb);
@@ -770,6 +779,7 @@
int radeon_resume_kms(struct drm_device *dev)
{
+ struct drm_connector *connector;
struct radeon_device *rdev = dev->dev_private;
if (rdev->powered_down)
@@ -788,6 +798,12 @@
radeon_resume(rdev);
radeon_pm_resume(rdev);
radeon_restore_bios_scratch_regs(rdev);
+
+ /* turn on display hw */
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
+ }
+
radeon_fbdev_set_suspend(rdev, 0);
release_console_sem();
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 1006549..8154cdf 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -284,8 +284,7 @@
"eDP",
};
-static const char *hpd_names[7] = {
- "NONE",
+static const char *hpd_names[6] = {
"HPD1",
"HPD2",
"HPD3",
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 902d173..e166fe4 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -45,9 +45,10 @@
* - 2.2.0 - add r6xx/r7xx const buffer support
* - 2.3.0 - add MSPOS + 3D texture + r500 VAP regs
* - 2.4.0 - add crtc id query
+ * - 2.5.0 - add get accel 2 to work around ddx breakage for evergreen
*/
#define KMS_DRIVER_MAJOR 2
-#define KMS_DRIVER_MINOR 4
+#define KMS_DRIVER_MINOR 5
#define KMS_DRIVER_PATCHLEVEL 0
int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
int radeon_driver_unload_kms(struct drm_device *dev);
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c
index 1ebb100..e0b30b2 100644
--- a/drivers/gpu/drm/radeon/radeon_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_encoders.c
@@ -1072,6 +1072,8 @@
if (is_dig) {
switch (mode) {
case DRM_MODE_DPMS_ON:
+ if (!ASIC_IS_DCE4(rdev))
+ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
@@ -1079,8 +1081,6 @@
if (ASIC_IS_DCE4(rdev))
atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON);
}
- if (!ASIC_IS_DCE4(rdev))
- atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
break;
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index e192acf..dc1634b 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -363,6 +363,7 @@
{
struct radeon_fbdev *rfbdev;
int bpp_sel = 32;
+ int ret;
/* select 8 bpp console on RN50 or 16MB cards */
if (ASIC_IS_RN50(rdev) || rdev->mc.real_vram_size <= (32*1024*1024))
@@ -376,9 +377,14 @@
rdev->mode_info.rfbdev = rfbdev;
rfbdev->helper.funcs = &radeon_fb_helper_funcs;
- drm_fb_helper_init(rdev->ddev, &rfbdev->helper,
- rdev->num_crtc,
- RADEONFB_CONN_LIMIT);
+ ret = drm_fb_helper_init(rdev->ddev, &rfbdev->helper,
+ rdev->num_crtc,
+ RADEONFB_CONN_LIMIT);
+ if (ret) {
+ kfree(rfbdev);
+ return ret;
+ }
+
drm_fb_helper_single_add_all_connectors(&rfbdev->helper);
drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel);
return 0;
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index 0406835..6a70c0d 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -118,7 +118,11 @@
value = rdev->num_z_pipes;
break;
case RADEON_INFO_ACCEL_WORKING:
- value = rdev->accel_working;
+ /* xf86-video-ati 6.13.0 relies on this being false for evergreen */
+ if ((rdev->family >= CHIP_CEDAR) && (rdev->family <= CHIP_HEMLOCK))
+ value = false;
+ else
+ value = rdev->accel_working;
break;
case RADEON_INFO_CRTC_FROM_ID:
for (i = 0, found = 0; i < rdev->num_crtc; i++) {
@@ -134,6 +138,9 @@
return -EINVAL;
}
break;
+ case RADEON_INFO_ACCEL_WORKING2:
+ value = rdev->accel_working;
+ break;
default:
DRM_DEBUG("Invalid request %d\n", info->request);
return -EINVAL;
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
index 5a13b3e..bad77f4 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
@@ -928,16 +928,14 @@
if (ASIC_IS_R300(rdev)) {
gpiopad_a = RREG32(RADEON_GPIOPAD_A) | 1;
disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
- }
-
- if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev))
- disp_tv_out_cntl = RREG32(RADEON_DISP_TV_OUT_CNTL);
- else
+ } else if (rdev->family != CHIP_R200)
disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
-
- if (rdev->family == CHIP_R200)
+ else if (rdev->family == CHIP_R200)
fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
+ if (rdev->family >= CHIP_R200)
+ disp_tv_out_cntl = RREG32(RADEON_DISP_TV_OUT_CNTL);
+
if (is_tv) {
uint32_t dac_cntl;
@@ -1002,15 +1000,13 @@
if (ASIC_IS_R300(rdev)) {
WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
- }
+ } else if (rdev->family != CHIP_R200)
+ WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
+ else if (rdev->family == CHIP_R200)
+ WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
if (rdev->family >= CHIP_R200)
WREG32(RADEON_DISP_TV_OUT_CNTL, disp_tv_out_cntl);
- else
- WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
-
- if (rdev->family == CHIP_R200)
- WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
if (is_tv)
radeon_legacy_tv_mode_set(encoder, mode, adjusted_mode);
@@ -1168,6 +1164,17 @@
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
bool color = true;
+ struct drm_crtc *crtc;
+
+ /* find out if crtc2 is in use or if this encoder is using it */
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+ if ((radeon_crtc->crtc_id == 1) && crtc->enabled) {
+ if (encoder->crtc != crtc) {
+ return connector_status_disconnected;
+ }
+ }
+ }
if (connector->connector_type == DRM_MODE_CONNECTOR_SVIDEO ||
connector->connector_type == DRM_MODE_CONNECTOR_Composite ||
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 67358baf..95696aa 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -206,6 +206,7 @@
CT_MINI_INTERNAL,
CT_IMAC_G5_ISIGHT,
CT_EMAC,
+ CT_RN50_POWER,
};
enum radeon_dvo_chip {
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
index a8d162c..115d26b 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -33,6 +33,14 @@
#define RADEON_WAIT_VBLANK_TIMEOUT 200
#define RADEON_WAIT_IDLE_TIMEOUT 200
+static const char *radeon_pm_state_type_name[5] = {
+ "Default",
+ "Powersave",
+ "Battery",
+ "Balanced",
+ "Performance",
+};
+
static void radeon_dynpm_idle_work_handler(struct work_struct *work);
static int radeon_debugfs_pm_init(struct radeon_device *rdev);
static bool radeon_pm_in_vbl(struct radeon_device *rdev);
@@ -84,9 +92,9 @@
rdev->pm.profile_index = PM_PROFILE_HIGH_SH_IDX;
} else {
if (rdev->pm.active_crtc_count > 1)
- rdev->pm.profile_index = PM_PROFILE_LOW_MH_IDX;
+ rdev->pm.profile_index = PM_PROFILE_MID_MH_IDX;
else
- rdev->pm.profile_index = PM_PROFILE_LOW_SH_IDX;
+ rdev->pm.profile_index = PM_PROFILE_MID_SH_IDX;
}
break;
case PM_PROFILE_LOW:
@@ -95,6 +103,12 @@
else
rdev->pm.profile_index = PM_PROFILE_LOW_SH_IDX;
break;
+ case PM_PROFILE_MID:
+ if (rdev->pm.active_crtc_count > 1)
+ rdev->pm.profile_index = PM_PROFILE_MID_MH_IDX;
+ else
+ rdev->pm.profile_index = PM_PROFILE_MID_SH_IDX;
+ break;
case PM_PROFILE_HIGH:
if (rdev->pm.active_crtc_count > 1)
rdev->pm.profile_index = PM_PROFILE_HIGH_MH_IDX;
@@ -127,15 +141,6 @@
if (bo->tbo.mem.mem_type == TTM_PL_VRAM)
ttm_bo_unmap_virtual(&bo->tbo);
}
-
- if (rdev->gart.table.vram.robj)
- ttm_bo_unmap_virtual(&rdev->gart.table.vram.robj->tbo);
-
- if (rdev->stollen_vga_memory)
- ttm_bo_unmap_virtual(&rdev->stollen_vga_memory->tbo);
-
- if (rdev->r600_blit.shader_obj)
- ttm_bo_unmap_virtual(&rdev->r600_blit.shader_obj->tbo);
}
static void radeon_sync_with_vblank(struct radeon_device *rdev)
@@ -151,6 +156,7 @@
static void radeon_set_power_state(struct radeon_device *rdev)
{
u32 sclk, mclk;
+ bool misc_after = false;
if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) &&
(rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index))
@@ -167,55 +173,47 @@
if (mclk > rdev->clock.default_mclk)
mclk = rdev->clock.default_mclk;
- /* voltage, pcie lanes, etc.*/
- radeon_pm_misc(rdev);
+ /* upvolt before raising clocks, downvolt after lowering clocks */
+ if (sclk < rdev->pm.current_sclk)
+ misc_after = true;
+
+ radeon_sync_with_vblank(rdev);
if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
- radeon_sync_with_vblank(rdev);
-
if (!radeon_pm_in_vbl(rdev))
return;
-
- radeon_pm_prepare(rdev);
- /* set engine clock */
- if (sclk != rdev->pm.current_sclk) {
- radeon_pm_debug_check_in_vbl(rdev, false);
- radeon_set_engine_clock(rdev, sclk);
- radeon_pm_debug_check_in_vbl(rdev, true);
- rdev->pm.current_sclk = sclk;
- DRM_DEBUG("Setting: e: %d\n", sclk);
- }
-
- /* set memory clock */
- if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
- radeon_pm_debug_check_in_vbl(rdev, false);
- radeon_set_memory_clock(rdev, mclk);
- radeon_pm_debug_check_in_vbl(rdev, true);
- rdev->pm.current_mclk = mclk;
- DRM_DEBUG("Setting: m: %d\n", mclk);
- }
- radeon_pm_finish(rdev);
- } else {
- /* set engine clock */
- if (sclk != rdev->pm.current_sclk) {
- radeon_sync_with_vblank(rdev);
- radeon_pm_prepare(rdev);
- radeon_set_engine_clock(rdev, sclk);
- radeon_pm_finish(rdev);
- rdev->pm.current_sclk = sclk;
- DRM_DEBUG("Setting: e: %d\n", sclk);
- }
- /* set memory clock */
- if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
- radeon_sync_with_vblank(rdev);
- radeon_pm_prepare(rdev);
- radeon_set_memory_clock(rdev, mclk);
- radeon_pm_finish(rdev);
- rdev->pm.current_mclk = mclk;
- DRM_DEBUG("Setting: m: %d\n", mclk);
- }
}
+ radeon_pm_prepare(rdev);
+
+ if (!misc_after)
+ /* voltage, pcie lanes, etc.*/
+ radeon_pm_misc(rdev);
+
+ /* set engine clock */
+ if (sclk != rdev->pm.current_sclk) {
+ radeon_pm_debug_check_in_vbl(rdev, false);
+ radeon_set_engine_clock(rdev, sclk);
+ radeon_pm_debug_check_in_vbl(rdev, true);
+ rdev->pm.current_sclk = sclk;
+ DRM_DEBUG("Setting: e: %d\n", sclk);
+ }
+
+ /* set memory clock */
+ if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
+ radeon_pm_debug_check_in_vbl(rdev, false);
+ radeon_set_memory_clock(rdev, mclk);
+ radeon_pm_debug_check_in_vbl(rdev, true);
+ rdev->pm.current_mclk = mclk;
+ DRM_DEBUG("Setting: m: %d\n", mclk);
+ }
+
+ if (misc_after)
+ /* voltage, pcie lanes, etc.*/
+ radeon_pm_misc(rdev);
+
+ radeon_pm_finish(rdev);
+
rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index;
rdev->pm.current_clock_mode_index = rdev->pm.requested_clock_mode_index;
} else
@@ -288,6 +286,42 @@
mutex_unlock(&rdev->ddev->struct_mutex);
}
+static void radeon_pm_print_states(struct radeon_device *rdev)
+{
+ int i, j;
+ struct radeon_power_state *power_state;
+ struct radeon_pm_clock_info *clock_info;
+
+ DRM_DEBUG("%d Power State(s)\n", rdev->pm.num_power_states);
+ for (i = 0; i < rdev->pm.num_power_states; i++) {
+ power_state = &rdev->pm.power_state[i];
+ DRM_DEBUG("State %d: %s\n", i,
+ radeon_pm_state_type_name[power_state->type]);
+ if (i == rdev->pm.default_power_state_index)
+ DRM_DEBUG("\tDefault");
+ if ((rdev->flags & RADEON_IS_PCIE) && !(rdev->flags & RADEON_IS_IGP))
+ DRM_DEBUG("\t%d PCIE Lanes\n", power_state->pcie_lanes);
+ if (power_state->flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY)
+ DRM_DEBUG("\tSingle display only\n");
+ DRM_DEBUG("\t%d Clock Mode(s)\n", power_state->num_clock_modes);
+ for (j = 0; j < power_state->num_clock_modes; j++) {
+ clock_info = &(power_state->clock_info[j]);
+ if (rdev->flags & RADEON_IS_IGP)
+ DRM_DEBUG("\t\t%d e: %d%s\n",
+ j,
+ clock_info->sclk * 10,
+ clock_info->flags & RADEON_PM_MODE_NO_DISPLAY ? "\tNo display only" : "");
+ else
+ DRM_DEBUG("\t\t%d e: %d\tm: %d\tv: %d%s\n",
+ j,
+ clock_info->sclk * 10,
+ clock_info->mclk * 10,
+ clock_info->voltage.voltage,
+ clock_info->flags & RADEON_PM_MODE_NO_DISPLAY ? "\tNo display only" : "");
+ }
+ }
+}
+
static ssize_t radeon_get_pm_profile(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -318,6 +352,8 @@
rdev->pm.profile = PM_PROFILE_AUTO;
else if (strncmp("low", buf, strlen("low")) == 0)
rdev->pm.profile = PM_PROFILE_LOW;
+ else if (strncmp("mid", buf, strlen("mid")) == 0)
+ rdev->pm.profile = PM_PROFILE_MID;
else if (strncmp("high", buf, strlen("high")) == 0)
rdev->pm.profile = PM_PROFILE_HIGH;
else {
@@ -361,13 +397,20 @@
rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
mutex_unlock(&rdev->pm.mutex);
} else if (strncmp("profile", buf, strlen("profile")) == 0) {
+ bool flush_wq = false;
+
mutex_lock(&rdev->pm.mutex);
- rdev->pm.pm_method = PM_METHOD_PROFILE;
+ if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+ cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+ flush_wq = true;
+ }
/* disable dynpm */
rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
- cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+ rdev->pm.pm_method = PM_METHOD_PROFILE;
mutex_unlock(&rdev->pm.mutex);
+ if (flush_wq)
+ flush_workqueue(rdev->wq);
} else {
DRM_ERROR("invalid power method!\n");
goto fail;
@@ -382,17 +425,36 @@
void radeon_pm_suspend(struct radeon_device *rdev)
{
+ bool flush_wq = false;
+
mutex_lock(&rdev->pm.mutex);
- cancel_delayed_work(&rdev->pm.dynpm_idle_work);
- rdev->pm.current_power_state_index = -1;
- rdev->pm.current_clock_mode_index = -1;
- rdev->pm.current_sclk = 0;
- rdev->pm.current_mclk = 0;
+ if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+ cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+ if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE)
+ rdev->pm.dynpm_state = DYNPM_STATE_SUSPENDED;
+ flush_wq = true;
+ }
mutex_unlock(&rdev->pm.mutex);
+ if (flush_wq)
+ flush_workqueue(rdev->wq);
}
void radeon_pm_resume(struct radeon_device *rdev)
{
+ /* asic init will reset the default power state */
+ mutex_lock(&rdev->pm.mutex);
+ rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
+ rdev->pm.current_clock_mode_index = 0;
+ rdev->pm.current_sclk = rdev->clock.default_sclk;
+ rdev->pm.current_mclk = rdev->clock.default_mclk;
+ rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+ if (rdev->pm.pm_method == PM_METHOD_DYNPM
+ && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
+ rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
+ queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+ msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
+ }
+ mutex_unlock(&rdev->pm.mutex);
radeon_pm_compute_clocks(rdev);
}
@@ -401,32 +463,24 @@
int ret;
/* default to profile method */
rdev->pm.pm_method = PM_METHOD_PROFILE;
+ rdev->pm.profile = PM_PROFILE_DEFAULT;
rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
rdev->pm.dynpm_can_upclock = true;
rdev->pm.dynpm_can_downclock = true;
- rdev->pm.current_sclk = 0;
- rdev->pm.current_mclk = 0;
+ rdev->pm.current_sclk = rdev->clock.default_sclk;
+ rdev->pm.current_mclk = rdev->clock.default_mclk;
if (rdev->bios) {
if (rdev->is_atom_bios)
radeon_atombios_get_power_modes(rdev);
else
radeon_combios_get_power_modes(rdev);
+ radeon_pm_print_states(rdev);
radeon_pm_init_profile(rdev);
- rdev->pm.current_power_state_index = -1;
- rdev->pm.current_clock_mode_index = -1;
}
if (rdev->pm.num_power_states > 1) {
- if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
- mutex_lock(&rdev->pm.mutex);
- rdev->pm.profile = PM_PROFILE_DEFAULT;
- radeon_pm_update_profile(rdev);
- radeon_pm_set_clocks(rdev);
- mutex_unlock(&rdev->pm.mutex);
- }
-
/* where's the best place to put these? */
ret = device_create_file(rdev->dev, &dev_attr_power_profile);
if (ret)
@@ -454,6 +508,8 @@
void radeon_pm_fini(struct radeon_device *rdev)
{
if (rdev->pm.num_power_states > 1) {
+ bool flush_wq = false;
+
mutex_lock(&rdev->pm.mutex);
if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
rdev->pm.profile = PM_PROFILE_DEFAULT;
@@ -461,13 +517,16 @@
radeon_pm_set_clocks(rdev);
} else if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
/* cancel work */
- cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
+ cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+ flush_wq = true;
/* reset default clocks */
rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
radeon_pm_set_clocks(rdev);
}
mutex_unlock(&rdev->pm.mutex);
+ if (flush_wq)
+ flush_workqueue(rdev->wq);
device_remove_file(rdev->dev, &dev_attr_power_profile);
device_remove_file(rdev->dev, &dev_attr_power_method);
@@ -688,12 +747,12 @@
radeon_pm_get_dynpm_state(rdev);
radeon_pm_set_clocks(rdev);
}
+
+ queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+ msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
}
mutex_unlock(&rdev->pm.mutex);
ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
-
- queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
- msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
}
/*
@@ -712,6 +771,8 @@
seq_printf(m, "default memory clock: %u0 kHz\n", rdev->clock.default_mclk);
if (rdev->asic->get_memory_clock)
seq_printf(m, "current memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev));
+ if (rdev->pm.current_vddc)
+ seq_printf(m, "voltage: %u mV\n", rdev->pm.current_vddc);
if (rdev->asic->get_pcie_lanes)
seq_printf(m, "PCIE lanes: %d\n", radeon_get_pcie_lanes(rdev));
diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen
new file mode 100644
index 0000000..f78fd59
--- /dev/null
+++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen
@@ -0,0 +1,611 @@
+evergreen 0x9400
+0x00008040 WAIT_UNTIL
+0x00008044 WAIT_UNTIL_POLL_CNTL
+0x00008048 WAIT_UNTIL_POLL_MASK
+0x0000804c WAIT_UNTIL_POLL_REFDATA
+0x000088B0 VGT_VTX_VECT_EJECT_REG
+0x000088C4 VGT_CACHE_INVALIDATION
+0x000088D4 VGT_GS_VERTEX_REUSE
+0x00008958 VGT_PRIMITIVE_TYPE
+0x0000895C VGT_INDEX_TYPE
+0x00008970 VGT_NUM_INDICES
+0x00008974 VGT_NUM_INSTANCES
+0x00008990 VGT_COMPUTE_DIM_X
+0x00008994 VGT_COMPUTE_DIM_Y
+0x00008998 VGT_COMPUTE_DIM_Z
+0x0000899C VGT_COMPUTE_START_X
+0x000089A0 VGT_COMPUTE_START_Y
+0x000089A4 VGT_COMPUTE_START_Z
+0x000089AC VGT_COMPUTE_THREAD_GOURP_SIZE
+0x00008A14 PA_CL_ENHANCE
+0x00008A60 PA_SC_LINE_STIPPLE_VALUE
+0x00008B10 PA_SC_LINE_STIPPLE_STATE
+0x00008BF0 PA_SC_ENHANCE
+0x00008D8C SQ_DYN_GPR_CNTL_PS_FLUSH_REQ
+0x00008C00 SQ_CONFIG
+0x00008C04 SQ_GPR_RESOURCE_MGMT_1
+0x00008C08 SQ_GPR_RESOURCE_MGMT_2
+0x00008C0C SQ_GPR_RESOURCE_MGMT_3
+0x00008C10 SQ_GLOBAL_GPR_RESOURCE_MGMT_1
+0x00008C14 SQ_GLOBAL_GPR_RESOURCE_MGMT_2
+0x00008C18 SQ_THREAD_RESOURCE_MGMT
+0x00008C1C SQ_THREAD_RESOURCE_MGMT_2
+0x00008C20 SQ_STACK_RESOURCE_MGMT_1
+0x00008C24 SQ_STACK_RESOURCE_MGMT_2
+0x00008C28 SQ_STACK_RESOURCE_MGMT_3
+0x00008DF8 SQ_CONST_MEM_BASE
+0x00008E48 SQ_EX_ALLOC_TABLE_SLOTS
+0x00009100 SPI_CONFIG_CNTL
+0x0000913C SPI_CONFIG_CNTL_1
+0x00009700 VC_CNTL
+0x00009714 VC_ENHANCE
+0x00009830 DB_DEBUG
+0x00009834 DB_DEBUG2
+0x00009838 DB_DEBUG3
+0x0000983C DB_DEBUG4
+0x00009854 DB_WATERMARKS
+0x0000A400 TD_PS_BORDER_COLOR_INDEX
+0x0000A404 TD_PS_BORDER_COLOR_RED
+0x0000A408 TD_PS_BORDER_COLOR_GREEN
+0x0000A40C TD_PS_BORDER_COLOR_BLUE
+0x0000A410 TD_PS_BORDER_COLOR_ALPHA
+0x0000A414 TD_VS_BORDER_COLOR_INDEX
+0x0000A418 TD_VS_BORDER_COLOR_RED
+0x0000A41C TD_VS_BORDER_COLOR_GREEN
+0x0000A420 TD_VS_BORDER_COLOR_BLUE
+0x0000A424 TD_VS_BORDER_COLOR_ALPHA
+0x0000A428 TD_GS_BORDER_COLOR_INDEX
+0x0000A42C TD_GS_BORDER_COLOR_RED
+0x0000A430 TD_GS_BORDER_COLOR_GREEN
+0x0000A434 TD_GS_BORDER_COLOR_BLUE
+0x0000A438 TD_GS_BORDER_COLOR_ALPHA
+0x0000A43C TD_HS_BORDER_COLOR_INDEX
+0x0000A440 TD_HS_BORDER_COLOR_RED
+0x0000A444 TD_HS_BORDER_COLOR_GREEN
+0x0000A448 TD_HS_BORDER_COLOR_BLUE
+0x0000A44C TD_HS_BORDER_COLOR_ALPHA
+0x0000A450 TD_LS_BORDER_COLOR_INDEX
+0x0000A454 TD_LS_BORDER_COLOR_RED
+0x0000A458 TD_LS_BORDER_COLOR_GREEN
+0x0000A45C TD_LS_BORDER_COLOR_BLUE
+0x0000A460 TD_LS_BORDER_COLOR_ALPHA
+0x0000A464 TD_CS_BORDER_COLOR_INDEX
+0x0000A468 TD_CS_BORDER_COLOR_RED
+0x0000A46C TD_CS_BORDER_COLOR_GREEN
+0x0000A470 TD_CS_BORDER_COLOR_BLUE
+0x0000A474 TD_CS_BORDER_COLOR_ALPHA
+0x00028000 DB_RENDER_CONTROL
+0x00028004 DB_COUNT_CONTROL
+0x0002800C DB_RENDER_OVERRIDE
+0x00028010 DB_RENDER_OVERRIDE2
+0x00028028 DB_STENCIL_CLEAR
+0x0002802C DB_DEPTH_CLEAR
+0x00028030 PA_SC_SCREEN_SCISSOR_TL
+0x00028034 PA_SC_SCREEN_SCISSOR_BR
+0x0002805C DB_DEPTH_SLICE
+0x00028140 SQ_ALU_CONST_BUFFER_SIZE_PS_0
+0x00028144 SQ_ALU_CONST_BUFFER_SIZE_PS_1
+0x00028148 SQ_ALU_CONST_BUFFER_SIZE_PS_2
+0x0002814C SQ_ALU_CONST_BUFFER_SIZE_PS_3
+0x00028150 SQ_ALU_CONST_BUFFER_SIZE_PS_4
+0x00028154 SQ_ALU_CONST_BUFFER_SIZE_PS_5
+0x00028158 SQ_ALU_CONST_BUFFER_SIZE_PS_6
+0x0002815C SQ_ALU_CONST_BUFFER_SIZE_PS_7
+0x00028160 SQ_ALU_CONST_BUFFER_SIZE_PS_8
+0x00028164 SQ_ALU_CONST_BUFFER_SIZE_PS_9
+0x00028168 SQ_ALU_CONST_BUFFER_SIZE_PS_10
+0x0002816C SQ_ALU_CONST_BUFFER_SIZE_PS_11
+0x00028170 SQ_ALU_CONST_BUFFER_SIZE_PS_12
+0x00028174 SQ_ALU_CONST_BUFFER_SIZE_PS_13
+0x00028178 SQ_ALU_CONST_BUFFER_SIZE_PS_14
+0x0002817C SQ_ALU_CONST_BUFFER_SIZE_PS_15
+0x00028180 SQ_ALU_CONST_BUFFER_SIZE_VS_0
+0x00028184 SQ_ALU_CONST_BUFFER_SIZE_VS_1
+0x00028188 SQ_ALU_CONST_BUFFER_SIZE_VS_2
+0x0002818C SQ_ALU_CONST_BUFFER_SIZE_VS_3
+0x00028190 SQ_ALU_CONST_BUFFER_SIZE_VS_4
+0x00028194 SQ_ALU_CONST_BUFFER_SIZE_VS_5
+0x00028198 SQ_ALU_CONST_BUFFER_SIZE_VS_6
+0x0002819C SQ_ALU_CONST_BUFFER_SIZE_VS_7
+0x000281A0 SQ_ALU_CONST_BUFFER_SIZE_VS_8
+0x000281A4 SQ_ALU_CONST_BUFFER_SIZE_VS_9
+0x000281A8 SQ_ALU_CONST_BUFFER_SIZE_VS_10
+0x000281AC SQ_ALU_CONST_BUFFER_SIZE_VS_11
+0x000281B0 SQ_ALU_CONST_BUFFER_SIZE_VS_12
+0x000281B4 SQ_ALU_CONST_BUFFER_SIZE_VS_13
+0x000281B8 SQ_ALU_CONST_BUFFER_SIZE_VS_14
+0x000281BC SQ_ALU_CONST_BUFFER_SIZE_VS_15
+0x000281C0 SQ_ALU_CONST_BUFFER_SIZE_GS_0
+0x000281C4 SQ_ALU_CONST_BUFFER_SIZE_GS_1
+0x000281C8 SQ_ALU_CONST_BUFFER_SIZE_GS_2
+0x000281CC SQ_ALU_CONST_BUFFER_SIZE_GS_3
+0x000281D0 SQ_ALU_CONST_BUFFER_SIZE_GS_4
+0x000281D4 SQ_ALU_CONST_BUFFER_SIZE_GS_5
+0x000281D8 SQ_ALU_CONST_BUFFER_SIZE_GS_6
+0x000281DC SQ_ALU_CONST_BUFFER_SIZE_GS_7
+0x000281E0 SQ_ALU_CONST_BUFFER_SIZE_GS_8
+0x000281E4 SQ_ALU_CONST_BUFFER_SIZE_GS_9
+0x000281E8 SQ_ALU_CONST_BUFFER_SIZE_GS_10
+0x000281EC SQ_ALU_CONST_BUFFER_SIZE_GS_11
+0x000281F0 SQ_ALU_CONST_BUFFER_SIZE_GS_12
+0x000281F4 SQ_ALU_CONST_BUFFER_SIZE_GS_13
+0x000281F8 SQ_ALU_CONST_BUFFER_SIZE_GS_14
+0x000281FC SQ_ALU_CONST_BUFFER_SIZE_GS_15
+0x00028200 PA_SC_WINDOW_OFFSET
+0x00028204 PA_SC_WINDOW_SCISSOR_TL
+0x00028208 PA_SC_WINDOW_SCISSOR_BR
+0x0002820C PA_SC_CLIPRECT_RULE
+0x00028210 PA_SC_CLIPRECT_0_TL
+0x00028214 PA_SC_CLIPRECT_0_BR
+0x00028218 PA_SC_CLIPRECT_1_TL
+0x0002821C PA_SC_CLIPRECT_1_BR
+0x00028220 PA_SC_CLIPRECT_2_TL
+0x00028224 PA_SC_CLIPRECT_2_BR
+0x00028228 PA_SC_CLIPRECT_3_TL
+0x0002822C PA_SC_CLIPRECT_3_BR
+0x00028230 PA_SC_EDGERULE
+0x00028234 PA_SU_HARDWARE_SCREEN_OFFSET
+0x00028240 PA_SC_GENERIC_SCISSOR_TL
+0x00028244 PA_SC_GENERIC_SCISSOR_BR
+0x00028250 PA_SC_VPORT_SCISSOR_0_TL
+0x00028254 PA_SC_VPORT_SCISSOR_0_BR
+0x00028258 PA_SC_VPORT_SCISSOR_1_TL
+0x0002825C PA_SC_VPORT_SCISSOR_1_BR
+0x00028260 PA_SC_VPORT_SCISSOR_2_TL
+0x00028264 PA_SC_VPORT_SCISSOR_2_BR
+0x00028268 PA_SC_VPORT_SCISSOR_3_TL
+0x0002826C PA_SC_VPORT_SCISSOR_3_BR
+0x00028270 PA_SC_VPORT_SCISSOR_4_TL
+0x00028274 PA_SC_VPORT_SCISSOR_4_BR
+0x00028278 PA_SC_VPORT_SCISSOR_5_TL
+0x0002827C PA_SC_VPORT_SCISSOR_5_BR
+0x00028280 PA_SC_VPORT_SCISSOR_6_TL
+0x00028284 PA_SC_VPORT_SCISSOR_6_BR
+0x00028288 PA_SC_VPORT_SCISSOR_7_TL
+0x0002828C PA_SC_VPORT_SCISSOR_7_BR
+0x00028290 PA_SC_VPORT_SCISSOR_8_TL
+0x00028294 PA_SC_VPORT_SCISSOR_8_BR
+0x00028298 PA_SC_VPORT_SCISSOR_9_TL
+0x0002829C PA_SC_VPORT_SCISSOR_9_BR
+0x000282A0 PA_SC_VPORT_SCISSOR_10_TL
+0x000282A4 PA_SC_VPORT_SCISSOR_10_BR
+0x000282A8 PA_SC_VPORT_SCISSOR_11_TL
+0x000282AC PA_SC_VPORT_SCISSOR_11_BR
+0x000282B0 PA_SC_VPORT_SCISSOR_12_TL
+0x000282B4 PA_SC_VPORT_SCISSOR_12_BR
+0x000282B8 PA_SC_VPORT_SCISSOR_13_TL
+0x000282BC PA_SC_VPORT_SCISSOR_13_BR
+0x000282C0 PA_SC_VPORT_SCISSOR_14_TL
+0x000282C4 PA_SC_VPORT_SCISSOR_14_BR
+0x000282C8 PA_SC_VPORT_SCISSOR_15_TL
+0x000282CC PA_SC_VPORT_SCISSOR_15_BR
+0x000282D0 PA_SC_VPORT_ZMIN_0
+0x000282D4 PA_SC_VPORT_ZMAX_0
+0x000282D8 PA_SC_VPORT_ZMIN_1
+0x000282DC PA_SC_VPORT_ZMAX_1
+0x000282E0 PA_SC_VPORT_ZMIN_2
+0x000282E4 PA_SC_VPORT_ZMAX_2
+0x000282E8 PA_SC_VPORT_ZMIN_3
+0x000282EC PA_SC_VPORT_ZMAX_3
+0x000282F0 PA_SC_VPORT_ZMIN_4
+0x000282F4 PA_SC_VPORT_ZMAX_4
+0x000282F8 PA_SC_VPORT_ZMIN_5
+0x000282FC PA_SC_VPORT_ZMAX_5
+0x00028300 PA_SC_VPORT_ZMIN_6
+0x00028304 PA_SC_VPORT_ZMAX_6
+0x00028308 PA_SC_VPORT_ZMIN_7
+0x0002830C PA_SC_VPORT_ZMAX_7
+0x00028310 PA_SC_VPORT_ZMIN_8
+0x00028314 PA_SC_VPORT_ZMAX_8
+0x00028318 PA_SC_VPORT_ZMIN_9
+0x0002831C PA_SC_VPORT_ZMAX_9
+0x00028320 PA_SC_VPORT_ZMIN_10
+0x00028324 PA_SC_VPORT_ZMAX_10
+0x00028328 PA_SC_VPORT_ZMIN_11
+0x0002832C PA_SC_VPORT_ZMAX_11
+0x00028330 PA_SC_VPORT_ZMIN_12
+0x00028334 PA_SC_VPORT_ZMAX_12
+0x00028338 PA_SC_VPORT_ZMIN_13
+0x0002833C PA_SC_VPORT_ZMAX_13
+0x00028340 PA_SC_VPORT_ZMIN_14
+0x00028344 PA_SC_VPORT_ZMAX_14
+0x00028348 PA_SC_VPORT_ZMIN_15
+0x0002834C PA_SC_VPORT_ZMAX_15
+0x00028350 SX_MISC
+0x00028380 SQ_VTX_SEMANTIC_0
+0x00028384 SQ_VTX_SEMANTIC_1
+0x00028388 SQ_VTX_SEMANTIC_2
+0x0002838C SQ_VTX_SEMANTIC_3
+0x00028390 SQ_VTX_SEMANTIC_4
+0x00028394 SQ_VTX_SEMANTIC_5
+0x00028398 SQ_VTX_SEMANTIC_6
+0x0002839C SQ_VTX_SEMANTIC_7
+0x000283A0 SQ_VTX_SEMANTIC_8
+0x000283A4 SQ_VTX_SEMANTIC_9
+0x000283A8 SQ_VTX_SEMANTIC_10
+0x000283AC SQ_VTX_SEMANTIC_11
+0x000283B0 SQ_VTX_SEMANTIC_12
+0x000283B4 SQ_VTX_SEMANTIC_13
+0x000283B8 SQ_VTX_SEMANTIC_14
+0x000283BC SQ_VTX_SEMANTIC_15
+0x000283C0 SQ_VTX_SEMANTIC_16
+0x000283C4 SQ_VTX_SEMANTIC_17
+0x000283C8 SQ_VTX_SEMANTIC_18
+0x000283CC SQ_VTX_SEMANTIC_19
+0x000283D0 SQ_VTX_SEMANTIC_20
+0x000283D4 SQ_VTX_SEMANTIC_21
+0x000283D8 SQ_VTX_SEMANTIC_22
+0x000283DC SQ_VTX_SEMANTIC_23
+0x000283E0 SQ_VTX_SEMANTIC_24
+0x000283E4 SQ_VTX_SEMANTIC_25
+0x000283E8 SQ_VTX_SEMANTIC_26
+0x000283EC SQ_VTX_SEMANTIC_27
+0x000283F0 SQ_VTX_SEMANTIC_28
+0x000283F4 SQ_VTX_SEMANTIC_29
+0x000283F8 SQ_VTX_SEMANTIC_30
+0x000283FC SQ_VTX_SEMANTIC_31
+0x00028400 VGT_MAX_VTX_INDX
+0x00028404 VGT_MIN_VTX_INDX
+0x00028408 VGT_INDX_OFFSET
+0x0002840C VGT_MULTI_PRIM_IB_RESET_INDX
+0x00028410 SX_ALPHA_TEST_CONTROL
+0x00028414 CB_BLEND_RED
+0x00028418 CB_BLEND_GREEN
+0x0002841C CB_BLEND_BLUE
+0x00028420 CB_BLEND_ALPHA
+0x00028430 DB_STENCILREFMASK
+0x00028434 DB_STENCILREFMASK_BF
+0x00028438 SX_ALPHA_REF
+0x0002843C PA_CL_VPORT_XSCALE_0
+0x00028440 PA_CL_VPORT_XOFFSET_0
+0x00028444 PA_CL_VPORT_YSCALE_0
+0x00028448 PA_CL_VPORT_YOFFSET_0
+0x0002844C PA_CL_VPORT_ZSCALE_0
+0x00028450 PA_CL_VPORT_ZOFFSET_0
+0x00028454 PA_CL_VPORT_XSCALE_1
+0x00028458 PA_CL_VPORT_XOFFSET_1
+0x0002845C PA_CL_VPORT_YSCALE_1
+0x00028460 PA_CL_VPORT_YOFFSET_1
+0x00028464 PA_CL_VPORT_ZSCALE_1
+0x00028468 PA_CL_VPORT_ZOFFSET_1
+0x0002846C PA_CL_VPORT_XSCALE_2
+0x00028470 PA_CL_VPORT_XOFFSET_2
+0x00028474 PA_CL_VPORT_YSCALE_2
+0x00028478 PA_CL_VPORT_YOFFSET_2
+0x0002847C PA_CL_VPORT_ZSCALE_2
+0x00028480 PA_CL_VPORT_ZOFFSET_2
+0x00028484 PA_CL_VPORT_XSCALE_3
+0x00028488 PA_CL_VPORT_XOFFSET_3
+0x0002848C PA_CL_VPORT_YSCALE_3
+0x00028490 PA_CL_VPORT_YOFFSET_3
+0x00028494 PA_CL_VPORT_ZSCALE_3
+0x00028498 PA_CL_VPORT_ZOFFSET_3
+0x0002849C PA_CL_VPORT_XSCALE_4
+0x000284A0 PA_CL_VPORT_XOFFSET_4
+0x000284A4 PA_CL_VPORT_YSCALE_4
+0x000284A8 PA_CL_VPORT_YOFFSET_4
+0x000284AC PA_CL_VPORT_ZSCALE_4
+0x000284B0 PA_CL_VPORT_ZOFFSET_4
+0x000284B4 PA_CL_VPORT_XSCALE_5
+0x000284B8 PA_CL_VPORT_XOFFSET_5
+0x000284BC PA_CL_VPORT_YSCALE_5
+0x000284C0 PA_CL_VPORT_YOFFSET_5
+0x000284C4 PA_CL_VPORT_ZSCALE_5
+0x000284C8 PA_CL_VPORT_ZOFFSET_5
+0x000284CC PA_CL_VPORT_XSCALE_6
+0x000284D0 PA_CL_VPORT_XOFFSET_6
+0x000284D4 PA_CL_VPORT_YSCALE_6
+0x000284D8 PA_CL_VPORT_YOFFSET_6
+0x000284DC PA_CL_VPORT_ZSCALE_6
+0x000284E0 PA_CL_VPORT_ZOFFSET_6
+0x000284E4 PA_CL_VPORT_XSCALE_7
+0x000284E8 PA_CL_VPORT_XOFFSET_7
+0x000284EC PA_CL_VPORT_YSCALE_7
+0x000284F0 PA_CL_VPORT_YOFFSET_7
+0x000284F4 PA_CL_VPORT_ZSCALE_7
+0x000284F8 PA_CL_VPORT_ZOFFSET_7
+0x000284FC PA_CL_VPORT_XSCALE_8
+0x00028500 PA_CL_VPORT_XOFFSET_8
+0x00028504 PA_CL_VPORT_YSCALE_8
+0x00028508 PA_CL_VPORT_YOFFSET_8
+0x0002850C PA_CL_VPORT_ZSCALE_8
+0x00028510 PA_CL_VPORT_ZOFFSET_8
+0x00028514 PA_CL_VPORT_XSCALE_9
+0x00028518 PA_CL_VPORT_XOFFSET_9
+0x0002851C PA_CL_VPORT_YSCALE_9
+0x00028520 PA_CL_VPORT_YOFFSET_9
+0x00028524 PA_CL_VPORT_ZSCALE_9
+0x00028528 PA_CL_VPORT_ZOFFSET_9
+0x0002852C PA_CL_VPORT_XSCALE_10
+0x00028530 PA_CL_VPORT_XOFFSET_10
+0x00028534 PA_CL_VPORT_YSCALE_10
+0x00028538 PA_CL_VPORT_YOFFSET_10
+0x0002853C PA_CL_VPORT_ZSCALE_10
+0x00028540 PA_CL_VPORT_ZOFFSET_10
+0x00028544 PA_CL_VPORT_XSCALE_11
+0x00028548 PA_CL_VPORT_XOFFSET_11
+0x0002854C PA_CL_VPORT_YSCALE_11
+0x00028550 PA_CL_VPORT_YOFFSET_11
+0x00028554 PA_CL_VPORT_ZSCALE_11
+0x00028558 PA_CL_VPORT_ZOFFSET_11
+0x0002855C PA_CL_VPORT_XSCALE_12
+0x00028560 PA_CL_VPORT_XOFFSET_12
+0x00028564 PA_CL_VPORT_YSCALE_12
+0x00028568 PA_CL_VPORT_YOFFSET_12
+0x0002856C PA_CL_VPORT_ZSCALE_12
+0x00028570 PA_CL_VPORT_ZOFFSET_12
+0x00028574 PA_CL_VPORT_XSCALE_13
+0x00028578 PA_CL_VPORT_XOFFSET_13
+0x0002857C PA_CL_VPORT_YSCALE_13
+0x00028580 PA_CL_VPORT_YOFFSET_13
+0x00028584 PA_CL_VPORT_ZSCALE_13
+0x00028588 PA_CL_VPORT_ZOFFSET_13
+0x0002858C PA_CL_VPORT_XSCALE_14
+0x00028590 PA_CL_VPORT_XOFFSET_14
+0x00028594 PA_CL_VPORT_YSCALE_14
+0x00028598 PA_CL_VPORT_YOFFSET_14
+0x0002859C PA_CL_VPORT_ZSCALE_14
+0x000285A0 PA_CL_VPORT_ZOFFSET_14
+0x000285A4 PA_CL_VPORT_XSCALE_15
+0x000285A8 PA_CL_VPORT_XOFFSET_15
+0x000285AC PA_CL_VPORT_YSCALE_15
+0x000285B0 PA_CL_VPORT_YOFFSET_15
+0x000285B4 PA_CL_VPORT_ZSCALE_15
+0x000285B8 PA_CL_VPORT_ZOFFSET_15
+0x000285BC PA_CL_UCP_0_X
+0x000285C0 PA_CL_UCP_0_Y
+0x000285C4 PA_CL_UCP_0_Z
+0x000285C8 PA_CL_UCP_0_W
+0x000285CC PA_CL_UCP_1_X
+0x000285D0 PA_CL_UCP_1_Y
+0x000285D4 PA_CL_UCP_1_Z
+0x000285D8 PA_CL_UCP_1_W
+0x000285DC PA_CL_UCP_2_X
+0x000285E0 PA_CL_UCP_2_Y
+0x000285E4 PA_CL_UCP_2_Z
+0x000285E8 PA_CL_UCP_2_W
+0x000285EC PA_CL_UCP_3_X
+0x000285F0 PA_CL_UCP_3_Y
+0x000285F4 PA_CL_UCP_3_Z
+0x000285F8 PA_CL_UCP_3_W
+0x000285FC PA_CL_UCP_4_X
+0x00028600 PA_CL_UCP_4_Y
+0x00028604 PA_CL_UCP_4_Z
+0x00028608 PA_CL_UCP_4_W
+0x0002860C PA_CL_UCP_5_X
+0x00028610 PA_CL_UCP_5_Y
+0x00028614 PA_CL_UCP_5_Z
+0x00028618 PA_CL_UCP_5_W
+0x0002861C SPI_VS_OUT_ID_0
+0x00028620 SPI_VS_OUT_ID_1
+0x00028624 SPI_VS_OUT_ID_2
+0x00028628 SPI_VS_OUT_ID_3
+0x0002862C SPI_VS_OUT_ID_4
+0x00028630 SPI_VS_OUT_ID_5
+0x00028634 SPI_VS_OUT_ID_6
+0x00028638 SPI_VS_OUT_ID_7
+0x0002863C SPI_VS_OUT_ID_8
+0x00028640 SPI_VS_OUT_ID_9
+0x00028644 SPI_PS_INPUT_CNTL_0
+0x00028648 SPI_PS_INPUT_CNTL_1
+0x0002864C SPI_PS_INPUT_CNTL_2
+0x00028650 SPI_PS_INPUT_CNTL_3
+0x00028654 SPI_PS_INPUT_CNTL_4
+0x00028658 SPI_PS_INPUT_CNTL_5
+0x0002865C SPI_PS_INPUT_CNTL_6
+0x00028660 SPI_PS_INPUT_CNTL_7
+0x00028664 SPI_PS_INPUT_CNTL_8
+0x00028668 SPI_PS_INPUT_CNTL_9
+0x0002866C SPI_PS_INPUT_CNTL_10
+0x00028670 SPI_PS_INPUT_CNTL_11
+0x00028674 SPI_PS_INPUT_CNTL_12
+0x00028678 SPI_PS_INPUT_CNTL_13
+0x0002867C SPI_PS_INPUT_CNTL_14
+0x00028680 SPI_PS_INPUT_CNTL_15
+0x00028684 SPI_PS_INPUT_CNTL_16
+0x00028688 SPI_PS_INPUT_CNTL_17
+0x0002868C SPI_PS_INPUT_CNTL_18
+0x00028690 SPI_PS_INPUT_CNTL_19
+0x00028694 SPI_PS_INPUT_CNTL_20
+0x00028698 SPI_PS_INPUT_CNTL_21
+0x0002869C SPI_PS_INPUT_CNTL_22
+0x000286A0 SPI_PS_INPUT_CNTL_23
+0x000286A4 SPI_PS_INPUT_CNTL_24
+0x000286A8 SPI_PS_INPUT_CNTL_25
+0x000286AC SPI_PS_INPUT_CNTL_26
+0x000286B0 SPI_PS_INPUT_CNTL_27
+0x000286B4 SPI_PS_INPUT_CNTL_28
+0x000286B8 SPI_PS_INPUT_CNTL_29
+0x000286BC SPI_PS_INPUT_CNTL_30
+0x000286C0 SPI_PS_INPUT_CNTL_31
+0x000286C4 SPI_VS_OUT_CONFIG
+0x000286C8 SPI_THREAD_GROUPING
+0x000286CC SPI_PS_IN_CONTROL_0
+0x000286D0 SPI_PS_IN_CONTROL_1
+0x000286D4 SPI_INTERP_CONTROL_0
+0x000286D8 SPI_INPUT_Z
+0x000286DC SPI_FOG_CNTL
+0x000286E0 SPI_BARYC_CNTL
+0x000286E4 SPI_PS_IN_CONTROL_2
+0x000286E8 SPI_COMPUTE_INPUT_CNTL
+0x000286EC SPI_COMPUTE_NUM_THREAD_X
+0x000286F0 SPI_COMPUTE_NUM_THREAD_Y
+0x000286F4 SPI_COMPUTE_NUM_THREAD_Z
+0x000286F8 GDS_ADDR_SIZE
+0x00028780 CB_BLEND0_CONTROL
+0x00028784 CB_BLEND1_CONTROL
+0x00028788 CB_BLEND2_CONTROL
+0x0002878C CB_BLEND3_CONTROL
+0x00028790 CB_BLEND4_CONTROL
+0x00028794 CB_BLEND5_CONTROL
+0x00028798 CB_BLEND6_CONTROL
+0x0002879C CB_BLEND7_CONTROL
+0x000287CC CS_COPY_STATE
+0x000287D0 GFX_COPY_STATE
+0x000287D4 PA_CL_POINT_X_RAD
+0x000287D8 PA_CL_POINT_Y_RAD
+0x000287DC PA_CL_POINT_SIZE
+0x000287E0 PA_CL_POINT_CULL_RAD
+0x00028808 CB_COLOR_CONTROL
+0x0002880C DB_SHADER_CONTROL
+0x00028810 PA_CL_CLIP_CNTL
+0x00028814 PA_SU_SC_MODE_CNTL
+0x00028818 PA_CL_VTE_CNTL
+0x0002881C PA_CL_VS_OUT_CNTL
+0x00028820 PA_CL_NANINF_CNTL
+0x00028824 PA_SU_LINE_STIPPLE_CNTL
+0x00028828 PA_SU_LINE_STIPPLE_SCALE
+0x0002882C PA_SU_PRIM_FILTER_CNTL
+0x00028838 SQ_DYN_GPR_RESOURCE_LIMIT_1
+0x00028844 SQ_PGM_RESOURCES_PS
+0x00028848 SQ_PGM_RESOURCES_2_PS
+0x0002884C SQ_PGM_EXPORTS_PS
+0x00028860 SQ_PGM_RESOURCES_VS
+0x00028864 SQ_PGM_RESOURCES_2_VS
+0x00028878 SQ_PGM_RESOURCES_GS
+0x0002887C SQ_PGM_RESOURCES_2_GS
+0x00028890 SQ_PGM_RESOURCES_ES
+0x00028894 SQ_PGM_RESOURCES_2_ES
+0x000288A8 SQ_PGM_RESOURCES_FS
+0x000288BC SQ_PGM_RESOURCES_HS
+0x000288C0 SQ_PGM_RESOURCES_2_HS
+0x000288D4 SQ_PGM_RESOURCES_LS
+0x000288D8 SQ_PGM_RESOURCES_2_LS
+0x000288E8 SQ_LDS_ALLOC
+0x000288EC SQ_LDS_ALLOC_PS
+0x000288F0 SQ_VTX_SEMANTIC_CLEAR
+0x00028A00 PA_SU_POINT_SIZE
+0x00028A04 PA_SU_POINT_MINMAX
+0x00028A08 PA_SU_LINE_CNTL
+0x00028A0C PA_SC_LINE_STIPPLE
+0x00028A10 VGT_OUTPUT_PATH_CNTL
+0x00028A14 VGT_HOS_CNTL
+0x00028A18 VGT_HOS_MAX_TESS_LEVEL
+0x00028A1C VGT_HOS_MIN_TESS_LEVEL
+0x00028A20 VGT_HOS_REUSE_DEPTH
+0x00028A24 VGT_GROUP_PRIM_TYPE
+0x00028A28 VGT_GROUP_FIRST_DECR
+0x00028A2C VGT_GROUP_DECR
+0x00028A30 VGT_GROUP_VECT_0_CNTL
+0x00028A34 VGT_GROUP_VECT_1_CNTL
+0x00028A38 VGT_GROUP_VECT_0_FMT_CNTL
+0x00028A3C VGT_GROUP_VECT_1_FMT_CNTL
+0x00028A40 VGT_GS_MODE
+0x00028A48 PA_SC_MODE_CNTL_0
+0x00028A4C PA_SC_MODE_CNTL_1
+0x00028A50 VGT_ENHANCE
+0x00028A54 VGT_GS_PER_ES
+0x00028A58 VGT_ES_PER_GS
+0x00028A5C VGT_GS_PER_VS
+0x00028A6C VGT_GS_OUT_PRIM_TYPE
+0x00028A84 VGT_PRIMITIVEID_EN
+0x00028A94 VGT_MULTI_PRIM_IB_RESET_EN
+0x00028AA0 VGT_INSTANCE_STEP_RATE_0
+0x00028AA4 VGT_INSTANCE_STEP_RATE_1
+0x00028AB4 VGT_REUSE_OFF
+0x00028AB8 VGT_VTX_CNT_EN
+0x00028ABC DB_HTILE_SURFACE
+0x00028AC0 DB_SRESULTS_COMPARE_STATE0
+0x00028AC4 DB_SRESULTS_COMPARE_STATE1
+0x00028AC8 DB_PRELOAD_CONTROL
+0x00028B38 VGT_GS_MAX_VERT_OUT
+0x00028B54 VGT_SHADER_STAGES_EN
+0x00028B58 VGT_LS_HS_CONFIG
+0x00028B5C VGT_LS_SIZE
+0x00028B60 VGT_HS_SIZE
+0x00028B64 VGT_LS_HS_ALLOC
+0x00028B68 VGT_HS_PATCH_CONST
+0x00028B6C VGT_TF_PARAM
+0x00028B70 DB_ALPHA_TO_MASK
+0x00028B74 VGT_DISPATCH_INITIATOR
+0x00028B78 PA_SU_POLY_OFFSET_DB_FMT_CNTL
+0x00028B7C PA_SU_POLY_OFFSET_CLAMP
+0x00028B80 PA_SU_POLY_OFFSET_FRONT_SCALE
+0x00028B84 PA_SU_POLY_OFFSET_FRONT_OFFSET
+0x00028B88 PA_SU_POLY_OFFSET_BACK_SCALE
+0x00028B8C PA_SU_POLY_OFFSET_BACK_OFFSET
+0x00028B74 VGT_GS_INSTANCE_CNT
+0x00028C00 PA_SC_LINE_CNTL
+0x00028C08 PA_SU_VTX_CNTL
+0x00028C0C PA_CL_GB_VERT_CLIP_ADJ
+0x00028C10 PA_CL_GB_VERT_DISC_ADJ
+0x00028C14 PA_CL_GB_HORZ_CLIP_ADJ
+0x00028C18 PA_CL_GB_HORZ_DISC_ADJ
+0x00028C1C PA_SC_AA_SAMPLE_LOCS_0
+0x00028C20 PA_SC_AA_SAMPLE_LOCS_1
+0x00028C24 PA_SC_AA_SAMPLE_LOCS_2
+0x00028C28 PA_SC_AA_SAMPLE_LOCS_3
+0x00028C2C PA_SC_AA_SAMPLE_LOCS_4
+0x00028C30 PA_SC_AA_SAMPLE_LOCS_5
+0x00028C34 PA_SC_AA_SAMPLE_LOCS_6
+0x00028C38 PA_SC_AA_SAMPLE_LOCS_7
+0x00028C3C PA_SC_AA_MASK
+0x00028C8C CB_COLOR0_CLEAR_WORD0
+0x00028C90 CB_COLOR0_CLEAR_WORD1
+0x00028C94 CB_COLOR0_CLEAR_WORD2
+0x00028C98 CB_COLOR0_CLEAR_WORD3
+0x00028CC8 CB_COLOR1_CLEAR_WORD0
+0x00028CCC CB_COLOR1_CLEAR_WORD1
+0x00028CD0 CB_COLOR1_CLEAR_WORD2
+0x00028CD4 CB_COLOR1_CLEAR_WORD3
+0x00028D04 CB_COLOR2_CLEAR_WORD0
+0x00028D08 CB_COLOR2_CLEAR_WORD1
+0x00028D0C CB_COLOR2_CLEAR_WORD2
+0x00028D10 CB_COLOR2_CLEAR_WORD3
+0x00028D40 CB_COLOR3_CLEAR_WORD0
+0x00028D44 CB_COLOR3_CLEAR_WORD1
+0x00028D48 CB_COLOR3_CLEAR_WORD2
+0x00028D4C CB_COLOR3_CLEAR_WORD3
+0x00028D7C CB_COLOR4_CLEAR_WORD0
+0x00028D80 CB_COLOR4_CLEAR_WORD1
+0x00028D84 CB_COLOR4_CLEAR_WORD2
+0x00028D88 CB_COLOR4_CLEAR_WORD3
+0x00028DB8 CB_COLOR5_CLEAR_WORD0
+0x00028DBC CB_COLOR5_CLEAR_WORD1
+0x00028DC0 CB_COLOR5_CLEAR_WORD2
+0x00028DC4 CB_COLOR5_CLEAR_WORD3
+0x00028DF4 CB_COLOR6_CLEAR_WORD0
+0x00028DF8 CB_COLOR6_CLEAR_WORD1
+0x00028DFC CB_COLOR6_CLEAR_WORD2
+0x00028E00 CB_COLOR6_CLEAR_WORD3
+0x00028E30 CB_COLOR7_CLEAR_WORD0
+0x00028E34 CB_COLOR7_CLEAR_WORD1
+0x00028E38 CB_COLOR7_CLEAR_WORD2
+0x00028E3C CB_COLOR7_CLEAR_WORD3
+0x00028F80 SQ_ALU_CONST_BUFFER_SIZE_HS_0
+0x00028F84 SQ_ALU_CONST_BUFFER_SIZE_HS_1
+0x00028F88 SQ_ALU_CONST_BUFFER_SIZE_HS_2
+0x00028F8C SQ_ALU_CONST_BUFFER_SIZE_HS_3
+0x00028F90 SQ_ALU_CONST_BUFFER_SIZE_HS_4
+0x00028F94 SQ_ALU_CONST_BUFFER_SIZE_HS_5
+0x00028F98 SQ_ALU_CONST_BUFFER_SIZE_HS_6
+0x00028F9C SQ_ALU_CONST_BUFFER_SIZE_HS_7
+0x00028FA0 SQ_ALU_CONST_BUFFER_SIZE_HS_8
+0x00028FA4 SQ_ALU_CONST_BUFFER_SIZE_HS_9
+0x00028FA8 SQ_ALU_CONST_BUFFER_SIZE_HS_10
+0x00028FAC SQ_ALU_CONST_BUFFER_SIZE_HS_11
+0x00028FB0 SQ_ALU_CONST_BUFFER_SIZE_HS_12
+0x00028FB4 SQ_ALU_CONST_BUFFER_SIZE_HS_13
+0x00028FB8 SQ_ALU_CONST_BUFFER_SIZE_HS_14
+0x00028FBC SQ_ALU_CONST_BUFFER_SIZE_HS_15
+0x00028FC0 SQ_ALU_CONST_BUFFER_SIZE_LS_0
+0x00028FC4 SQ_ALU_CONST_BUFFER_SIZE_LS_1
+0x00028FC8 SQ_ALU_CONST_BUFFER_SIZE_LS_2
+0x00028FCC SQ_ALU_CONST_BUFFER_SIZE_LS_3
+0x00028FD0 SQ_ALU_CONST_BUFFER_SIZE_LS_4
+0x00028FD4 SQ_ALU_CONST_BUFFER_SIZE_LS_5
+0x00028FD8 SQ_ALU_CONST_BUFFER_SIZE_LS_6
+0x00028FDC SQ_ALU_CONST_BUFFER_SIZE_LS_7
+0x00028FE0 SQ_ALU_CONST_BUFFER_SIZE_LS_8
+0x00028FE4 SQ_ALU_CONST_BUFFER_SIZE_LS_9
+0x00028FE8 SQ_ALU_CONST_BUFFER_SIZE_LS_10
+0x00028FEC SQ_ALU_CONST_BUFFER_SIZE_LS_11
+0x00028FF0 SQ_ALU_CONST_BUFFER_SIZE_LS_12
+0x00028FF4 SQ_ALU_CONST_BUFFER_SIZE_LS_13
+0x00028FF8 SQ_ALU_CONST_BUFFER_SIZE_LS_14
+0x00028FFC SQ_ALU_CONST_BUFFER_SIZE_LS_15
+0x0003CFF0 SQ_VTX_BASE_VTX_LOC
+0x0003CFF4 SQ_VTX_START_INST_LOC
+0x0003FF00 SQ_TEX_SAMPLER_CLEAR
+0x0003FF04 SQ_TEX_RESOURCE_CLEAR
+0x0003FF08 SQ_LOOP_BOOL_CLEAR
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
index 79887ca..7bb4c3e 100644
--- a/drivers/gpu/drm/radeon/rs600.c
+++ b/drivers/gpu/drm/radeon/rs600.c
@@ -74,7 +74,8 @@
if (voltage->delay)
udelay(voltage->delay);
}
- }
+ } else if (voltage->type == VOLTAGE_VDDC)
+ radeon_atom_set_voltage(rdev, voltage->vddc_id);
dyn_pwrmgt_sclk_length = RREG32_PLL(DYN_PWRMGT_SCLK_LENGTH);
dyn_pwrmgt_sclk_length &= ~REDUCED_POWER_SCLK_HILEN(0xf);
diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c
index bcc3319..f4f0a61 100644
--- a/drivers/gpu/drm/radeon/rs690.c
+++ b/drivers/gpu/drm/radeon/rs690.c
@@ -79,7 +79,13 @@
tmp.full = dfixed_const(100);
rdev->pm.igp_sideport_mclk.full = dfixed_const(info->info.ulBootUpMemoryClock);
rdev->pm.igp_sideport_mclk.full = dfixed_div(rdev->pm.igp_sideport_mclk, tmp);
- rdev->pm.igp_system_mclk.full = dfixed_const(le16_to_cpu(info->info.usK8MemoryClock));
+ if (info->info.usK8MemoryClock)
+ rdev->pm.igp_system_mclk.full = dfixed_const(le16_to_cpu(info->info.usK8MemoryClock));
+ else if (rdev->clock.default_mclk) {
+ rdev->pm.igp_system_mclk.full = dfixed_const(rdev->clock.default_mclk);
+ rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp);
+ } else
+ rdev->pm.igp_system_mclk.full = dfixed_const(400);
rdev->pm.igp_ht_link_clk.full = dfixed_const(le16_to_cpu(info->info.usFSBClock));
rdev->pm.igp_ht_link_width.full = dfixed_const(info->info.ucHTLinkWidth);
break;
@@ -87,34 +93,31 @@
tmp.full = dfixed_const(100);
rdev->pm.igp_sideport_mclk.full = dfixed_const(info->info_v2.ulBootUpSidePortClock);
rdev->pm.igp_sideport_mclk.full = dfixed_div(rdev->pm.igp_sideport_mclk, tmp);
- rdev->pm.igp_system_mclk.full = dfixed_const(info->info_v2.ulBootUpUMAClock);
+ if (info->info_v2.ulBootUpUMAClock)
+ rdev->pm.igp_system_mclk.full = dfixed_const(info->info_v2.ulBootUpUMAClock);
+ else if (rdev->clock.default_mclk)
+ rdev->pm.igp_system_mclk.full = dfixed_const(rdev->clock.default_mclk);
+ else
+ rdev->pm.igp_system_mclk.full = dfixed_const(66700);
rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp);
rdev->pm.igp_ht_link_clk.full = dfixed_const(info->info_v2.ulHTLinkFreq);
rdev->pm.igp_ht_link_clk.full = dfixed_div(rdev->pm.igp_ht_link_clk, tmp);
rdev->pm.igp_ht_link_width.full = dfixed_const(le16_to_cpu(info->info_v2.usMinHTLinkWidth));
break;
default:
- tmp.full = dfixed_const(100);
/* We assume the slower possible clock ie worst case */
- /* DDR 333Mhz */
- rdev->pm.igp_sideport_mclk.full = dfixed_const(333);
- /* FIXME: system clock ? */
- rdev->pm.igp_system_mclk.full = dfixed_const(100);
- rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp);
- rdev->pm.igp_ht_link_clk.full = dfixed_const(200);
+ rdev->pm.igp_sideport_mclk.full = dfixed_const(200);
+ rdev->pm.igp_system_mclk.full = dfixed_const(200);
+ rdev->pm.igp_ht_link_clk.full = dfixed_const(1000);
rdev->pm.igp_ht_link_width.full = dfixed_const(8);
DRM_ERROR("No integrated system info for your GPU, using safe default\n");
break;
}
} else {
- tmp.full = dfixed_const(100);
/* We assume the slower possible clock ie worst case */
- /* DDR 333Mhz */
- rdev->pm.igp_sideport_mclk.full = dfixed_const(333);
- /* FIXME: system clock ? */
- rdev->pm.igp_system_mclk.full = dfixed_const(100);
- rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp);
- rdev->pm.igp_ht_link_clk.full = dfixed_const(200);
+ rdev->pm.igp_sideport_mclk.full = dfixed_const(200);
+ rdev->pm.igp_system_mclk.full = dfixed_const(200);
+ rdev->pm.igp_ht_link_clk.full = dfixed_const(1000);
rdev->pm.igp_ht_link_width.full = dfixed_const(8);
DRM_ERROR("No integrated system info for your GPU, using safe default\n");
}
@@ -228,10 +231,6 @@
fixed20_12 a, b, c;
fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width;
fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency;
- /* FIXME: detect IGP with sideport memory, i don't think there is any
- * such product available
- */
- bool sideport = false;
if (!crtc->base.enabled) {
/* FIXME: wouldn't it better to set priority mark to maximum */
@@ -300,7 +299,7 @@
/* Maximun bandwidth is the minimun bandwidth of all component */
rdev->pm.max_bandwidth = rdev->pm.core_bandwidth;
- if (sideport) {
+ if (rdev->mc.igp_sideport_enabled) {
if (rdev->pm.max_bandwidth.full > rdev->pm.sideport_bandwidth.full &&
rdev->pm.sideport_bandwidth.full)
rdev->pm.max_bandwidth = rdev->pm.sideport_bandwidth;
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index 253f24a..b7fd820 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -44,7 +44,18 @@
void rv770_pm_misc(struct radeon_device *rdev)
{
+ int req_ps_idx = rdev->pm.requested_power_state_index;
+ int req_cm_idx = rdev->pm.requested_clock_mode_index;
+ struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx];
+ struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;
+ if ((voltage->type == VOLTAGE_SW) && voltage->voltage) {
+ if (voltage->voltage != rdev->pm.current_vddc) {
+ radeon_atom_set_voltage(rdev, voltage->voltage);
+ rdev->pm.current_vddc = voltage->voltage;
+ DRM_DEBUG("Setting: v: %d\n", voltage->voltage);
+ }
+ }
}
/*
@@ -213,7 +224,7 @@
WREG32(MC_VM_FB_LOCATION, tmp);
WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8));
WREG32(HDP_NONSURFACE_INFO, (2 << 7));
- WREG32(HDP_NONSURFACE_SIZE, (rdev->mc.mc_vram_size - 1) | 0x3FF);
+ WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF);
if (rdev->flags & RADEON_IS_AGP) {
WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 16);
WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 16);
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c
index 0d9a42c..2f04757 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
@@ -77,7 +77,7 @@
/**
* Limits for the pool. They are handled without locks because only place where
* they may change is in sysfs store. They won't have immediate effect anyway
- * so forcing serialiazation to access them is pointless.
+ * so forcing serialization to access them is pointless.
*/
struct ttm_pool_opts {
@@ -165,16 +165,18 @@
m->options.small = val;
else if (attr == &ttm_page_pool_alloc_size) {
if (val > NUM_PAGES_TO_ALLOC*8) {
- printk(KERN_ERR "[ttm] Setting allocation size to %lu "
- "is not allowed. Recomended size is "
- "%lu\n",
- NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 7),
- NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10));
+ printk(KERN_ERR TTM_PFX
+ "Setting allocation size to %lu "
+ "is not allowed. Recommended size is "
+ "%lu\n",
+ NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 7),
+ NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10));
return size;
} else if (val > NUM_PAGES_TO_ALLOC) {
- printk(KERN_WARNING "[ttm] Setting allocation size to "
- "larger than %lu is not recomended.\n",
- NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10));
+ printk(KERN_WARNING TTM_PFX
+ "Setting allocation size to "
+ "larger than %lu is not recommended.\n",
+ NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10));
}
m->options.alloc_size = val;
}
@@ -277,7 +279,7 @@
{
unsigned i;
if (set_pages_array_wb(pages, npages))
- printk(KERN_ERR "[ttm] Failed to set %d pages to wb!\n",
+ printk(KERN_ERR TTM_PFX "Failed to set %d pages to wb!\n",
npages);
for (i = 0; i < npages; ++i)
__free_page(pages[i]);
@@ -313,7 +315,8 @@
pages_to_free = kmalloc(npages_to_free * sizeof(struct page *),
GFP_KERNEL);
if (!pages_to_free) {
- printk(KERN_ERR "Failed to allocate memory for pool free operation.\n");
+ printk(KERN_ERR TTM_PFX
+ "Failed to allocate memory for pool free operation.\n");
return 0;
}
@@ -390,7 +393,7 @@
}
/**
- * Calback for mm to request pool to reduce number of page held.
+ * Callback for mm to request pool to reduce number of page held.
*/
static int ttm_pool_mm_shrink(int shrink_pages, gfp_t gfp_mask)
{
@@ -433,14 +436,16 @@
case tt_uncached:
r = set_pages_array_uc(pages, cpages);
if (r)
- printk(KERN_ERR "[ttm] Failed to set %d pages to uc!\n",
- cpages);
+ printk(KERN_ERR TTM_PFX
+ "Failed to set %d pages to uc!\n",
+ cpages);
break;
case tt_wc:
r = set_pages_array_wc(pages, cpages);
if (r)
- printk(KERN_ERR "[ttm] Failed to set %d pages to wc!\n",
- cpages);
+ printk(KERN_ERR TTM_PFX
+ "Failed to set %d pages to wc!\n",
+ cpages);
break;
default:
break;
@@ -458,7 +463,7 @@
struct page **failed_pages, unsigned cpages)
{
unsigned i;
- /* Failed pages has to be reed */
+ /* Failed pages have to be freed */
for (i = 0; i < cpages; ++i) {
list_del(&failed_pages[i]->lru);
__free_page(failed_pages[i]);
@@ -485,7 +490,8 @@
caching_array = kmalloc(max_cpages*sizeof(struct page *), GFP_KERNEL);
if (!caching_array) {
- printk(KERN_ERR "[ttm] unable to allocate table for new pages.");
+ printk(KERN_ERR TTM_PFX
+ "Unable to allocate table for new pages.");
return -ENOMEM;
}
@@ -493,12 +499,13 @@
p = alloc_page(gfp_flags);
if (!p) {
- printk(KERN_ERR "[ttm] unable to get page %u\n", i);
+ printk(KERN_ERR TTM_PFX "Unable to get page %u.\n", i);
/* store already allocated pages in the pool after
* setting the caching state */
if (cpages) {
- r = ttm_set_pages_caching(caching_array, cstate, cpages);
+ r = ttm_set_pages_caching(caching_array,
+ cstate, cpages);
if (r)
ttm_handle_caching_state_failure(pages,
ttm_flags, cstate,
@@ -590,7 +597,8 @@
++pool->nrefills;
pool->npages += alloc_size;
} else {
- printk(KERN_ERR "[ttm] Failed to fill pool (%p).", pool);
+ printk(KERN_ERR TTM_PFX
+ "Failed to fill pool (%p).", pool);
/* If we have any pages left put them to the pool. */
list_for_each_entry(p, &pool->list, lru) {
++cpages;
@@ -659,7 +667,7 @@
{
struct ttm_page_pool *pool = ttm_get_pool(flags, cstate);
struct page *p = NULL;
- int gfp_flags = 0;
+ int gfp_flags = GFP_USER;
int r;
/* set zero flag for page allocation if required */
@@ -671,13 +679,14 @@
if (flags & TTM_PAGE_FLAG_DMA32)
gfp_flags |= GFP_DMA32;
else
- gfp_flags |= __GFP_HIGHMEM;
+ gfp_flags |= GFP_HIGHUSER;
for (r = 0; r < count; ++r) {
p = alloc_page(gfp_flags);
if (!p) {
- printk(KERN_ERR "[ttm] unable to allocate page.");
+ printk(KERN_ERR TTM_PFX
+ "Unable to allocate page.");
return -ENOMEM;
}
@@ -709,8 +718,9 @@
if (r) {
/* If there is any pages in the list put them back to
* the pool. */
- printk(KERN_ERR "[ttm] Failed to allocate extra pages "
- "for large request.");
+ printk(KERN_ERR TTM_PFX
+ "Failed to allocate extra pages "
+ "for large request.");
ttm_put_pages(pages, 0, flags, cstate);
return r;
}
@@ -778,7 +788,7 @@
if (atomic_add_return(1, &_manager.page_alloc_inited) > 1)
return 0;
- printk(KERN_INFO "[ttm] Initializing pool allocator.\n");
+ printk(KERN_INFO TTM_PFX "Initializing pool allocator.\n");
ttm_page_pool_init_locked(&_manager.wc_pool, GFP_HIGHUSER, "wc");
@@ -813,7 +823,7 @@
if (atomic_sub_return(1, &_manager.page_alloc_inited) > 0)
return;
- printk(KERN_INFO "[ttm] Finilizing pool allocator.\n");
+ printk(KERN_INFO TTM_PFX "Finalizing pool allocator.\n");
ttm_pool_mm_shrink_fini(&_manager);
for (i = 0; i < NUM_POOLS; ++i)
diff --git a/drivers/gpu/drm/vmwgfx/Makefile b/drivers/gpu/drm/vmwgfx/Makefile
index 1a3cb68..4505e17 100644
--- a/drivers/gpu/drm/vmwgfx/Makefile
+++ b/drivers/gpu/drm/vmwgfx/Makefile
@@ -4,6 +4,6 @@
vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \
vmwgfx_fb.o vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_buffer.o \
vmwgfx_fifo.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \
- vmwgfx_overlay.o
+ vmwgfx_overlay.o vmwgfx_fence.o
obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 0c9c081..b793c8c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -88,6 +88,9 @@
#define DRM_IOCTL_VMW_FENCE_WAIT \
DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_FENCE_WAIT, \
struct drm_vmw_fence_wait_arg)
+#define DRM_IOCTL_VMW_UPDATE_LAYOUT \
+ DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_UPDATE_LAYOUT, \
+ struct drm_vmw_update_layout_arg)
/**
@@ -135,7 +138,9 @@
VMW_IOCTL_DEF(DRM_IOCTL_VMW_FIFO_DEBUG, vmw_fifo_debug_ioctl,
DRM_AUTH | DRM_ROOT_ONLY | DRM_MASTER | DRM_UNLOCKED),
VMW_IOCTL_DEF(DRM_IOCTL_VMW_FENCE_WAIT, vmw_fence_wait_ioctl,
- DRM_AUTH | DRM_UNLOCKED)
+ DRM_AUTH | DRM_UNLOCKED),
+ VMW_IOCTL_DEF(DRM_IOCTL_VMW_UPDATE_LAYOUT, vmw_kms_update_layout_ioctl,
+ DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED)
};
static struct pci_device_id vmw_pci_id_list[] = {
@@ -318,6 +323,15 @@
goto out_err3;
}
+ /* Need mmio memory to check for fifo pitchlock cap. */
+ if (!(dev_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) &&
+ !(dev_priv->capabilities & SVGA_CAP_PITCHLOCK) &&
+ !vmw_fifo_have_pitchlock(dev_priv)) {
+ ret = -ENOSYS;
+ DRM_ERROR("Hardware has no pitchlock\n");
+ goto out_err4;
+ }
+
dev_priv->tdev = ttm_object_device_init
(dev_priv->mem_global_ref.object, 12);
@@ -399,8 +413,6 @@
{
struct vmw_private *dev_priv = vmw_priv(dev);
- DRM_INFO(VMWGFX_DRIVER_NAME " unload.\n");
-
unregister_pm_notifier(&dev_priv->pm_nb);
vmw_fb_close(dev_priv);
@@ -546,7 +558,6 @@
{
struct vmw_master *vmaster;
- DRM_INFO("Master create.\n");
vmaster = kzalloc(sizeof(*vmaster), GFP_KERNEL);
if (unlikely(vmaster == NULL))
return -ENOMEM;
@@ -563,7 +574,6 @@
{
struct vmw_master *vmaster = vmw_master(master);
- DRM_INFO("Master destroy.\n");
master->driver_priv = NULL;
kfree(vmaster);
}
@@ -579,8 +589,6 @@
struct vmw_master *vmaster = vmw_master(file_priv->master);
int ret = 0;
- DRM_INFO("Master set.\n");
-
if (active) {
BUG_ON(active != &dev_priv->fbdev_master);
ret = ttm_vt_lock(&active->lock, false, vmw_fp->tfile);
@@ -622,8 +630,6 @@
struct vmw_master *vmaster = vmw_master(file_priv->master);
int ret;
- DRM_INFO("Master drop.\n");
-
/**
* Make sure the master doesn't disappear while we have
* it locked.
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 356dc93..eaad520 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -41,12 +41,13 @@
#define VMWGFX_DRIVER_DATE "20100209"
#define VMWGFX_DRIVER_MAJOR 1
-#define VMWGFX_DRIVER_MINOR 0
+#define VMWGFX_DRIVER_MINOR 2
#define VMWGFX_DRIVER_PATCHLEVEL 0
#define VMWGFX_FILE_PAGE_OFFSET 0x00100000
#define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
#define VMWGFX_MAX_RELOCATIONS 2048
#define VMWGFX_MAX_GMRS 2048
+#define VMWGFX_MAX_DISPLAYS 16
struct vmw_fpriv {
struct drm_master *locked_master;
@@ -102,6 +103,13 @@
struct vmw_cursor_snooper snooper;
};
+struct vmw_fence_queue {
+ struct list_head head;
+ struct timespec lag;
+ struct timespec lag_time;
+ spinlock_t lock;
+};
+
struct vmw_fifo_state {
unsigned long reserved_size;
__le32 *dynamic_buffer;
@@ -115,6 +123,7 @@
uint32_t capabilities;
struct mutex fifo_mutex;
struct rw_semaphore rwsem;
+ struct vmw_fence_queue fence_queue;
};
struct vmw_relocation {
@@ -144,6 +153,14 @@
struct ttm_lock lock;
};
+struct vmw_vga_topology_state {
+ uint32_t width;
+ uint32_t height;
+ uint32_t primary;
+ uint32_t pos_x;
+ uint32_t pos_y;
+};
+
struct vmw_private {
struct ttm_bo_device bdev;
struct ttm_bo_global_ref bo_global_ref;
@@ -171,14 +188,19 @@
* VGA registers.
*/
+ struct vmw_vga_topology_state vga_save[VMWGFX_MAX_DISPLAYS];
uint32_t vga_width;
uint32_t vga_height;
uint32_t vga_depth;
uint32_t vga_bpp;
uint32_t vga_pseudo;
uint32_t vga_red_mask;
- uint32_t vga_blue_mask;
uint32_t vga_green_mask;
+ uint32_t vga_blue_mask;
+ uint32_t vga_bpl;
+ uint32_t vga_pitchlock;
+
+ uint32_t num_displays;
/*
* Framebuffer info.
@@ -393,6 +415,7 @@
extern void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason);
extern int vmw_fifo_mmap(struct file *filp, struct vm_area_struct *vma);
extern bool vmw_fifo_have_3d(struct vmw_private *dev_priv);
+extern bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv);
/**
* TTM glue - vmwgfx_ttm_glue.c
@@ -441,6 +464,23 @@
uint32_t sequence,
bool interruptible,
unsigned long timeout);
+extern void vmw_update_sequence(struct vmw_private *dev_priv,
+ struct vmw_fifo_state *fifo_state);
+
+
+/**
+ * Rudimentary fence objects currently used only for throttling -
+ * vmwgfx_fence.c
+ */
+
+extern void vmw_fence_queue_init(struct vmw_fence_queue *queue);
+extern void vmw_fence_queue_takedown(struct vmw_fence_queue *queue);
+extern int vmw_fence_push(struct vmw_fence_queue *queue,
+ uint32_t sequence);
+extern int vmw_fence_pull(struct vmw_fence_queue *queue,
+ uint32_t signaled_sequence);
+extern int vmw_wait_lag(struct vmw_private *dev_priv,
+ struct vmw_fence_queue *queue, uint32_t us);
/**
* Kernel framebuffer - vmwgfx_fb.c
@@ -466,6 +506,11 @@
struct ttm_object_file *tfile,
struct ttm_buffer_object *bo,
SVGA3dCmdHeader *header);
+void vmw_kms_write_svga(struct vmw_private *vmw_priv,
+ unsigned width, unsigned height, unsigned pitch,
+ unsigned bbp, unsigned depth);
+int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
/**
* Overlay control - vmwgfx_overlay.c
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index dbd36b8..8e39685 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -644,6 +644,7 @@
ret = copy_from_user(cmd, user_cmd, arg->command_size);
if (unlikely(ret != 0)) {
+ ret = -EFAULT;
DRM_ERROR("Failed copying commands.\n");
goto out_commit;
}
@@ -669,6 +670,15 @@
goto out_err;
vmw_apply_relocations(sw_context);
+
+ if (arg->throttle_us) {
+ ret = vmw_wait_lag(dev_priv, &dev_priv->fifo.fence_queue,
+ arg->throttle_us);
+
+ if (unlikely(ret != 0))
+ goto out_err;
+ }
+
vmw_fifo_commit(dev_priv, arg->command_size);
ret = vmw_fifo_send_fence(dev_priv, &sequence);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
index 7421aaa..b0866f04e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
@@ -132,16 +132,14 @@
return -EINVAL;
}
- /* without multimon its hard to resize */
- if (!(vmw_priv->capabilities & SVGA_CAP_MULTIMON) &&
- (var->xres != par->max_width ||
- var->yres != par->max_height)) {
- DRM_ERROR("Tried to resize, but we don't have multimon\n");
+ if (!(vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) &&
+ (var->xoffset != 0 || var->yoffset != 0)) {
+ DRM_ERROR("Can not handle panning without display topology\n");
return -EINVAL;
}
- if (var->xres > par->max_width ||
- var->yres > par->max_height) {
+ if ((var->xoffset + var->xres) > par->max_width ||
+ (var->yoffset + var->yres) > par->max_height) {
DRM_ERROR("Requested geom can not fit in framebuffer\n");
return -EINVAL;
}
@@ -154,27 +152,11 @@
struct vmw_fb_par *par = info->par;
struct vmw_private *vmw_priv = par->vmw_priv;
- if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) {
- vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
- vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
- vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
- vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
- vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
- vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, 0);
- vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
- vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
-
- vmw_write(vmw_priv, SVGA_REG_ENABLE, 1);
- vmw_write(vmw_priv, SVGA_REG_WIDTH, par->max_width);
- vmw_write(vmw_priv, SVGA_REG_HEIGHT, par->max_height);
- vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, par->bpp);
- vmw_write(vmw_priv, SVGA_REG_DEPTH, par->depth);
- vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
- vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
- vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
-
+ vmw_kms_write_svga(vmw_priv, info->var.xres, info->var.yres,
+ info->fix.line_length,
+ par->bpp, par->depth);
+ if (vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) {
/* TODO check if pitch and offset changes */
-
vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
@@ -183,13 +165,13 @@
vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, info->var.xres);
vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, info->var.yres);
vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
- } else {
- vmw_write(vmw_priv, SVGA_REG_WIDTH, info->var.xres);
- vmw_write(vmw_priv, SVGA_REG_HEIGHT, info->var.yres);
-
- /* TODO check if pitch and offset changes */
}
+ /* This is really helpful since if this fails the user
+ * can probably not see anything on the screen.
+ */
+ WARN_ON(vmw_read(vmw_priv, SVGA_REG_FB_OFFSET) != 0);
+
return 0;
}
@@ -416,48 +398,23 @@
unsigned fb_bbp, fb_depth, fb_offset, fb_pitch, fb_size;
int ret;
+ /* XXX These shouldn't be hardcoded. */
initial_width = 800;
initial_height = 600;
fb_bbp = 32;
fb_depth = 24;
- if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) {
- fb_width = min(vmw_priv->fb_max_width, (unsigned)2048);
- fb_height = min(vmw_priv->fb_max_height, (unsigned)2048);
- } else {
- fb_width = min(vmw_priv->fb_max_width, initial_width);
- fb_height = min(vmw_priv->fb_max_height, initial_height);
- }
+ /* XXX As shouldn't these be as well. */
+ fb_width = min(vmw_priv->fb_max_width, (unsigned)2048);
+ fb_height = min(vmw_priv->fb_max_height, (unsigned)2048);
initial_width = min(fb_width, initial_width);
initial_height = min(fb_height, initial_height);
- vmw_write(vmw_priv, SVGA_REG_WIDTH, fb_width);
- vmw_write(vmw_priv, SVGA_REG_HEIGHT, fb_height);
- vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, fb_bbp);
- vmw_write(vmw_priv, SVGA_REG_DEPTH, fb_depth);
- vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
- vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
- vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
-
- fb_size = vmw_read(vmw_priv, SVGA_REG_FB_SIZE);
+ fb_pitch = fb_width * fb_bbp / 8;
+ fb_size = fb_pitch * fb_height;
fb_offset = vmw_read(vmw_priv, SVGA_REG_FB_OFFSET);
- fb_pitch = vmw_read(vmw_priv, SVGA_REG_BYTES_PER_LINE);
-
- DRM_DEBUG("width %u\n", vmw_read(vmw_priv, SVGA_REG_MAX_WIDTH));
- DRM_DEBUG("height %u\n", vmw_read(vmw_priv, SVGA_REG_MAX_HEIGHT));
- DRM_DEBUG("width %u\n", vmw_read(vmw_priv, SVGA_REG_WIDTH));
- DRM_DEBUG("height %u\n", vmw_read(vmw_priv, SVGA_REG_HEIGHT));
- DRM_DEBUG("bpp %u\n", vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL));
- DRM_DEBUG("depth %u\n", vmw_read(vmw_priv, SVGA_REG_DEPTH));
- DRM_DEBUG("bpl %u\n", vmw_read(vmw_priv, SVGA_REG_BYTES_PER_LINE));
- DRM_DEBUG("r mask %08x\n", vmw_read(vmw_priv, SVGA_REG_RED_MASK));
- DRM_DEBUG("g mask %08x\n", vmw_read(vmw_priv, SVGA_REG_GREEN_MASK));
- DRM_DEBUG("b mask %08x\n", vmw_read(vmw_priv, SVGA_REG_BLUE_MASK));
- DRM_DEBUG("fb_offset 0x%08x\n", fb_offset);
- DRM_DEBUG("fb_pitch %u\n", fb_pitch);
- DRM_DEBUG("fb_size %u kiB\n", fb_size / 1024);
info = framebuffer_alloc(sizeof(*par), device);
if (!info)
@@ -659,6 +616,10 @@
goto err_unlock;
ret = ttm_bo_validate(bo, &ne_placement, false, false, false);
+
+ /* Could probably bug on */
+ WARN_ON(bo->offset != 0);
+
ttm_bo_unreserve(bo);
err_unlock:
ttm_write_unlock(&vmw_priv->active_master->lock);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
new file mode 100644
index 0000000..61eacc1
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
@@ -0,0 +1,173 @@
+/**************************************************************************
+ *
+ * Copyright (C) 2010 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, 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 (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "vmwgfx_drv.h"
+
+struct vmw_fence {
+ struct list_head head;
+ uint32_t sequence;
+ struct timespec submitted;
+};
+
+void vmw_fence_queue_init(struct vmw_fence_queue *queue)
+{
+ INIT_LIST_HEAD(&queue->head);
+ queue->lag = ns_to_timespec(0);
+ getrawmonotonic(&queue->lag_time);
+ spin_lock_init(&queue->lock);
+}
+
+void vmw_fence_queue_takedown(struct vmw_fence_queue *queue)
+{
+ struct vmw_fence *fence, *next;
+
+ spin_lock(&queue->lock);
+ list_for_each_entry_safe(fence, next, &queue->head, head) {
+ kfree(fence);
+ }
+ spin_unlock(&queue->lock);
+}
+
+int vmw_fence_push(struct vmw_fence_queue *queue,
+ uint32_t sequence)
+{
+ struct vmw_fence *fence = kmalloc(sizeof(*fence), GFP_KERNEL);
+
+ if (unlikely(!fence))
+ return -ENOMEM;
+
+ fence->sequence = sequence;
+ getrawmonotonic(&fence->submitted);
+ spin_lock(&queue->lock);
+ list_add_tail(&fence->head, &queue->head);
+ spin_unlock(&queue->lock);
+
+ return 0;
+}
+
+int vmw_fence_pull(struct vmw_fence_queue *queue,
+ uint32_t signaled_sequence)
+{
+ struct vmw_fence *fence, *next;
+ struct timespec now;
+ bool updated = false;
+
+ spin_lock(&queue->lock);
+ getrawmonotonic(&now);
+
+ if (list_empty(&queue->head)) {
+ queue->lag = ns_to_timespec(0);
+ queue->lag_time = now;
+ updated = true;
+ goto out_unlock;
+ }
+
+ list_for_each_entry_safe(fence, next, &queue->head, head) {
+ if (signaled_sequence - fence->sequence > (1 << 30))
+ continue;
+
+ queue->lag = timespec_sub(now, fence->submitted);
+ queue->lag_time = now;
+ updated = true;
+ list_del(&fence->head);
+ kfree(fence);
+ }
+
+out_unlock:
+ spin_unlock(&queue->lock);
+
+ return (updated) ? 0 : -EBUSY;
+}
+
+static struct timespec vmw_timespec_add(struct timespec t1,
+ struct timespec t2)
+{
+ t1.tv_sec += t2.tv_sec;
+ t1.tv_nsec += t2.tv_nsec;
+ if (t1.tv_nsec >= 1000000000L) {
+ t1.tv_sec += 1;
+ t1.tv_nsec -= 1000000000L;
+ }
+
+ return t1;
+}
+
+static struct timespec vmw_fifo_lag(struct vmw_fence_queue *queue)
+{
+ struct timespec now;
+
+ spin_lock(&queue->lock);
+ getrawmonotonic(&now);
+ queue->lag = vmw_timespec_add(queue->lag,
+ timespec_sub(now, queue->lag_time));
+ queue->lag_time = now;
+ spin_unlock(&queue->lock);
+ return queue->lag;
+}
+
+
+static bool vmw_lag_lt(struct vmw_fence_queue *queue,
+ uint32_t us)
+{
+ struct timespec lag, cond;
+
+ cond = ns_to_timespec((s64) us * 1000);
+ lag = vmw_fifo_lag(queue);
+ return (timespec_compare(&lag, &cond) < 1);
+}
+
+int vmw_wait_lag(struct vmw_private *dev_priv,
+ struct vmw_fence_queue *queue, uint32_t us)
+{
+ struct vmw_fence *fence;
+ uint32_t sequence;
+ int ret;
+
+ while (!vmw_lag_lt(queue, us)) {
+ spin_lock(&queue->lock);
+ if (list_empty(&queue->head))
+ sequence = atomic_read(&dev_priv->fence_seq);
+ else {
+ fence = list_first_entry(&queue->head,
+ struct vmw_fence, head);
+ sequence = fence->sequence;
+ }
+ spin_unlock(&queue->lock);
+
+ ret = vmw_wait_fence(dev_priv, false, sequence, true,
+ 3*HZ);
+
+ if (unlikely(ret != 0))
+ return ret;
+
+ (void) vmw_fence_pull(queue, sequence);
+ }
+ return 0;
+}
+
+
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
index 39d43a0..e6a1eb7 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
@@ -34,6 +34,9 @@
__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
uint32_t fifo_min, hwversion;
+ if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
+ return false;
+
fifo_min = ioread32(fifo_mem + SVGA_FIFO_MIN);
if (fifo_min <= SVGA_FIFO_3D_HWVERSION * sizeof(unsigned int))
return false;
@@ -48,6 +51,21 @@
return true;
}
+bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv)
+{
+ __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+ uint32_t caps;
+
+ if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
+ return false;
+
+ caps = ioread32(fifo_mem + SVGA_FIFO_CAPABILITIES);
+ if (caps & SVGA_FIFO_CAP_PITCHLOCK)
+ return true;
+
+ return false;
+}
+
int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
{
__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
@@ -120,7 +138,7 @@
atomic_set(&dev_priv->fence_seq, dev_priv->last_read_sequence);
iowrite32(dev_priv->last_read_sequence, fifo_mem + SVGA_FIFO_FENCE);
-
+ vmw_fence_queue_init(&fifo->fence_queue);
return vmw_fifo_send_fence(dev_priv, &dummy);
out_err:
vfree(fifo->static_buffer);
@@ -159,6 +177,7 @@
dev_priv->enable_state);
mutex_unlock(&dev_priv->hw_mutex);
+ vmw_fence_queue_takedown(&fifo->fence_queue);
if (likely(fifo->last_buffer != NULL)) {
vfree(fifo->last_buffer);
@@ -484,6 +503,8 @@
fifo_state->last_buffer_add = true;
vmw_fifo_commit(dev_priv, bytes);
fifo_state->last_buffer_add = false;
+ (void) vmw_fence_push(&fifo_state->fence_queue, *sequence);
+ vmw_update_sequence(dev_priv, fifo_state);
out_err:
return ret;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
index 4d7cb53..e92298a 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
@@ -64,22 +64,33 @@
return (busy == 0);
}
+void vmw_update_sequence(struct vmw_private *dev_priv,
+ struct vmw_fifo_state *fifo_state)
+{
+ __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+
+ uint32_t sequence = ioread32(fifo_mem + SVGA_FIFO_FENCE);
+
+ if (dev_priv->last_read_sequence != sequence) {
+ dev_priv->last_read_sequence = sequence;
+ vmw_fence_pull(&fifo_state->fence_queue, sequence);
+ }
+}
bool vmw_fence_signaled(struct vmw_private *dev_priv,
uint32_t sequence)
{
- __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
struct vmw_fifo_state *fifo_state;
bool ret;
if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
return true;
- dev_priv->last_read_sequence = ioread32(fifo_mem + SVGA_FIFO_FENCE);
+ fifo_state = &dev_priv->fifo;
+ vmw_update_sequence(dev_priv, fifo_state);
if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
return true;
- fifo_state = &dev_priv->fifo;
if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE) &&
vmw_fifo_idle(dev_priv, sequence))
return true;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index bbc7c4c..f1d6261 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -30,6 +30,8 @@
/* Might need a hrtimer here? */
#define VMWGFX_PRESENT_RATE ((HZ / 60 > 0) ? HZ / 60 : 1)
+static int vmw_surface_dmabuf_pin(struct vmw_framebuffer *vfb);
+static int vmw_surface_dmabuf_unpin(struct vmw_framebuffer *vfb);
void vmw_display_unit_cleanup(struct vmw_display_unit *du)
{
@@ -326,6 +328,7 @@
struct vmw_framebuffer_surface {
struct vmw_framebuffer base;
struct vmw_surface *surface;
+ struct vmw_dma_buffer *buffer;
struct delayed_work d_work;
struct mutex work_lock;
bool present_fs;
@@ -500,8 +503,8 @@
vfbs->base.base.depth = 24;
vfbs->base.base.width = width;
vfbs->base.base.height = height;
- vfbs->base.pin = NULL;
- vfbs->base.unpin = NULL;
+ vfbs->base.pin = &vmw_surface_dmabuf_pin;
+ vfbs->base.unpin = &vmw_surface_dmabuf_unpin;
vfbs->surface = surface;
mutex_init(&vfbs->work_lock);
INIT_DELAYED_WORK(&vfbs->d_work, &vmw_framebuffer_present_fs_callback);
@@ -589,6 +592,40 @@
.create_handle = vmw_framebuffer_create_handle,
};
+static int vmw_surface_dmabuf_pin(struct vmw_framebuffer *vfb)
+{
+ struct vmw_private *dev_priv = vmw_priv(vfb->base.dev);
+ struct vmw_framebuffer_surface *vfbs =
+ vmw_framebuffer_to_vfbs(&vfb->base);
+ unsigned long size = vfbs->base.base.pitch * vfbs->base.base.height;
+ int ret;
+
+ vfbs->buffer = kzalloc(sizeof(*vfbs->buffer), GFP_KERNEL);
+ if (unlikely(vfbs->buffer == NULL))
+ return -ENOMEM;
+
+ vmw_overlay_pause_all(dev_priv);
+ ret = vmw_dmabuf_init(dev_priv, vfbs->buffer, size,
+ &vmw_vram_ne_placement,
+ false, &vmw_dmabuf_bo_free);
+ vmw_overlay_resume_all(dev_priv);
+
+ return ret;
+}
+
+static int vmw_surface_dmabuf_unpin(struct vmw_framebuffer *vfb)
+{
+ struct ttm_buffer_object *bo;
+ struct vmw_framebuffer_surface *vfbs =
+ vmw_framebuffer_to_vfbs(&vfb->base);
+
+ bo = &vfbs->buffer->base;
+ ttm_bo_unref(&bo);
+ vfbs->buffer = NULL;
+
+ return 0;
+}
+
static int vmw_framebuffer_dmabuf_pin(struct vmw_framebuffer *vfb)
{
struct vmw_private *dev_priv = vmw_priv(vfb->base.dev);
@@ -596,33 +633,15 @@
vmw_framebuffer_to_vfbd(&vfb->base);
int ret;
+
vmw_overlay_pause_all(dev_priv);
ret = vmw_dmabuf_to_start_of_vram(dev_priv, vfbd->buffer);
- if (dev_priv->capabilities & SVGA_CAP_MULTIMON) {
- vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
- vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, 0);
- vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
- vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
- vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
- vmw_write(dev_priv, SVGA_REG_DISPLAY_WIDTH, 0);
- vmw_write(dev_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
- vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
-
- vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
- vmw_write(dev_priv, SVGA_REG_WIDTH, vfb->base.width);
- vmw_write(dev_priv, SVGA_REG_HEIGHT, vfb->base.height);
- vmw_write(dev_priv, SVGA_REG_BITS_PER_PIXEL, vfb->base.bits_per_pixel);
- vmw_write(dev_priv, SVGA_REG_DEPTH, vfb->base.depth);
- vmw_write(dev_priv, SVGA_REG_RED_MASK, 0x00ff0000);
- vmw_write(dev_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
- vmw_write(dev_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
- } else
- WARN_ON(true);
-
vmw_overlay_resume_all(dev_priv);
+ WARN_ON(ret != 0);
+
return 0;
}
@@ -668,7 +687,7 @@
/* XXX get the first 3 from the surface info */
vfbd->base.base.bits_per_pixel = 32;
- vfbd->base.base.pitch = width * 32 / 4;
+ vfbd->base.base.pitch = width * vfbd->base.base.bits_per_pixel / 8;
vfbd->base.base.depth = 24;
vfbd->base.base.width = width;
vfbd->base.base.height = height;
@@ -765,8 +784,9 @@
dev->mode_config.funcs = &vmw_kms_funcs;
dev->mode_config.min_width = 1;
dev->mode_config.min_height = 1;
- dev->mode_config.max_width = dev_priv->fb_max_width;
- dev->mode_config.max_height = dev_priv->fb_max_height;
+ /* assumed largest fb size */
+ dev->mode_config.max_width = 8192;
+ dev->mode_config.max_height = 8192;
ret = vmw_kms_init_legacy_display_system(dev_priv);
@@ -826,49 +846,140 @@
return ret;
}
+void vmw_kms_write_svga(struct vmw_private *vmw_priv,
+ unsigned width, unsigned height, unsigned pitch,
+ unsigned bbp, unsigned depth)
+{
+ if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
+ vmw_write(vmw_priv, SVGA_REG_PITCHLOCK, pitch);
+ else if (vmw_fifo_have_pitchlock(vmw_priv))
+ iowrite32(pitch, vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
+ vmw_write(vmw_priv, SVGA_REG_WIDTH, width);
+ vmw_write(vmw_priv, SVGA_REG_HEIGHT, height);
+ vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, bbp);
+ vmw_write(vmw_priv, SVGA_REG_DEPTH, depth);
+ vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
+ vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
+ vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
+}
+
int vmw_kms_save_vga(struct vmw_private *vmw_priv)
{
- /*
- * setup a single multimon monitor with the size
- * of 0x0, this stops the UI from resizing when we
- * change the framebuffer size
- */
- if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) {
- vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
- vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
- vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
- vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
- vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
- vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, 0);
- vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
- vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
- }
+ struct vmw_vga_topology_state *save;
+ uint32_t i;
vmw_priv->vga_width = vmw_read(vmw_priv, SVGA_REG_WIDTH);
vmw_priv->vga_height = vmw_read(vmw_priv, SVGA_REG_HEIGHT);
- vmw_priv->vga_bpp = vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL);
vmw_priv->vga_depth = vmw_read(vmw_priv, SVGA_REG_DEPTH);
+ vmw_priv->vga_bpp = vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL);
vmw_priv->vga_pseudo = vmw_read(vmw_priv, SVGA_REG_PSEUDOCOLOR);
vmw_priv->vga_red_mask = vmw_read(vmw_priv, SVGA_REG_RED_MASK);
- vmw_priv->vga_green_mask = vmw_read(vmw_priv, SVGA_REG_GREEN_MASK);
vmw_priv->vga_blue_mask = vmw_read(vmw_priv, SVGA_REG_BLUE_MASK);
+ vmw_priv->vga_green_mask = vmw_read(vmw_priv, SVGA_REG_GREEN_MASK);
+ if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
+ vmw_priv->vga_pitchlock =
+ vmw_read(vmw_priv, SVGA_REG_PITCHLOCK);
+ else if (vmw_fifo_have_pitchlock(vmw_priv))
+ vmw_priv->vga_pitchlock = ioread32(vmw_priv->mmio_virt +
+ SVGA_FIFO_PITCHLOCK);
+ if (!(vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY))
+ return 0;
+
+ vmw_priv->num_displays = vmw_read(vmw_priv,
+ SVGA_REG_NUM_GUEST_DISPLAYS);
+
+ for (i = 0; i < vmw_priv->num_displays; ++i) {
+ save = &vmw_priv->vga_save[i];
+ vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, i);
+ save->primary = vmw_read(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY);
+ save->pos_x = vmw_read(vmw_priv, SVGA_REG_DISPLAY_POSITION_X);
+ save->pos_y = vmw_read(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y);
+ save->width = vmw_read(vmw_priv, SVGA_REG_DISPLAY_WIDTH);
+ save->height = vmw_read(vmw_priv, SVGA_REG_DISPLAY_HEIGHT);
+ vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+ }
return 0;
}
int vmw_kms_restore_vga(struct vmw_private *vmw_priv)
{
+ struct vmw_vga_topology_state *save;
+ uint32_t i;
+
vmw_write(vmw_priv, SVGA_REG_WIDTH, vmw_priv->vga_width);
vmw_write(vmw_priv, SVGA_REG_HEIGHT, vmw_priv->vga_height);
- vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, vmw_priv->vga_bpp);
vmw_write(vmw_priv, SVGA_REG_DEPTH, vmw_priv->vga_depth);
+ vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, vmw_priv->vga_bpp);
vmw_write(vmw_priv, SVGA_REG_PSEUDOCOLOR, vmw_priv->vga_pseudo);
vmw_write(vmw_priv, SVGA_REG_RED_MASK, vmw_priv->vga_red_mask);
vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, vmw_priv->vga_green_mask);
vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, vmw_priv->vga_blue_mask);
+ if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
+ vmw_write(vmw_priv, SVGA_REG_PITCHLOCK,
+ vmw_priv->vga_pitchlock);
+ else if (vmw_fifo_have_pitchlock(vmw_priv))
+ iowrite32(vmw_priv->vga_pitchlock,
+ vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
- /* TODO check for multimon */
- vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 0);
+ if (!(vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY))
+ return 0;
+
+ for (i = 0; i < vmw_priv->num_displays; ++i) {
+ save = &vmw_priv->vga_save[i];
+ vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, i);
+ vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, save->primary);
+ vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, save->pos_x);
+ vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, save->pos_y);
+ vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, save->width);
+ vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, save->height);
+ vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+ }
return 0;
}
+
+int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct vmw_private *dev_priv = vmw_priv(dev);
+ struct drm_vmw_update_layout_arg *arg =
+ (struct drm_vmw_update_layout_arg *)data;
+ struct vmw_master *vmaster = vmw_master(file_priv->master);
+ void __user *user_rects;
+ struct drm_vmw_rect *rects;
+ unsigned rects_size;
+ int ret;
+
+ ret = ttm_read_lock(&vmaster->lock, true);
+ if (unlikely(ret != 0))
+ return ret;
+
+ if (!arg->num_outputs) {
+ struct drm_vmw_rect def_rect = {0, 0, 800, 600};
+ vmw_kms_ldu_update_layout(dev_priv, 1, &def_rect);
+ goto out_unlock;
+ }
+
+ rects_size = arg->num_outputs * sizeof(struct drm_vmw_rect);
+ rects = kzalloc(rects_size, GFP_KERNEL);
+ if (unlikely(!rects)) {
+ ret = -ENOMEM;
+ goto out_unlock;
+ }
+
+ user_rects = (void __user *)(unsigned long)arg->rects;
+ ret = copy_from_user(rects, user_rects, rects_size);
+ if (unlikely(ret != 0)) {
+ DRM_ERROR("Failed to get rects.\n");
+ goto out_free;
+ }
+
+ vmw_kms_ldu_update_layout(dev_priv, arg->num_outputs, rects);
+
+out_free:
+ kfree(rects);
+out_unlock:
+ ttm_read_unlock(&vmaster->lock);
+ return ret;
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index 8b95249..8a398a0 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -94,9 +94,11 @@
int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
/*
- * Legacy display unit functions - vmwgfx_ldu.h
+ * Legacy display unit functions - vmwgfx_ldu.c
*/
int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv);
int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv);
+int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num,
+ struct drm_vmw_rect *rects);
#endif
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index 9089159..cfaf690 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -38,6 +38,7 @@
struct list_head active;
unsigned num_active;
+ unsigned last_num_active;
struct vmw_framebuffer *fb;
};
@@ -48,9 +49,12 @@
struct vmw_legacy_display_unit {
struct vmw_display_unit base;
- struct list_head active;
+ unsigned pref_width;
+ unsigned pref_height;
+ bool pref_active;
+ struct drm_display_mode *pref_mode;
- unsigned unit;
+ struct list_head active;
};
static void vmw_ldu_destroy(struct vmw_legacy_display_unit *ldu)
@@ -88,23 +92,44 @@
{
struct vmw_legacy_display *lds = dev_priv->ldu_priv;
struct vmw_legacy_display_unit *entry;
- struct drm_crtc *crtc;
+ struct drm_framebuffer *fb = NULL;
+ struct drm_crtc *crtc = NULL;
int i = 0;
- /* to stop the screen from changing size on resize */
- vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 0);
- for (i = 0; i < lds->num_active; i++) {
- vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, i);
- vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, !i);
- vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
- vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
- vmw_write(dev_priv, SVGA_REG_DISPLAY_WIDTH, 0);
- vmw_write(dev_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
- vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+ /* If there is no display topology the host just assumes
+ * that the guest will set the same layout as the host.
+ */
+ if (!(dev_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY)) {
+ int w = 0, h = 0;
+ list_for_each_entry(entry, &lds->active, active) {
+ crtc = &entry->base.crtc;
+ w = max(w, crtc->x + crtc->mode.hdisplay);
+ h = max(h, crtc->y + crtc->mode.vdisplay);
+ i++;
+ }
+
+ if (crtc == NULL)
+ return 0;
+ fb = entry->base.crtc.fb;
+
+ vmw_kms_write_svga(dev_priv, w, h, fb->pitch,
+ fb->bits_per_pixel, fb->depth);
+
+ return 0;
}
- /* Now set the mode */
- vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, lds->num_active);
+ if (!list_empty(&lds->active)) {
+ entry = list_entry(lds->active.next, typeof(*entry), active);
+ fb = entry->base.crtc.fb;
+
+ vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitch,
+ fb->bits_per_pixel, fb->depth);
+ }
+
+ /* Make sure we always show something. */
+ vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS,
+ lds->num_active ? lds->num_active : 1);
+
i = 0;
list_for_each_entry(entry, &lds->active, active) {
crtc = &entry->base.crtc;
@@ -120,6 +145,10 @@
i++;
}
+ BUG_ON(i != lds->num_active);
+
+ lds->last_num_active = lds->num_active;
+
return 0;
}
@@ -130,6 +159,7 @@
if (list_empty(&ldu->active))
return 0;
+ /* Must init otherwise list_empty(&ldu->active) will not work. */
list_del_init(&ldu->active);
if (--(ld->num_active) == 0) {
BUG_ON(!ld->fb);
@@ -149,24 +179,29 @@
struct vmw_legacy_display_unit *entry;
struct list_head *at;
+ BUG_ON(!ld->num_active && ld->fb);
+ if (vfb != ld->fb) {
+ if (ld->fb && ld->fb->unpin)
+ ld->fb->unpin(ld->fb);
+ if (vfb->pin)
+ vfb->pin(vfb);
+ ld->fb = vfb;
+ }
+
if (!list_empty(&ldu->active))
return 0;
at = &ld->active;
list_for_each_entry(entry, &ld->active, active) {
- if (entry->unit > ldu->unit)
+ if (entry->base.unit > ldu->base.unit)
break;
at = &entry->active;
}
list_add(&ldu->active, at);
- if (ld->num_active++ == 0) {
- BUG_ON(ld->fb);
- if (vfb->pin)
- vfb->pin(vfb);
- ld->fb = vfb;
- }
+
+ ld->num_active++;
return 0;
}
@@ -208,6 +243,8 @@
/* ldu only supports one fb active at the time */
if (dev_priv->ldu_priv->fb && vfb &&
+ !(dev_priv->ldu_priv->num_active == 1 &&
+ !list_empty(&ldu->active)) &&
dev_priv->ldu_priv->fb != vfb) {
DRM_ERROR("Multiple framebuffers not supported\n");
return -EINVAL;
@@ -300,8 +337,7 @@
static enum drm_connector_status
vmw_ldu_connector_detect(struct drm_connector *connector)
{
- /* XXX vmwctrl should control connection status */
- if (vmw_connector_to_ldu(connector)->base.unit == 0)
+ if (vmw_connector_to_ldu(connector)->pref_active)
return connector_status_connected;
return connector_status_disconnected;
}
@@ -312,10 +348,9 @@
752, 800, 0, 480, 489, 492, 525, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
/* 800x600@60Hz */
- { DRM_MODE("800x600",
- DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
- 40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628,
- 0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+ { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
+ 968, 1056, 0, 600, 601, 605, 628, 0,
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
/* 1024x768@60Hz */
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
1184, 1344, 0, 768, 771, 777, 806, 0,
@@ -387,10 +422,34 @@
static int vmw_ldu_connector_fill_modes(struct drm_connector *connector,
uint32_t max_width, uint32_t max_height)
{
+ struct vmw_legacy_display_unit *ldu = vmw_connector_to_ldu(connector);
struct drm_device *dev = connector->dev;
struct drm_display_mode *mode = NULL;
+ struct drm_display_mode prefmode = { DRM_MODE("preferred",
+ DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC)
+ };
int i;
+ /* Add preferred mode */
+ {
+ mode = drm_mode_duplicate(dev, &prefmode);
+ if (!mode)
+ return 0;
+ mode->hdisplay = ldu->pref_width;
+ mode->vdisplay = ldu->pref_height;
+ mode->vrefresh = drm_mode_vrefresh(mode);
+ drm_mode_probed_add(connector, mode);
+
+ if (ldu->pref_mode) {
+ list_del_init(&ldu->pref_mode->head);
+ drm_mode_destroy(dev, ldu->pref_mode);
+ }
+
+ ldu->pref_mode = mode;
+ }
+
for (i = 0; vmw_ldu_connector_builtin[i].type != 0; i++) {
if (vmw_ldu_connector_builtin[i].hdisplay > max_width ||
vmw_ldu_connector_builtin[i].vdisplay > max_height)
@@ -443,18 +502,21 @@
if (!ldu)
return -ENOMEM;
- ldu->unit = unit;
+ ldu->base.unit = unit;
crtc = &ldu->base.crtc;
encoder = &ldu->base.encoder;
connector = &ldu->base.connector;
+ INIT_LIST_HEAD(&ldu->active);
+
+ ldu->pref_active = (unit == 0);
+ ldu->pref_width = 800;
+ ldu->pref_height = 600;
+ ldu->pref_mode = NULL;
+
drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
DRM_MODE_CONNECTOR_LVDS);
- /* Initial status */
- if (unit == 0)
- connector->status = connector_status_connected;
- else
- connector->status = connector_status_disconnected;
+ connector->status = vmw_ldu_connector_detect(connector);
drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs,
DRM_MODE_ENCODER_LVDS);
@@ -462,8 +524,6 @@
encoder->possible_crtcs = (1 << unit);
encoder->possible_clones = 0;
- INIT_LIST_HEAD(&ldu->active);
-
drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs);
drm_connector_attach_property(connector,
@@ -487,18 +547,22 @@
INIT_LIST_HEAD(&dev_priv->ldu_priv->active);
dev_priv->ldu_priv->num_active = 0;
+ dev_priv->ldu_priv->last_num_active = 0;
dev_priv->ldu_priv->fb = NULL;
drm_mode_create_dirty_info_property(dev_priv->dev);
vmw_ldu_init(dev_priv, 0);
- vmw_ldu_init(dev_priv, 1);
- vmw_ldu_init(dev_priv, 2);
- vmw_ldu_init(dev_priv, 3);
- vmw_ldu_init(dev_priv, 4);
- vmw_ldu_init(dev_priv, 5);
- vmw_ldu_init(dev_priv, 6);
- vmw_ldu_init(dev_priv, 7);
+ /* for old hardware without multimon only enable one display */
+ if (dev_priv->capabilities & SVGA_CAP_MULTIMON) {
+ vmw_ldu_init(dev_priv, 1);
+ vmw_ldu_init(dev_priv, 2);
+ vmw_ldu_init(dev_priv, 3);
+ vmw_ldu_init(dev_priv, 4);
+ vmw_ldu_init(dev_priv, 5);
+ vmw_ldu_init(dev_priv, 6);
+ vmw_ldu_init(dev_priv, 7);
+ }
return 0;
}
@@ -514,3 +578,42 @@
return 0;
}
+
+int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num,
+ struct drm_vmw_rect *rects)
+{
+ struct drm_device *dev = dev_priv->dev;
+ struct vmw_legacy_display_unit *ldu;
+ struct drm_connector *con;
+ int i;
+
+ mutex_lock(&dev->mode_config.mutex);
+
+#if 0
+ DRM_INFO("%s: new layout ", __func__);
+ for (i = 0; i < (int)num; i++)
+ DRM_INFO("(%i, %i %ux%u) ", rects[i].x, rects[i].y,
+ rects[i].w, rects[i].h);
+ DRM_INFO("\n");
+#else
+ (void)i;
+#endif
+
+ list_for_each_entry(con, &dev->mode_config.connector_list, head) {
+ ldu = vmw_connector_to_ldu(con);
+ if (num > ldu->base.unit) {
+ ldu->pref_width = rects[ldu->base.unit].w;
+ ldu->pref_height = rects[ldu->base.unit].h;
+ ldu->pref_active = true;
+ } else {
+ ldu->pref_width = 800;
+ ldu->pref_height = 600;
+ ldu->pref_active = false;
+ }
+ con->status = vmw_ldu_connector_detect(con);
+ }
+
+ mutex_unlock(&dev->mode_config.mutex);
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
index ad566c8..df2036e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
@@ -358,6 +358,8 @@
if (stream->buf != buf)
stream->buf = vmw_dmabuf_reference(buf);
stream->saved = *arg;
+ /* stream is no longer stopped/paused */
+ stream->paused = false;
return 0;
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index f8fbbc6..8612378 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -597,8 +597,10 @@
ret = copy_from_user(srf->sizes, user_sizes,
srf->num_sizes * sizeof(*srf->sizes));
- if (unlikely(ret != 0))
+ if (unlikely(ret != 0)) {
+ ret = -EFAULT;
goto out_err1;
+ }
if (srf->scanout &&
srf->num_sizes == 1 &&
@@ -697,9 +699,11 @@
if (user_sizes)
ret = copy_to_user(user_sizes, srf->sizes,
srf->num_sizes * sizeof(*srf->sizes));
- if (unlikely(ret != 0))
+ if (unlikely(ret != 0)) {
DRM_ERROR("copy_to_user failed %p %u\n",
user_sizes, srf->num_sizes);
+ ret = -EFAULT;
+ }
out_bad_resource:
out_no_reference:
ttm_base_object_unref(&base);
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c
index 441e38c..b87569e 100644
--- a/drivers/gpu/vga/vgaarb.c
+++ b/drivers/gpu/vga/vgaarb.c
@@ -1,12 +1,32 @@
/*
- * vgaarb.c
+ * vgaarb.c: Implements the VGA arbitration. For details refer to
+ * Documentation/vgaarbiter.txt
+ *
*
* (C) Copyright 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org>
* (C) Copyright 2007 Paulo R. Zanoni <przanoni@gmail.com>
* (C) Copyright 2007, 2009 Tiago Vignatti <vignatti@freedesktop.org>
*
- * Implements the VGA arbitration. For details refer to
- * Documentation/vgaarbiter.txt
+ * 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 (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS
+ * IN THE SOFTWARE.
+ *
*/
#include <linux/module.h>
@@ -155,8 +175,8 @@
(vgadev->decodes & VGA_RSRC_LEGACY_MEM))
rsrc |= VGA_RSRC_LEGACY_MEM;
- pr_devel("%s: %d\n", __func__, rsrc);
- pr_devel("%s: owns: %d\n", __func__, vgadev->owns);
+ pr_debug("%s: %d\n", __func__, rsrc);
+ pr_debug("%s: owns: %d\n", __func__, vgadev->owns);
/* Check what resources we need to acquire */
wants = rsrc & ~vgadev->owns;
@@ -268,7 +288,7 @@
{
unsigned int old_locks = vgadev->locks;
- pr_devel("%s\n", __func__);
+ pr_debug("%s\n", __func__);
/* Update our counters, and account for equivalent legacy resources
* if we decode them
@@ -575,6 +595,7 @@
else
vga_decode_count--;
}
+ pr_debug("vgaarb: decoding count now is: %d\n", vga_decode_count);
}
void __vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes, bool userspace)
@@ -831,7 +852,7 @@
curr_pos += 5;
remaining -= 5;
- pr_devel("client 0x%p called 'lock'\n", priv);
+ pr_debug("client 0x%p called 'lock'\n", priv);
if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) {
ret_val = -EPROTO;
@@ -867,7 +888,7 @@
curr_pos += 7;
remaining -= 7;
- pr_devel("client 0x%p called 'unlock'\n", priv);
+ pr_debug("client 0x%p called 'unlock'\n", priv);
if (strncmp(curr_pos, "all", 3) == 0)
io_state = VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM;
@@ -917,7 +938,7 @@
curr_pos += 8;
remaining -= 8;
- pr_devel("client 0x%p called 'trylock'\n", priv);
+ pr_debug("client 0x%p called 'trylock'\n", priv);
if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) {
ret_val = -EPROTO;
@@ -961,7 +982,7 @@
curr_pos += 7;
remaining -= 7;
- pr_devel("client 0x%p called 'target'\n", priv);
+ pr_debug("client 0x%p called 'target'\n", priv);
/* if target is default */
if (!strncmp(curr_pos, "default", 7))
pdev = pci_dev_get(vga_default_device());
@@ -971,11 +992,11 @@
ret_val = -EPROTO;
goto done;
}
- pr_devel("vgaarb: %s ==> %x:%x:%x.%x\n", curr_pos,
+ pr_debug("vgaarb: %s ==> %x:%x:%x.%x\n", curr_pos,
domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
pbus = pci_find_bus(domain, bus);
- pr_devel("vgaarb: pbus %p\n", pbus);
+ pr_debug("vgaarb: pbus %p\n", pbus);
if (pbus == NULL) {
pr_err("vgaarb: invalid PCI domain and/or bus address %x:%x\n",
domain, bus);
@@ -983,7 +1004,7 @@
goto done;
}
pdev = pci_get_slot(pbus, devfn);
- pr_devel("vgaarb: pdev %p\n", pdev);
+ pr_debug("vgaarb: pdev %p\n", pdev);
if (!pdev) {
pr_err("vgaarb: invalid PCI address %x:%x\n",
bus, devfn);
@@ -993,7 +1014,7 @@
}
vgadev = vgadev_find(pdev);
- pr_devel("vgaarb: vgadev %p\n", vgadev);
+ pr_debug("vgaarb: vgadev %p\n", vgadev);
if (vgadev == NULL) {
pr_err("vgaarb: this pci device is not a vga device\n");
pci_dev_put(pdev);
@@ -1029,7 +1050,7 @@
} else if (strncmp(curr_pos, "decodes ", 8) == 0) {
curr_pos += 8;
remaining -= 8;
- pr_devel("vgaarb: client 0x%p called 'decodes'\n", priv);
+ pr_debug("vgaarb: client 0x%p called 'decodes'\n", priv);
if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) {
ret_val = -EPROTO;
@@ -1058,7 +1079,7 @@
{
struct vga_arb_private *priv = file->private_data;
- pr_devel("%s\n", __func__);
+ pr_debug("%s\n", __func__);
if (priv == NULL)
return -ENODEV;
@@ -1071,7 +1092,7 @@
struct vga_arb_private *priv;
unsigned long flags;
- pr_devel("%s\n", __func__);
+ pr_debug("%s\n", __func__);
priv = kmalloc(sizeof(struct vga_arb_private), GFP_KERNEL);
if (priv == NULL)
@@ -1101,7 +1122,7 @@
unsigned long flags;
int i;
- pr_devel("%s\n", __func__);
+ pr_debug("%s\n", __func__);
if (priv == NULL)
return -ENODEV;
@@ -1112,7 +1133,7 @@
uc = &priv->cards[i];
if (uc->pdev == NULL)
continue;
- pr_devel("uc->io_cnt == %d, uc->mem_cnt == %d\n",
+ pr_debug("uc->io_cnt == %d, uc->mem_cnt == %d\n",
uc->io_cnt, uc->mem_cnt);
while (uc->io_cnt--)
vga_put(uc->pdev, VGA_RSRC_LEGACY_IO);
@@ -1165,7 +1186,7 @@
struct pci_dev *pdev = to_pci_dev(dev);
bool notify = false;
- pr_devel("%s\n", __func__);
+ pr_debug("%s\n", __func__);
/* For now we're only intereted in devices added and removed. I didn't
* test this thing here, so someone needs to double check for the
diff --git a/drivers/hwmon/adt7411.c b/drivers/hwmon/adt7411.c
index 4086c72..f13c843 100644
--- a/drivers/hwmon/adt7411.c
+++ b/drivers/hwmon/adt7411.c
@@ -316,7 +316,6 @@
exit_remove:
sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp);
exit_free:
- i2c_set_clientdata(client, NULL);
kfree(data);
return ret;
}
@@ -327,7 +326,6 @@
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp);
- i2c_set_clientdata(client, NULL);
kfree(data);
return 0;
}
diff --git a/drivers/hwmon/asc7621.c b/drivers/hwmon/asc7621.c
index 0f388ad..3b973f3 100644
--- a/drivers/hwmon/asc7621.c
+++ b/drivers/hwmon/asc7621.c
@@ -1141,7 +1141,6 @@
&(asc7621_params[i].sda.dev_attr));
}
- i2c_set_clientdata(client, NULL);
kfree(data);
return err;
}
@@ -1196,7 +1195,6 @@
&(asc7621_params[i].sda.dev_attr));
}
- i2c_set_clientdata(client, NULL);
kfree(data);
return 0;
}
diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c
index bad2cf3..0f58ecc 100644
--- a/drivers/hwmon/f75375s.c
+++ b/drivers/hwmon/f75375s.c
@@ -662,7 +662,6 @@
sysfs_remove_group(&client->dev.kobj, &f75375_group);
exit_free:
kfree(data);
- i2c_set_clientdata(client, NULL);
return err;
}
@@ -672,7 +671,6 @@
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &f75375_group);
kfree(data);
- i2c_set_clientdata(client, NULL);
return 0;
}
diff --git a/drivers/hwmon/g760a.c b/drivers/hwmon/g760a.c
index 09ea12e..1f63d1a 100644
--- a/drivers/hwmon/g760a.c
+++ b/drivers/hwmon/g760a.c
@@ -236,7 +236,6 @@
sysfs_remove_group(&client->dev.kobj, &g760a_group);
error_sysfs_create_group:
kfree(data);
- i2c_set_clientdata(client, NULL);
return err;
}
@@ -247,7 +246,6 @@
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &g760a_group);
kfree(data);
- i2c_set_clientdata(client, NULL);
return 0;
}
diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c
index e880e2c..9379834 100644
--- a/drivers/hwmon/i5k_amb.c
+++ b/drivers/hwmon/i5k_amb.c
@@ -289,6 +289,7 @@
iattr->s_attr.dev_attr.attr.mode = S_IRUGO;
iattr->s_attr.dev_attr.show = show_label;
iattr->s_attr.index = k;
+ sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
res = device_create_file(&pdev->dev,
&iattr->s_attr.dev_attr);
if (res)
@@ -303,6 +304,7 @@
iattr->s_attr.dev_attr.attr.mode = S_IRUGO;
iattr->s_attr.dev_attr.show = show_amb_temp;
iattr->s_attr.index = k;
+ sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
res = device_create_file(&pdev->dev,
&iattr->s_attr.dev_attr);
if (res)
@@ -318,6 +320,7 @@
iattr->s_attr.dev_attr.show = show_amb_min;
iattr->s_attr.dev_attr.store = store_amb_min;
iattr->s_attr.index = k;
+ sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
res = device_create_file(&pdev->dev,
&iattr->s_attr.dev_attr);
if (res)
@@ -333,6 +336,7 @@
iattr->s_attr.dev_attr.show = show_amb_mid;
iattr->s_attr.dev_attr.store = store_amb_mid;
iattr->s_attr.index = k;
+ sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
res = device_create_file(&pdev->dev,
&iattr->s_attr.dev_attr);
if (res)
@@ -348,6 +352,7 @@
iattr->s_attr.dev_attr.show = show_amb_max;
iattr->s_attr.dev_attr.store = store_amb_max;
iattr->s_attr.index = k;
+ sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
res = device_create_file(&pdev->dev,
&iattr->s_attr.dev_attr);
if (res)
@@ -362,6 +367,7 @@
iattr->s_attr.dev_attr.attr.mode = S_IRUGO;
iattr->s_attr.dev_attr.show = show_amb_alarm;
iattr->s_attr.index = k;
+ sysfs_attr_init(&iattr->s_attr.dev_attr.attr);
res = device_create_file(&pdev->dev,
&iattr->s_attr.dev_attr);
if (res)
diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c
index 099a213..da5a240 100644
--- a/drivers/hwmon/k10temp.c
+++ b/drivers/hwmon/k10temp.c
@@ -112,11 +112,21 @@
if (pkg_type != CPUID_PKGTYPE_AM2R2_AM3)
return false;
- /* Differentiate between AM2+ (bad) and AM3 (good) */
+ /* DDR3 memory implies socket AM3, which is good */
pci_bus_read_config_dword(pdev->bus,
PCI_DEVFN(PCI_SLOT(pdev->devfn), 2),
REG_DCT0_CONFIG_HIGH, ®_dram_cfg);
- return !(reg_dram_cfg & DDR3_MODE);
+ if (reg_dram_cfg & DDR3_MODE)
+ return false;
+
+ /*
+ * Unfortunately it is possible to run a socket AM3 CPU with DDR2
+ * memory. We blacklist all the cores which do exist in socket AM2+
+ * format. It still isn't perfect, as RB-C2 cores exist in both AM2+
+ * and AM3 formats, but that's the best we can do.
+ */
+ return boot_cpu_data.x86_model < 4 ||
+ (boot_cpu_data.x86_model == 4 && boot_cpu_data.x86_mask <= 2);
}
static int __devinit k10temp_probe(struct pci_dev *pdev,
diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c
index 0ceb6d6..f26acdb 100644
--- a/drivers/hwmon/k8temp.c
+++ b/drivers/hwmon/k8temp.c
@@ -120,7 +120,7 @@
int temp;
struct k8temp_data *data = k8temp_update_device(dev);
- if (data->swap_core_select)
+ if (data->swap_core_select && (data->sensorsp & SEL_CORE))
core = core ? 0 : 1;
temp = TEMP_FROM_REG(data->temp[core][place]) + data->temp_offset;
diff --git a/drivers/hwmon/lm73.c b/drivers/hwmon/lm73.c
index 4d1b76b..29b9030 100644
--- a/drivers/hwmon/lm73.c
+++ b/drivers/hwmon/lm73.c
@@ -136,7 +136,6 @@
hwmon_device_unregister(hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm73_group);
- i2c_set_clientdata(client, NULL);
return 0;
}
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index 5646342..393f354 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -192,7 +192,6 @@
exit_remove:
sysfs_remove_group(&client->dev.kobj, &lm75_group);
exit_free:
- i2c_set_clientdata(client, NULL);
kfree(data);
return status;
}
@@ -204,7 +203,6 @@
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm75_group);
lm75_write_value(client, LM75_REG_CONF, data->orig_conf);
- i2c_set_clientdata(client, NULL);
kfree(data);
return 0;
}
diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c
index 8fc8eb8..94741d4 100644
--- a/drivers/hwmon/lm95241.c
+++ b/drivers/hwmon/lm95241.c
@@ -399,7 +399,6 @@
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm95241_group);
- i2c_set_clientdata(client, NULL);
kfree(data);
return 0;
}
diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c
index 8013895..93187c3c 100644
--- a/drivers/hwmon/tmp102.c
+++ b/drivers/hwmon/tmp102.c
@@ -224,7 +224,6 @@
fail_restore_config:
tmp102_write_reg(client, TMP102_CONF_REG, tmp102->config_orig);
fail_free:
- i2c_set_clientdata(client, NULL);
kfree(tmp102);
return status;
@@ -247,7 +246,6 @@
config | TMP102_CONF_SD);
}
- i2c_set_clientdata(client, NULL);
kfree(tmp102);
return 0;
diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c
index 738c472..6b4165c 100644
--- a/drivers/hwmon/tmp421.c
+++ b/drivers/hwmon/tmp421.c
@@ -295,7 +295,6 @@
sysfs_remove_group(&client->dev.kobj, &tmp421_group);
exit_free:
- i2c_set_clientdata(client, NULL);
kfree(data);
return err;
@@ -308,7 +307,6 @@
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &tmp421_group);
- i2c_set_clientdata(client, NULL);
kfree(data);
return 0;
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index 32d4ade..c84b9b4 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -1197,7 +1197,6 @@
if (data->lm75[1])
i2c_unregister_device(data->lm75[1]);
ERROR3:
- i2c_set_clientdata(client, NULL);
kfree(data);
ERROR1:
return err;
@@ -1219,7 +1218,6 @@
if (data->lm75[1])
i2c_unregister_device(data->lm75[1]);
- i2c_set_clientdata(client, NULL);
kfree(data);
return 0;
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 87ab056..bceafbf 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -475,6 +475,26 @@
help
Supports the PA Semi PWRficient on-chip SMBus interfaces.
+config I2C_PCA_PLATFORM
+ tristate "PCA9564/PCA9665 as platform device"
+ select I2C_ALGOPCA
+ default n
+ help
+ This driver supports a memory mapped Philips PCA9564/PCA9665
+ parallel bus to I2C bus controller.
+
+ This driver can also be built as a module. If so, the module
+ will be called i2c-pca-platform.
+
+config I2C_PMCMSP
+ tristate "PMC MSP I2C TWI Controller"
+ depends on PMC_MSP
+ help
+ This driver supports the PMC TWI controller on MSP devices.
+
+ This driver can also be built as module. If so, the module
+ will be called i2c-pmcmsp.
+
config I2C_PNX
tristate "I2C bus support for Philips PNX targets"
depends on ARCH_PNX4008
@@ -711,26 +731,6 @@
delays when I2C/SMBus chip drivers are loaded (e.g. at boot
time). If unsure, say N.
-config I2C_PCA_PLATFORM
- tristate "PCA9564/PCA9665 as platform device"
- select I2C_ALGOPCA
- default n
- help
- This driver supports a memory mapped Philips PCA9564/PCA9665
- parallel bus to I2C bus controller.
-
- This driver can also be built as a module. If so, the module
- will be called i2c-pca-platform.
-
-config I2C_PMCMSP
- tristate "PMC MSP I2C TWI Controller"
- depends on PMC_MSP
- help
- This driver supports the PMC TWI controller on MSP devices.
-
- This driver can also be built as module. If so, the module
- will be called i2c-pmcmsp.
-
config I2C_SIBYTE
tristate "SiByte SMBus interface"
depends on SIBYTE_SB1xxx_SOC
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 097236f..936880b 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -27,7 +27,7 @@
obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o
obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o
-# Embebbed system I2C/SMBus host controller drivers
+# Embedded system I2C/SMBus host controller drivers
obj-$(CONFIG_I2C_AT91) += i2c-at91.o
obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
@@ -46,6 +46,8 @@
obj-$(CONFIG_I2C_OCORES) += i2c-ocores.o
obj-$(CONFIG_I2C_OMAP) += i2c-omap.o
obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o
+obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
+obj-$(CONFIG_I2C_PMCMSP) += i2c-pmcmsp.o
obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
@@ -68,8 +70,6 @@
obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o
obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
-obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
-obj-$(CONFIG_I2C_PMCMSP) += i2c-pmcmsp.o
obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
obj-$(CONFIG_I2C_STUB) += i2c-stub.o
obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index e0f833c..1cca263 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -47,7 +47,6 @@
static DEFINE_IDR(i2c_adapter_idr);
static struct device_type i2c_client_type;
-static int i2c_check_addr(struct i2c_adapter *adapter, int addr);
static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver);
/* ------------------------------------------------------------------------- */
@@ -371,6 +370,59 @@
EXPORT_SYMBOL(i2c_verify_client);
+/* This is a permissive address validity check, I2C address map constraints
+ * are purposedly not enforced, except for the general call address. */
+static int i2c_check_client_addr_validity(const struct i2c_client *client)
+{
+ if (client->flags & I2C_CLIENT_TEN) {
+ /* 10-bit address, all values are valid */
+ if (client->addr > 0x3ff)
+ return -EINVAL;
+ } else {
+ /* 7-bit address, reject the general call address */
+ if (client->addr == 0x00 || client->addr > 0x7f)
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/* And this is a strict address validity check, used when probing. If a
+ * device uses a reserved address, then it shouldn't be probed. 7-bit
+ * addressing is assumed, 10-bit address devices are rare and should be
+ * explicitly enumerated. */
+static int i2c_check_addr_validity(unsigned short addr)
+{
+ /*
+ * Reserved addresses per I2C specification:
+ * 0x00 General call address / START byte
+ * 0x01 CBUS address
+ * 0x02 Reserved for different bus format
+ * 0x03 Reserved for future purposes
+ * 0x04-0x07 Hs-mode master code
+ * 0x78-0x7b 10-bit slave addressing
+ * 0x7c-0x7f Reserved for future purposes
+ */
+ if (addr < 0x08 || addr > 0x77)
+ return -EINVAL;
+ return 0;
+}
+
+static int __i2c_check_addr_busy(struct device *dev, void *addrp)
+{
+ struct i2c_client *client = i2c_verify_client(dev);
+ int addr = *(int *)addrp;
+
+ if (client && client->addr == addr)
+ return -EBUSY;
+ return 0;
+}
+
+static int i2c_check_addr_busy(struct i2c_adapter *adapter, int addr)
+{
+ return device_for_each_child(&adapter->dev, &addr,
+ __i2c_check_addr_busy);
+}
+
/**
* i2c_new_device - instantiate an i2c device
* @adap: the adapter managing the device
@@ -410,8 +462,16 @@
strlcpy(client->name, info->type, sizeof(client->name));
+ /* Check for address validity */
+ status = i2c_check_client_addr_validity(client);
+ if (status) {
+ dev_err(&adap->dev, "Invalid %d-bit I2C address 0x%02hx\n",
+ client->flags & I2C_CLIENT_TEN ? 10 : 7, client->addr);
+ goto out_err_silent;
+ }
+
/* Check for address business */
- status = i2c_check_addr(adap, client->addr);
+ status = i2c_check_addr_busy(adap, client->addr);
if (status)
goto out_err;
@@ -436,6 +496,7 @@
out_err:
dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x "
"(%d)\n", client->name, client->addr, status);
+out_err_silent:
kfree(client);
return NULL;
}
@@ -561,15 +622,9 @@
return -EINVAL;
}
- if (info.addr < 0x03 || info.addr > 0x77) {
- dev_err(dev, "%s: Invalid I2C address 0x%hx\n", "new_device",
- info.addr);
- return -EINVAL;
- }
-
client = i2c_new_device(adap, &info);
if (!client)
- return -EEXIST;
+ return -EINVAL;
/* Keep track of the added device */
i2c_lock_adapter(adap);
@@ -1024,21 +1079,6 @@
/* ------------------------------------------------------------------------- */
-static int __i2c_check_addr(struct device *dev, void *addrp)
-{
- struct i2c_client *client = i2c_verify_client(dev);
- int addr = *(int *)addrp;
-
- if (client && client->addr == addr)
- return -EBUSY;
- return 0;
-}
-
-static int i2c_check_addr(struct i2c_adapter *adapter, int addr)
-{
- return device_for_each_child(&adapter->dev, &addr, __i2c_check_addr);
-}
-
/**
* i2c_use_client - increments the reference count of the i2c client structure
* @client: the client being referenced
@@ -1277,6 +1317,41 @@
* ----------------------------------------------------
*/
+/*
+ * Legacy default probe function, mostly relevant for SMBus. The default
+ * probe method is a quick write, but it is known to corrupt the 24RF08
+ * EEPROMs due to a state machine bug, and could also irreversibly
+ * write-protect some EEPROMs, so for address ranges 0x30-0x37 and 0x50-0x5f,
+ * we use a short byte read instead. Also, some bus drivers don't implement
+ * quick write, so we fallback to a byte read in that case too.
+ * On x86, there is another special case for FSC hardware monitoring chips,
+ * which want regular byte reads (address 0x73.) Fortunately, these are the
+ * only known chips using this I2C address on PC hardware.
+ * Returns 1 if probe succeeded, 0 if not.
+ */
+static int i2c_default_probe(struct i2c_adapter *adap, unsigned short addr)
+{
+ int err;
+ union i2c_smbus_data dummy;
+
+#ifdef CONFIG_X86
+ if (addr == 0x73 && (adap->class & I2C_CLASS_HWMON)
+ && i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_BYTE_DATA))
+ err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0,
+ I2C_SMBUS_BYTE_DATA, &dummy);
+ else
+#endif
+ if ((addr & ~0x07) == 0x30 || (addr & ~0x0f) == 0x50
+ || !i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK))
+ err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0,
+ I2C_SMBUS_BYTE, &dummy);
+ else
+ err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_WRITE, 0,
+ I2C_SMBUS_QUICK, NULL);
+
+ return err >= 0;
+}
+
static int i2c_detect_address(struct i2c_client *temp_client,
struct i2c_driver *driver)
{
@@ -1286,34 +1361,20 @@
int err;
/* Make sure the address is valid */
- if (addr < 0x03 || addr > 0x77) {
+ err = i2c_check_addr_validity(addr);
+ if (err) {
dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n",
addr);
- return -EINVAL;
+ return err;
}
/* Skip if already in use */
- if (i2c_check_addr(adapter, addr))
+ if (i2c_check_addr_busy(adapter, addr))
return 0;
/* Make sure there is something at this address */
- if (addr == 0x73 && (adapter->class & I2C_CLASS_HWMON)) {
- /* Special probe for FSC hwmon chips */
- union i2c_smbus_data dummy;
-
- if (i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_READ, 0,
- I2C_SMBUS_BYTE_DATA, &dummy) < 0)
- return 0;
- } else {
- if (i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_WRITE, 0,
- I2C_SMBUS_QUICK, NULL) < 0)
- return 0;
-
- /* Prevent 24RF08 corruption */
- if ((addr & ~0x0f) == 0x50)
- i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_WRITE, 0,
- I2C_SMBUS_QUICK, NULL);
- }
+ if (!i2c_default_probe(adapter, addr))
+ return 0;
/* Finally call the custom detection function */
memset(&info, 0, sizeof(struct i2c_board_info));
@@ -1407,42 +1468,22 @@
for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) {
/* Check address validity */
- if (addr_list[i] < 0x03 || addr_list[i] > 0x77) {
+ if (i2c_check_addr_validity(addr_list[i]) < 0) {
dev_warn(&adap->dev, "Invalid 7-bit address "
"0x%02x\n", addr_list[i]);
continue;
}
/* Check address availability */
- if (i2c_check_addr(adap, addr_list[i])) {
+ if (i2c_check_addr_busy(adap, addr_list[i])) {
dev_dbg(&adap->dev, "Address 0x%02x already in "
"use, not probing\n", addr_list[i]);
continue;
}
- /* Test address responsiveness
- The default probe method is a quick write, but it is known
- to corrupt the 24RF08 EEPROMs due to a state machine bug,
- and could also irreversibly write-protect some EEPROMs, so
- for address ranges 0x30-0x37 and 0x50-0x5f, we use a byte
- read instead. Also, some bus drivers don't implement
- quick write, so we fallback to a byte read it that case
- too. */
- if ((addr_list[i] & ~0x07) == 0x30
- || (addr_list[i] & ~0x0f) == 0x50
- || !i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK)) {
- union i2c_smbus_data data;
-
- if (i2c_smbus_xfer(adap, addr_list[i], 0,
- I2C_SMBUS_READ, 0,
- I2C_SMBUS_BYTE, &data) >= 0)
- break;
- } else {
- if (i2c_smbus_xfer(adap, addr_list[i], 0,
- I2C_SMBUS_WRITE, 0,
- I2C_SMBUS_QUICK, NULL) >= 0)
- break;
- }
+ /* Test address responsiveness */
+ if (i2c_default_probe(adap, addr_list[i]))
+ break;
}
if (addr_list[i] == I2C_CLIENT_END) {
diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c
index a24e0bf..f61ccc1 100644
--- a/drivers/i2c/i2c-smbus.c
+++ b/drivers/i2c/i2c-smbus.c
@@ -173,7 +173,6 @@
cancel_work_sync(&alert->alert);
- i2c_set_clientdata(ara, NULL);
kfree(alert);
return 0;
}
diff --git a/drivers/ide/pmac.c b/drivers/ide/pmac.c
index 183fa38..ebcf8e4 100644
--- a/drivers/ide/pmac.c
+++ b/drivers/ide/pmac.c
@@ -1400,8 +1400,11 @@
static struct macio_driver pmac_ide_macio_driver =
{
- .name = "ide-pmac",
- .match_table = pmac_ide_macio_match,
+ .driver = {
+ .name = "ide-pmac",
+ .owner = THIS_MODULE,
+ .of_match_table = pmac_ide_macio_match,
+ },
.probe = pmac_ide_macio_attach,
.suspend = pmac_ide_macio_suspend,
.resume = pmac_ide_macio_resume,
diff --git a/drivers/infiniband/hw/qib/qib_fs.c b/drivers/infiniband/hw/qib/qib_fs.c
index edef852..844954b 100644
--- a/drivers/infiniband/hw/qib/qib_fs.c
+++ b/drivers/infiniband/hw/qib/qib_fs.c
@@ -542,10 +542,8 @@
list_for_each_entry_safe(dd, tmp, &qib_dev_list, list) {
spin_unlock_irqrestore(&qib_devs_lock, flags);
ret = add_cntr_files(sb, dd);
- if (ret) {
- deactivate_super(sb);
+ if (ret)
goto bail;
- }
spin_lock_irqsave(&qib_devs_lock, flags);
}
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index d8fa5d7..0f9a478 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -69,7 +69,7 @@
module will be called atakbd.
config KEYBOARD_ATKBD
- tristate "AT keyboard" if EMBEDDED || !X86
+ tristate "AT keyboard" if EMBEDDED || !X86 || X86_MRST
default y
select SERIO
select SERIO_LIBPS2
diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c
index 4771ab1..744600e 100644
--- a/drivers/input/keyboard/adp5588-keys.c
+++ b/drivers/input/keyboard/adp5588-keys.c
@@ -287,7 +287,6 @@
free_irq(client->irq, kpad);
cancel_delayed_work_sync(&kpad->work);
input_unregister_device(kpad->input);
- i2c_set_clientdata(client, NULL);
kfree(kpad);
return 0;
diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c
index bc69693..40b032f 100644
--- a/drivers/input/keyboard/lm8323.c
+++ b/drivers/input/keyboard/lm8323.c
@@ -778,8 +778,6 @@
struct lm8323_chip *lm = i2c_get_clientdata(client);
int i;
- i2c_set_clientdata(client, NULL);
-
disable_irq_wake(client->irq);
free_irq(client->irq, lm);
cancel_work_sync(&lm->work);
diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c
index 7fc8185..9091ff5 100644
--- a/drivers/input/keyboard/max7359_keypad.c
+++ b/drivers/input/keyboard/max7359_keypad.c
@@ -265,7 +265,6 @@
free_irq(client->irq, keypad);
input_unregister_device(keypad->input_dev);
- i2c_set_clientdata(client, NULL);
kfree(keypad);
return 0;
diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c
index 31f3008..fac6951 100644
--- a/drivers/input/keyboard/qt2160.c
+++ b/drivers/input/keyboard/qt2160.c
@@ -358,7 +358,6 @@
input_unregister_device(qt2160->input);
kfree(qt2160);
- i2c_set_clientdata(client, NULL);
return 0;
}
diff --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c
index 493c93f..00137be 100644
--- a/drivers/input/keyboard/tca6416-keypad.c
+++ b/drivers/input/keyboard/tca6416-keypad.c
@@ -316,8 +316,6 @@
input_unregister_device(chip->input);
kfree(chip);
- i2c_set_clientdata(client, NULL);
-
return 0;
}
diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c
index e9adbe4..2bef8fa 100644
--- a/drivers/input/misc/ad714x-i2c.c
+++ b/drivers/input/misc/ad714x-i2c.c
@@ -97,7 +97,6 @@
struct ad714x_chip *chip = i2c_get_clientdata(client);
ad714x_remove(chip);
- i2c_set_clientdata(client, NULL);
return 0;
}
diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c
index e00a1cc..c190664 100644
--- a/drivers/input/misc/hp_sdc_rtc.c
+++ b/drivers/input/misc/hp_sdc_rtc.c
@@ -678,7 +678,7 @@
.llseek = no_llseek,
.read = hp_sdc_rtc_read,
.poll = hp_sdc_rtc_poll,
- .unlocked_ioctl = hp_sdc_rtc_ioctl,
+ .unlocked_ioctl = hp_sdc_rtc_unlocked_ioctl,
.open = hp_sdc_rtc_open,
.fasync = hp_sdc_rtc_fasync,
};
diff --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c
index 5c3ac4e..4b42ffc 100644
--- a/drivers/input/misc/pcf8574_keypad.c
+++ b/drivers/input/misc/pcf8574_keypad.c
@@ -69,7 +69,7 @@
unsigned char nextstate = read_state(lp);
if (lp->laststate != nextstate) {
- int key_down = nextstate <= ARRAY_SIZE(lp->btncode);
+ int key_down = nextstate < ARRAY_SIZE(lp->btncode);
unsigned short keycode = key_down ?
lp->btncode[nextstate] : lp->btncode[lp->laststate];
@@ -168,8 +168,6 @@
input_unregister_device(lp->idev);
kfree(lp);
- i2c_set_clientdata(client, NULL);
-
return 0;
}
diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c
index 8291e73..0ae62f0 100644
--- a/drivers/input/mouse/synaptics_i2c.c
+++ b/drivers/input/mouse/synaptics_i2c.c
@@ -613,7 +613,6 @@
free_irq(client->irq, touch);
input_unregister_device(touch->input);
- i2c_set_clientdata(client, NULL);
kfree(touch);
return 0;
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index f34f1db..256b9e9 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -21,7 +21,8 @@
config SERIO_I8042
tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86
default y
- depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && !M68K && !BLACKFIN
+ depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && \
+ (!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN && !X86_MRST
help
i8042 is the chip over which the standard AT keyboard and PS/2
mouse are connected to the computer. If you use these devices,
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 2dc0c07..42ba369 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -508,7 +508,6 @@
}
input_dev->name = wacom_wac->name;
- input_dev->name = wacom_wac->name;
input_dev->dev.parent = &intf->dev;
input_dev->open = wacom_open;
input_dev->close = wacom_close;
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 847fd01..415f630 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -284,12 +284,13 @@
(data[4] << 20) + (data[5] << 12) +
(data[6] << 4) + (data[7] >> 4);
- wacom->id[idx] = (data[2] << 4) | (data[3] >> 4);
+ wacom->id[idx] = (data[2] << 4) | (data[3] >> 4) |
+ ((data[7] & 0x0f) << 20) | ((data[8] & 0xf0) << 12);
- switch (wacom->id[idx]) {
+ switch (wacom->id[idx] & 0xfffff) {
case 0x812: /* Inking pen */
case 0x801: /* Intuos3 Inking pen */
- case 0x20802: /* Intuos4 Classic Pen */
+ case 0x20802: /* Intuos4 Inking Pen */
case 0x012:
wacom->tool[idx] = BTN_TOOL_PENCIL;
break;
@@ -300,7 +301,7 @@
case 0x823: /* Intuos3 Grip Pen */
case 0x813: /* Intuos3 Classic Pen */
case 0x885: /* Intuos3 Marker Pen */
- case 0x802: /* Intuos4 Grip Pen Eraser */
+ case 0x802: /* Intuos4 General Pen */
case 0x804: /* Intuos4 Marker Pen */
case 0x40802: /* Intuos4 Classic Pen */
case 0x022:
@@ -335,7 +336,7 @@
case 0x81b: /* Intuos3 Classic Pen Eraser */
case 0x91b: /* Intuos3 Airbrush Eraser */
case 0x80c: /* Intuos4 Marker Pen Eraser */
- case 0x80a: /* Intuos4 Grip Pen Eraser */
+ case 0x80a: /* Intuos4 General Pen Eraser */
case 0x4080a: /* Intuos4 Classic Pen Eraser */
case 0x90a: /* Intuos4 Airbrush Eraser */
wacom->tool[idx] = BTN_TOOL_RUBBER;
@@ -356,6 +357,11 @@
return 1;
}
+ /* older I4 styli don't work with new Cintiqs */
+ if (!((wacom->id[idx] >> 20) & 0x01) &&
+ (features->type == WACOM_21UX2))
+ return 1;
+
/* Exit report */
if ((data[1] & 0xfe) == 0x80) {
/*
@@ -474,21 +480,43 @@
input_report_abs(input, ABS_MISC, 0);
}
} else {
- input_report_key(input, BTN_0, (data[5] & 0x01));
- input_report_key(input, BTN_1, (data[5] & 0x02));
- input_report_key(input, BTN_2, (data[5] & 0x04));
- input_report_key(input, BTN_3, (data[5] & 0x08));
- input_report_key(input, BTN_4, (data[6] & 0x01));
- input_report_key(input, BTN_5, (data[6] & 0x02));
- input_report_key(input, BTN_6, (data[6] & 0x04));
- input_report_key(input, BTN_7, (data[6] & 0x08));
- input_report_key(input, BTN_8, (data[5] & 0x10));
- input_report_key(input, BTN_9, (data[6] & 0x10));
+ if (features->type == WACOM_21UX2) {
+ input_report_key(input, BTN_0, (data[5] & 0x01));
+ input_report_key(input, BTN_1, (data[6] & 0x01));
+ input_report_key(input, BTN_2, (data[6] & 0x02));
+ input_report_key(input, BTN_3, (data[6] & 0x04));
+ input_report_key(input, BTN_4, (data[6] & 0x08));
+ input_report_key(input, BTN_5, (data[6] & 0x10));
+ input_report_key(input, BTN_6, (data[6] & 0x20));
+ input_report_key(input, BTN_7, (data[6] & 0x40));
+ input_report_key(input, BTN_8, (data[6] & 0x80));
+ input_report_key(input, BTN_9, (data[7] & 0x01));
+ input_report_key(input, BTN_A, (data[8] & 0x01));
+ input_report_key(input, BTN_B, (data[8] & 0x02));
+ input_report_key(input, BTN_C, (data[8] & 0x04));
+ input_report_key(input, BTN_X, (data[8] & 0x08));
+ input_report_key(input, BTN_Y, (data[8] & 0x10));
+ input_report_key(input, BTN_Z, (data[8] & 0x20));
+ input_report_key(input, BTN_BASE, (data[8] & 0x40));
+ input_report_key(input, BTN_BASE2, (data[8] & 0x80));
+ } else {
+ input_report_key(input, BTN_0, (data[5] & 0x01));
+ input_report_key(input, BTN_1, (data[5] & 0x02));
+ input_report_key(input, BTN_2, (data[5] & 0x04));
+ input_report_key(input, BTN_3, (data[5] & 0x08));
+ input_report_key(input, BTN_4, (data[6] & 0x01));
+ input_report_key(input, BTN_5, (data[6] & 0x02));
+ input_report_key(input, BTN_6, (data[6] & 0x04));
+ input_report_key(input, BTN_7, (data[6] & 0x08));
+ input_report_key(input, BTN_8, (data[5] & 0x10));
+ input_report_key(input, BTN_9, (data[6] & 0x10));
+ }
input_report_abs(input, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
input_report_abs(input, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
- if ((data[5] & 0x1f) | (data[6] & 0x1f) | (data[1] & 0x1f) |
- data[2] | (data[3] & 0x1f) | data[4]) {
+ if ((data[5] & 0x1f) | data[6] | (data[1] & 0x1f) |
+ data[2] | (data[3] & 0x1f) | data[4] | data[8] |
+ (data[7] & 0x01)) {
input_report_key(input, wacom->tool[1], 1);
input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
} else {
@@ -640,7 +668,7 @@
if (!idx)
input_report_key(input, BTN_TOUCH, 1);
input_event(input, EV_MSC, MSC_SERIAL, finger);
- input_sync(wacom->input);
+ input_sync(input);
wacom->last_finger = finger;
}
@@ -826,6 +854,7 @@
case INTUOS4L:
case CINTIQ:
case WACOM_BEE:
+ case WACOM_21UX2:
sync = wacom_intuos_irq(wacom_wac);
break;
@@ -921,6 +950,17 @@
__set_bit(BTN_STYLUS2, input_dev->keybit);
break;
+ case WACOM_21UX2:
+ __set_bit(BTN_A, input_dev->keybit);
+ __set_bit(BTN_B, input_dev->keybit);
+ __set_bit(BTN_C, input_dev->keybit);
+ __set_bit(BTN_X, input_dev->keybit);
+ __set_bit(BTN_Y, input_dev->keybit);
+ __set_bit(BTN_Z, input_dev->keybit);
+ __set_bit(BTN_BASE, input_dev->keybit);
+ __set_bit(BTN_BASE2, input_dev->keybit);
+ /* fall through */
+
case WACOM_BEE:
__set_bit(BTN_8, input_dev->keybit);
__set_bit(BTN_9, input_dev->keybit);
@@ -1105,6 +1145,8 @@
{ "Wacom Intuos4 8x13", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047, 63, INTUOS4L };
static const struct wacom_features wacom_features_0xBB =
{ "Wacom Intuos4 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 2047, 63, INTUOS4L };
+static const struct wacom_features wacom_features_0xBC =
+ { "Wacom Intuos4 WL", WACOM_PKGLEN_INTUOS, 40840, 25400, 2047, 63, INTUOS4 };
static const struct wacom_features wacom_features_0x3F =
{ "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, 63, CINTIQ };
static const struct wacom_features wacom_features_0xC5 =
@@ -1113,6 +1155,8 @@
{ "Wacom Cintiq 12WX", WACOM_PKGLEN_INTUOS, 53020, 33440, 1023, 63, WACOM_BEE };
static const struct wacom_features wacom_features_0xC7 =
{ "Wacom DTU1931", WACOM_PKGLEN_GRAPHIRE, 37832, 30305, 511, 0, PL };
+static const struct wacom_features wacom_features_0xCC =
+ { "Wacom Cintiq 21UX2", WACOM_PKGLEN_INTUOS, 87200, 65600, 2047, 63, WACOM_21UX2 };
static const struct wacom_features wacom_features_0x90 =
{ "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC };
static const struct wacom_features wacom_features_0x93 =
@@ -1185,10 +1229,12 @@
{ USB_DEVICE_WACOM(0xB9) },
{ USB_DEVICE_WACOM(0xBA) },
{ USB_DEVICE_WACOM(0xBB) },
+ { USB_DEVICE_WACOM(0xBC) },
{ USB_DEVICE_WACOM(0x3F) },
{ USB_DEVICE_WACOM(0xC5) },
{ USB_DEVICE_WACOM(0xC6) },
{ USB_DEVICE_WACOM(0xC7) },
+ { USB_DEVICE_WACOM(0xCC) },
{ USB_DEVICE_WACOM(0x90) },
{ USB_DEVICE_WACOM(0x93) },
{ USB_DEVICE_WACOM(0x9A) },
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index 063f1af..854b920 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -50,6 +50,7 @@
INTUOS4S,
INTUOS4,
INTUOS4L,
+ WACOM_21UX2,
CINTIQ,
WACOM_BEE,
WACOM_MO,
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 6703c6b..3b9d5e2 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -156,7 +156,7 @@
config TOUCHSCREEN_S3C2410
tristate "Samsung S3C2410/generic touchscreen input driver"
depends on ARCH_S3C2410 || SAMSUNG_DEV_TS
- select S3C24XX_ADC
+ select S3C_ADC
help
Say Y here if you have the s3c2410 touchscreen.
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c
index 0d2d7e5..5f0221c 100644
--- a/drivers/input/touchscreen/ad7877.c
+++ b/drivers/input/touchscreen/ad7877.c
@@ -679,6 +679,13 @@
return -EINVAL;
}
+ spi->bits_per_word = 16;
+ err = spi_setup(spi);
+ if (err) {
+ dev_dbg(&spi->dev, "spi master doesn't support 16 bits/word\n");
+ return err;
+ }
+
ts = kzalloc(sizeof(struct ad7877), GFP_KERNEL);
input_dev = input_allocate_device();
if (!ts || !input_dev) {
diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c
index 794d070..4b32fb4 100644
--- a/drivers/input/touchscreen/ad7879.c
+++ b/drivers/input/touchscreen/ad7879.c
@@ -812,10 +812,8 @@
ts->bus = client;
error = ad7879_construct(client, ts);
- if (error) {
- i2c_set_clientdata(client, NULL);
+ if (error)
kfree(ts);
- }
return error;
}
@@ -825,7 +823,6 @@
struct ad7879 *ts = dev_get_drvdata(&client->dev);
ad7879_destroy(client, ts);
- i2c_set_clientdata(client, NULL);
kfree(ts);
return 0;
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 634f6f6..a9fdf55 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -1164,7 +1164,7 @@
ts->reg = regulator_get(&spi->dev, "vcc");
if (IS_ERR(ts->reg)) {
err = PTR_ERR(ts->reg);
- dev_err(&spi->dev, "unable to get regulator: %ld\n", err);
+ dev_err(&spi->dev, "unable to get regulator: %d\n", err);
goto err_free_gpio;
}
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c
index 75f8b73..7a3a916 100644
--- a/drivers/input/touchscreen/eeti_ts.c
+++ b/drivers/input/touchscreen/eeti_ts.c
@@ -238,7 +238,6 @@
input = NULL; /* so we dont try to free it below */
err1:
input_free_device(input);
- i2c_set_clientdata(client, NULL);
kfree(priv);
err0:
return err;
@@ -256,7 +255,6 @@
enable_irq(priv->irq);
input_unregister_device(priv->input);
- i2c_set_clientdata(client, NULL);
kfree(priv);
return 0;
diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c
index ce8ab02..1fb0c2f 100644
--- a/drivers/input/touchscreen/mcs5000_ts.c
+++ b/drivers/input/touchscreen/mcs5000_ts.c
@@ -256,7 +256,6 @@
free_irq(client->irq, data);
input_unregister_device(data->input_dev);
kfree(data);
- i2c_set_clientdata(client, NULL);
return 0;
}
diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c
index ac5d0f9..6085d12 100644
--- a/drivers/input/touchscreen/s3c2410_ts.c
+++ b/drivers/input/touchscreen/s3c2410_ts.c
@@ -173,7 +173,7 @@
if (down)
s3c_adc_start(ts.client, 0, 1 << ts.shift);
else
- dev_info(ts.dev, "%s: count=%d\n", __func__, ts.count);
+ dev_dbg(ts.dev, "%s: count=%d\n", __func__, ts.count);
if (ts.features & FEAT_PEN_IRQ) {
/* Clear pen down/up interrupt */
diff --git a/drivers/input/touchscreen/tps6507x-ts.c b/drivers/input/touchscreen/tps6507x-ts.c
index 5de80a1..5b70a14 100644
--- a/drivers/input/touchscreen/tps6507x-ts.c
+++ b/drivers/input/touchscreen/tps6507x-ts.c
@@ -221,7 +221,7 @@
if (poll) {
schd = queue_delayed_work(tsc->wq, &tsc->work,
- tsc->poll_period * HZ / 1000);
+ msecs_to_jiffies(tsc->poll_period));
if (schd)
tsc->polling = 1;
else {
@@ -326,7 +326,7 @@
goto err2;
schd = queue_delayed_work(tsc->wq, &tsc->work,
- tsc->poll_period * HZ / 1000);
+ msecs_to_jiffies(tsc->poll_period));
if (schd)
tsc->polling = 1;
@@ -339,10 +339,8 @@
return 0;
err2:
- cancel_delayed_work(&tsc->work);
- flush_workqueue(tsc->wq);
+ cancel_delayed_work_sync(&tsc->work);
destroy_workqueue(tsc->wq);
- tsc->wq = 0;
input_free_device(input_dev);
err1:
kfree(tsc);
@@ -360,10 +358,8 @@
if (!tsc)
return 0;
- cancel_delayed_work(&tsc->work);
- flush_workqueue(tsc->wq);
+ cancel_delayed_work_sync(&tsc->work);
destroy_workqueue(tsc->wq);
- tsc->wq = 0;
input_free_device(input_dev);
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c
index 769b479..be23780 100644
--- a/drivers/input/touchscreen/tsc2007.c
+++ b/drivers/input/touchscreen/tsc2007.c
@@ -347,8 +347,6 @@
struct tsc2007 *ts = i2c_get_clientdata(client);
struct tsc2007_platform_data *pdata = client->dev.platform_data;
- i2c_set_clientdata(client, NULL);
-
tsc2007_free_irq(ts);
if (pdata->exit_platform_hw)
diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c
index bde3c88..b054494 100644
--- a/drivers/isdn/capi/kcapi.c
+++ b/drivers/isdn/capi/kcapi.c
@@ -1020,12 +1020,12 @@
if (cmd == AVMB1_ADDCARD) {
if ((retval = copy_from_user(&cdef, data,
sizeof(avmb1_carddef))))
- return retval;
+ return -EFAULT;
cdef.cardtype = AVM_CARDTYPE_B1;
} else {
if ((retval = copy_from_user(&cdef, data,
sizeof(avmb1_extcarddef))))
- return retval;
+ return -EFAULT;
}
cparams.port = cdef.port;
cparams.irq = cdef.irq;
@@ -1218,7 +1218,7 @@
kcapi_carddef cdef;
if ((retval = copy_from_user(&cdef, data, sizeof(cdef))))
- return retval;
+ return -EFAULT;
cparams.port = cdef.port;
cparams.irq = cdef.irq;
diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c
index c5016bd..c3b1dc3 100644
--- a/drivers/isdn/gigaset/asyncdata.c
+++ b/drivers/isdn/gigaset/asyncdata.c
@@ -126,26 +126,6 @@
return numbytes;
}
-/* set up next receive skb for data mode
- */
-static void new_rcv_skb(struct bc_state *bcs)
-{
- struct cardstate *cs = bcs->cs;
- unsigned short hw_hdr_len = cs->hw_hdr_len;
-
- if (bcs->ignore) {
- bcs->skb = NULL;
- return;
- }
-
- bcs->skb = dev_alloc_skb(SBUFSIZE + hw_hdr_len);
- if (bcs->skb == NULL) {
- dev_warn(cs->dev, "could not allocate new skb\n");
- return;
- }
- skb_reserve(bcs->skb, hw_hdr_len);
-}
-
/* process a block of received bytes in HDLC data mode
* (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 == L2_HDLC)
* Collect HDLC frames, undoing byte stuffing and watching for DLE escapes.
@@ -159,8 +139,8 @@
struct cardstate *cs = inbuf->cs;
struct bc_state *bcs = cs->bcs;
int inputstate = bcs->inputstate;
- __u16 fcs = bcs->fcs;
- struct sk_buff *skb = bcs->skb;
+ __u16 fcs = bcs->rx_fcs;
+ struct sk_buff *skb = bcs->rx_skb;
unsigned char *src = inbuf->data + inbuf->head;
unsigned procbytes = 0;
unsigned char c;
@@ -245,8 +225,7 @@
/* prepare reception of next frame */
inputstate &= ~INS_have_data;
- new_rcv_skb(bcs);
- skb = bcs->skb;
+ skb = gigaset_new_rx_skb(bcs);
} else {
/* empty frame (7E 7E) */
#ifdef CONFIG_GIGASET_DEBUG
@@ -255,8 +234,7 @@
if (!skb) {
/* skipped (?) */
gigaset_isdn_rcv_err(bcs);
- new_rcv_skb(bcs);
- skb = bcs->skb;
+ skb = gigaset_new_rx_skb(bcs);
}
}
@@ -279,11 +257,11 @@
#endif
inputstate |= INS_have_data;
if (skb) {
- if (skb->len == SBUFSIZE) {
+ if (skb->len >= bcs->rx_bufsize) {
dev_warn(cs->dev, "received packet too long\n");
dev_kfree_skb_any(skb);
/* skip remainder of packet */
- bcs->skb = skb = NULL;
+ bcs->rx_skb = skb = NULL;
} else {
*__skb_put(skb, 1) = c;
fcs = crc_ccitt_byte(fcs, c);
@@ -292,7 +270,7 @@
}
bcs->inputstate = inputstate;
- bcs->fcs = fcs;
+ bcs->rx_fcs = fcs;
return procbytes;
}
@@ -308,18 +286,18 @@
struct cardstate *cs = inbuf->cs;
struct bc_state *bcs = cs->bcs;
int inputstate = bcs->inputstate;
- struct sk_buff *skb = bcs->skb;
+ struct sk_buff *skb = bcs->rx_skb;
unsigned char *src = inbuf->data + inbuf->head;
unsigned procbytes = 0;
unsigned char c;
if (!skb) {
/* skip this block */
- new_rcv_skb(bcs);
+ gigaset_new_rx_skb(bcs);
return numbytes;
}
- while (procbytes < numbytes && skb->len < SBUFSIZE) {
+ while (procbytes < numbytes && skb->len < bcs->rx_bufsize) {
c = *src++;
procbytes++;
@@ -343,7 +321,7 @@
if (inputstate & INS_have_data) {
gigaset_skb_rcvd(bcs, skb);
inputstate &= ~INS_have_data;
- new_rcv_skb(bcs);
+ gigaset_new_rx_skb(bcs);
}
bcs->inputstate = inputstate;
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c
index 8f78f15..6fbe899 100644
--- a/drivers/isdn/gigaset/capi.c
+++ b/drivers/isdn/gigaset/capi.c
@@ -70,7 +70,7 @@
#define MAX_NUMBER_DIGITS 20
#define MAX_FMT_IE_LEN 20
-/* values for gigaset_capi_appl.connected */
+/* values for bcs->apconnstate */
#define APCONN_NONE 0 /* inactive/listening */
#define APCONN_SETUP 1 /* connecting */
#define APCONN_ACTIVE 2 /* B channel up */
@@ -80,10 +80,10 @@
struct list_head ctrlist;
struct gigaset_capi_appl *bcnext;
u16 id;
+ struct capi_register_params rp;
u16 nextMessageNumber;
u32 listenInfoMask;
u32 listenCIPmask;
- int connected;
};
/* CAPI specific controller data structure */
@@ -319,6 +319,39 @@
return result;
}
+/*
+ * emit DATA_B3_CONF message
+ */
+static void send_data_b3_conf(struct cardstate *cs, struct capi_ctr *ctr,
+ u16 appl, u16 msgid, int channel,
+ u16 handle, u16 info)
+{
+ struct sk_buff *cskb;
+ u8 *msg;
+
+ cskb = alloc_skb(CAPI_DATA_B3_CONF_LEN, GFP_ATOMIC);
+ if (!cskb) {
+ dev_err(cs->dev, "%s: out of memory\n", __func__);
+ return;
+ }
+ /* frequent message, avoid _cmsg overhead */
+ msg = __skb_put(cskb, CAPI_DATA_B3_CONF_LEN);
+ CAPIMSG_SETLEN(msg, CAPI_DATA_B3_CONF_LEN);
+ CAPIMSG_SETAPPID(msg, appl);
+ CAPIMSG_SETCOMMAND(msg, CAPI_DATA_B3);
+ CAPIMSG_SETSUBCOMMAND(msg, CAPI_CONF);
+ CAPIMSG_SETMSGID(msg, msgid);
+ CAPIMSG_SETCONTROLLER(msg, ctr->cnr);
+ CAPIMSG_SETPLCI_PART(msg, channel);
+ CAPIMSG_SETNCCI_PART(msg, 1);
+ CAPIMSG_SETHANDLE_CONF(msg, handle);
+ CAPIMSG_SETINFO_CONF(msg, info);
+
+ /* emit message */
+ dump_rawmsg(DEBUG_MCMD, __func__, msg);
+ capi_ctr_handle_message(ctr, appl, cskb);
+}
+
/*
* driver interface functions
@@ -339,7 +372,6 @@
struct gigaset_capi_ctr *iif = cs->iif;
struct gigaset_capi_appl *ap = bcs->ap;
unsigned char *req = skb_mac_header(dskb);
- struct sk_buff *cskb;
u16 flags;
/* update statistics */
@@ -351,39 +383,22 @@
}
/* don't send further B3 messages if disconnected */
- if (ap->connected < APCONN_ACTIVE) {
+ if (bcs->apconnstate < APCONN_ACTIVE) {
gig_dbg(DEBUG_LLDATA, "disconnected, discarding ack");
return;
}
- /* ToDo: honor unset "delivery confirmation" bit */
+ /*
+ * send DATA_B3_CONF if "delivery confirmation" bit was set in request;
+ * otherwise it has already been sent by do_data_b3_req()
+ */
flags = CAPIMSG_FLAGS(req);
-
- /* build DATA_B3_CONF message */
- cskb = alloc_skb(CAPI_DATA_B3_CONF_LEN, GFP_ATOMIC);
- if (!cskb) {
- dev_err(cs->dev, "%s: out of memory\n", __func__);
- return;
- }
- /* frequent message, avoid _cmsg overhead */
- CAPIMSG_SETLEN(cskb->data, CAPI_DATA_B3_CONF_LEN);
- CAPIMSG_SETAPPID(cskb->data, ap->id);
- CAPIMSG_SETCOMMAND(cskb->data, CAPI_DATA_B3);
- CAPIMSG_SETSUBCOMMAND(cskb->data, CAPI_CONF);
- CAPIMSG_SETMSGID(cskb->data, CAPIMSG_MSGID(req));
- CAPIMSG_SETCONTROLLER(cskb->data, iif->ctr.cnr);
- CAPIMSG_SETPLCI_PART(cskb->data, bcs->channel + 1);
- CAPIMSG_SETNCCI_PART(cskb->data, 1);
- CAPIMSG_SETHANDLE_CONF(cskb->data, CAPIMSG_HANDLE_REQ(req));
- if (flags & ~CAPI_FLAGS_DELIVERY_CONFIRMATION)
- CAPIMSG_SETINFO_CONF(cskb->data,
- CapiFlagsNotSupportedByProtocol);
- else
- CAPIMSG_SETINFO_CONF(cskb->data, CAPI_NOERROR);
-
- /* emit message */
- dump_rawmsg(DEBUG_LLDATA, "DATA_B3_CONF", cskb->data);
- capi_ctr_handle_message(&iif->ctr, ap->id, cskb);
+ if (flags & CAPI_FLAGS_DELIVERY_CONFIRMATION)
+ send_data_b3_conf(cs, &iif->ctr, ap->id, CAPIMSG_MSGID(req),
+ bcs->channel + 1, CAPIMSG_HANDLE_REQ(req),
+ (flags & ~CAPI_FLAGS_DELIVERY_CONFIRMATION) ?
+ CapiFlagsNotSupportedByProtocol :
+ CAPI_NOERROR);
}
EXPORT_SYMBOL_GPL(gigaset_skb_sent);
@@ -412,7 +427,7 @@
}
/* don't send further B3 messages if disconnected */
- if (ap->connected < APCONN_ACTIVE) {
+ if (bcs->apconnstate < APCONN_ACTIVE) {
gig_dbg(DEBUG_LLDATA, "disconnected, discarding data");
dev_kfree_skb_any(skb);
return;
@@ -484,6 +499,7 @@
u32 actCIPmask;
struct sk_buff *skb;
unsigned int msgsize;
+ unsigned long flags;
int i;
/*
@@ -608,7 +624,14 @@
format_ie(iif->hcmsg.CalledPartyNumber));
/* scan application list for matching listeners */
- bcs->ap = NULL;
+ spin_lock_irqsave(&bcs->aplock, flags);
+ if (bcs->ap != NULL || bcs->apconnstate != APCONN_NONE) {
+ dev_warn(cs->dev, "%s: channel not properly cleared (%p/%d)\n",
+ __func__, bcs->ap, bcs->apconnstate);
+ bcs->ap = NULL;
+ bcs->apconnstate = APCONN_NONE;
+ }
+ spin_unlock_irqrestore(&bcs->aplock, flags);
actCIPmask = 1 | (1 << iif->hcmsg.CIPValue);
list_for_each_entry(ap, &iif->appls, ctrlist)
if (actCIPmask & ap->listenCIPmask) {
@@ -626,10 +649,12 @@
dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg);
/* add to listeners on this B channel, update state */
+ spin_lock_irqsave(&bcs->aplock, flags);
ap->bcnext = bcs->ap;
bcs->ap = ap;
bcs->chstate |= CHS_NOTIFY_LL;
- ap->connected = APCONN_SETUP;
+ bcs->apconnstate = APCONN_SETUP;
+ spin_unlock_irqrestore(&bcs->aplock, flags);
/* emit message */
capi_ctr_handle_message(&iif->ctr, ap->id, skb);
@@ -654,7 +679,7 @@
struct gigaset_capi_ctr *iif = cs->iif;
struct sk_buff *skb;
- if (ap->connected == APCONN_NONE)
+ if (bcs->apconnstate == APCONN_NONE)
return;
capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT, CAPI_IND,
@@ -668,7 +693,6 @@
}
capi_cmsg2message(&iif->hcmsg, __skb_put(skb, CAPI_DISCONNECT_IND_LEN));
dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg);
- ap->connected = APCONN_NONE;
capi_ctr_handle_message(&iif->ctr, ap->id, skb);
}
@@ -685,9 +709,9 @@
struct sk_buff *skb;
/* nothing to do if no logical connection active */
- if (ap->connected < APCONN_ACTIVE)
+ if (bcs->apconnstate < APCONN_ACTIVE)
return;
- ap->connected = APCONN_SETUP;
+ bcs->apconnstate = APCONN_SETUP;
capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND,
ap->nextMessageNumber++,
@@ -714,14 +738,25 @@
{
struct cardstate *cs = bcs->cs;
struct gigaset_capi_ctr *iif = cs->iif;
- struct gigaset_capi_appl *ap = bcs->ap;
+ struct gigaset_capi_appl *ap;
struct sk_buff *skb;
unsigned int msgsize;
+ unsigned long flags;
+ spin_lock_irqsave(&bcs->aplock, flags);
+ ap = bcs->ap;
if (!ap) {
+ spin_unlock_irqrestore(&bcs->aplock, flags);
dev_err(cs->dev, "%s: no application\n", __func__);
return;
}
+ if (bcs->apconnstate == APCONN_NONE) {
+ spin_unlock_irqrestore(&bcs->aplock, flags);
+ dev_warn(cs->dev, "%s: application %u not connected\n",
+ __func__, ap->id);
+ return;
+ }
+ spin_unlock_irqrestore(&bcs->aplock, flags);
while (ap->bcnext) {
/* this should never happen */
dev_warn(cs->dev, "%s: dropping extra application %u\n",
@@ -730,11 +765,6 @@
CapiCallGivenToOtherApplication);
ap->bcnext = ap->bcnext->bcnext;
}
- if (ap->connected == APCONN_NONE) {
- dev_warn(cs->dev, "%s: application %u not connected\n",
- __func__, ap->id);
- return;
- }
/* prepare CONNECT_ACTIVE_IND message
* Note: LLC not supported by device
@@ -772,17 +802,24 @@
void gigaset_isdn_hupD(struct bc_state *bcs)
{
struct gigaset_capi_appl *ap;
+ unsigned long flags;
/*
* ToDo: pass on reason code reported by device
* (requires ev-layer state machine extension to collect
* ZCAU device reply)
*/
- for (ap = bcs->ap; ap != NULL; ap = ap->bcnext) {
+ spin_lock_irqsave(&bcs->aplock, flags);
+ while (bcs->ap != NULL) {
+ ap = bcs->ap;
+ bcs->ap = ap->bcnext;
+ spin_unlock_irqrestore(&bcs->aplock, flags);
send_disconnect_b3_ind(bcs, ap);
send_disconnect_ind(bcs, ap, 0);
+ spin_lock_irqsave(&bcs->aplock, flags);
}
- bcs->ap = NULL;
+ bcs->apconnstate = APCONN_NONE;
+ spin_unlock_irqrestore(&bcs->aplock, flags);
}
/**
@@ -796,24 +833,21 @@
{
struct cardstate *cs = bcs->cs;
struct gigaset_capi_ctr *iif = cs->iif;
- struct gigaset_capi_appl *ap = bcs->ap;
+ struct gigaset_capi_appl *ap;
struct sk_buff *skb;
+ unsigned long flags;
unsigned int msgsize;
u8 command;
+ spin_lock_irqsave(&bcs->aplock, flags);
+ ap = bcs->ap;
if (!ap) {
+ spin_unlock_irqrestore(&bcs->aplock, flags);
dev_err(cs->dev, "%s: no application\n", __func__);
return;
}
- while (ap->bcnext) {
- /* this should never happen */
- dev_warn(cs->dev, "%s: dropping extra application %u\n",
- __func__, ap->bcnext->id);
- send_disconnect_ind(bcs, ap->bcnext,
- CapiCallGivenToOtherApplication);
- ap->bcnext = ap->bcnext->bcnext;
- }
- if (!ap->connected) {
+ if (!bcs->apconnstate) {
+ spin_unlock_irqrestore(&bcs->aplock, flags);
dev_warn(cs->dev, "%s: application %u not connected\n",
__func__, ap->id);
return;
@@ -825,13 +859,26 @@
* CONNECT_B3_ACTIVE_IND in reply to CONNECT_B3_RESP
* Parameters in both cases always: NCCI = 1, NCPI empty
*/
- if (ap->connected >= APCONN_ACTIVE) {
+ if (bcs->apconnstate >= APCONN_ACTIVE) {
command = CAPI_CONNECT_B3_ACTIVE;
msgsize = CAPI_CONNECT_B3_ACTIVE_IND_BASELEN;
} else {
command = CAPI_CONNECT_B3;
msgsize = CAPI_CONNECT_B3_IND_BASELEN;
}
+ bcs->apconnstate = APCONN_ACTIVE;
+
+ spin_unlock_irqrestore(&bcs->aplock, flags);
+
+ while (ap->bcnext) {
+ /* this should never happen */
+ dev_warn(cs->dev, "%s: dropping extra application %u\n",
+ __func__, ap->bcnext->id);
+ send_disconnect_ind(bcs, ap->bcnext,
+ CapiCallGivenToOtherApplication);
+ ap->bcnext = ap->bcnext->bcnext;
+ }
+
capi_cmsg_header(&iif->hcmsg, ap->id, command, CAPI_IND,
ap->nextMessageNumber++,
iif->ctr.cnr | ((bcs->channel + 1) << 8) | (1 << 16));
@@ -842,7 +889,6 @@
}
capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize));
dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg);
- ap->connected = APCONN_ACTIVE;
capi_ctr_handle_message(&iif->ctr, ap->id, skb);
}
@@ -945,8 +991,64 @@
return;
}
ap->id = appl;
+ ap->rp = *rp;
list_add(&ap->ctrlist, &iif->appls);
+ dev_info(cs->dev, "application %u registered\n", ap->id);
+}
+
+/*
+ * remove CAPI application from channel
+ * helper function to keep indentation levels down and stay in 80 columns
+ */
+
+static inline void remove_appl_from_channel(struct bc_state *bcs,
+ struct gigaset_capi_appl *ap)
+{
+ struct cardstate *cs = bcs->cs;
+ struct gigaset_capi_appl *bcap;
+ unsigned long flags;
+ int prevconnstate;
+
+ spin_lock_irqsave(&bcs->aplock, flags);
+ bcap = bcs->ap;
+ if (bcap == NULL) {
+ spin_unlock_irqrestore(&bcs->aplock, flags);
+ return;
+ }
+
+ /* check first application on channel */
+ if (bcap == ap) {
+ bcs->ap = ap->bcnext;
+ if (bcs->ap != NULL) {
+ spin_unlock_irqrestore(&bcs->aplock, flags);
+ return;
+ }
+
+ /* none left, clear channel state */
+ prevconnstate = bcs->apconnstate;
+ bcs->apconnstate = APCONN_NONE;
+ spin_unlock_irqrestore(&bcs->aplock, flags);
+
+ if (prevconnstate == APCONN_ACTIVE) {
+ dev_notice(cs->dev, "%s: hanging up channel %u\n",
+ __func__, bcs->channel);
+ gigaset_add_event(cs, &bcs->at_state,
+ EV_HUP, NULL, 0, NULL);
+ gigaset_schedule_event(cs);
+ }
+ return;
+ }
+
+ /* check remaining list */
+ do {
+ if (bcap->bcnext == ap) {
+ bcap->bcnext = bcap->bcnext->bcnext;
+ return;
+ }
+ bcap = bcap->bcnext;
+ } while (bcap != NULL);
+ spin_unlock_irqrestore(&bcs->aplock, flags);
}
/*
@@ -958,19 +1060,19 @@
= container_of(ctr, struct gigaset_capi_ctr, ctr);
struct cardstate *cs = iif->ctr.driverdata;
struct gigaset_capi_appl *ap, *tmp;
+ unsigned ch;
list_for_each_entry_safe(ap, tmp, &iif->appls, ctrlist)
if (ap->id == appl) {
- if (ap->connected != APCONN_NONE) {
- dev_err(cs->dev,
- "%s: application %u still connected\n",
- __func__, ap->id);
- /* ToDo: clear active connection */
- }
+ /* remove from any channels */
+ for (ch = 0; ch < cs->channels; ch++)
+ remove_appl_from_channel(&cs->bcs[ch], ap);
+
+ /* remove from registration list */
list_del(&ap->ctrlist);
kfree(ap);
+ dev_info(cs->dev, "application %u released\n", appl);
}
-
}
/*
@@ -1149,7 +1251,8 @@
char **commands;
char *s;
u8 *pp;
- int i, l;
+ unsigned long flags;
+ int i, l, lbc, lhlc;
u16 info;
/* decode message */
@@ -1164,8 +1267,18 @@
send_conf(iif, ap, skb, CapiNoPlciAvailable);
return;
}
+ spin_lock_irqsave(&bcs->aplock, flags);
+ if (bcs->ap != NULL || bcs->apconnstate != APCONN_NONE)
+ dev_warn(cs->dev, "%s: channel not properly cleared (%p/%d)\n",
+ __func__, bcs->ap, bcs->apconnstate);
ap->bcnext = NULL;
bcs->ap = ap;
+ bcs->apconnstate = APCONN_SETUP;
+ spin_unlock_irqrestore(&bcs->aplock, flags);
+
+ bcs->rx_bufsize = ap->rp.datablklen;
+ dev_kfree_skb(bcs->rx_skb);
+ gigaset_new_rx_skb(bcs);
cmsg->adr.adrPLCI |= (bcs->channel + 1) << 8;
/* build command table */
@@ -1273,42 +1386,59 @@
goto error;
}
- /* check/encode parameter: BC */
- if (cmsg->BC && cmsg->BC[0]) {
- /* explicit BC overrides CIP */
- l = 2*cmsg->BC[0] + 7;
+ /*
+ * check/encode parameters: BC & HLC
+ * must be encoded together as device doesn't accept HLC separately
+ * explicit parameters override values derived from CIP
+ */
+
+ /* determine lengths */
+ if (cmsg->BC && cmsg->BC[0]) /* BC specified explicitly */
+ lbc = 2*cmsg->BC[0];
+ else if (cip2bchlc[cmsg->CIPValue].bc) /* BC derived from CIP */
+ lbc = strlen(cip2bchlc[cmsg->CIPValue].bc);
+ else /* no BC */
+ lbc = 0;
+ if (cmsg->HLC && cmsg->HLC[0]) /* HLC specified explicitly */
+ lhlc = 2*cmsg->HLC[0];
+ else if (cip2bchlc[cmsg->CIPValue].hlc) /* HLC derived from CIP */
+ lhlc = strlen(cip2bchlc[cmsg->CIPValue].hlc);
+ else /* no HLC */
+ lhlc = 0;
+
+ if (lbc) {
+ /* have BC: allocate and assemble command string */
+ l = lbc + 7; /* "^SBC=" + value + "\r" + null byte */
+ if (lhlc)
+ l += lhlc + 7; /* ";^SHLC=" + value */
commands[AT_BC] = kmalloc(l, GFP_KERNEL);
if (!commands[AT_BC])
goto oom;
strcpy(commands[AT_BC], "^SBC=");
- decode_ie(cmsg->BC, commands[AT_BC]+5);
+ if (cmsg->BC && cmsg->BC[0]) /* BC specified explicitly */
+ decode_ie(cmsg->BC, commands[AT_BC] + 5);
+ else /* BC derived from CIP */
+ strcpy(commands[AT_BC] + 5,
+ cip2bchlc[cmsg->CIPValue].bc);
+ if (lhlc) {
+ strcpy(commands[AT_BC] + lbc + 5, ";^SHLC=");
+ if (cmsg->HLC && cmsg->HLC[0])
+ /* HLC specified explicitly */
+ decode_ie(cmsg->HLC,
+ commands[AT_BC] + lbc + 12);
+ else /* HLC derived from CIP */
+ strcpy(commands[AT_BC] + lbc + 12,
+ cip2bchlc[cmsg->CIPValue].hlc);
+ }
strcpy(commands[AT_BC] + l - 2, "\r");
- } else if (cip2bchlc[cmsg->CIPValue].bc) {
- l = strlen(cip2bchlc[cmsg->CIPValue].bc) + 7;
- commands[AT_BC] = kmalloc(l, GFP_KERNEL);
- if (!commands[AT_BC])
- goto oom;
- snprintf(commands[AT_BC], l, "^SBC=%s\r",
- cip2bchlc[cmsg->CIPValue].bc);
- }
-
- /* check/encode parameter: HLC */
- if (cmsg->HLC && cmsg->HLC[0]) {
- /* explicit HLC overrides CIP */
- l = 2*cmsg->HLC[0] + 7;
- commands[AT_HLC] = kmalloc(l, GFP_KERNEL);
- if (!commands[AT_HLC])
- goto oom;
- strcpy(commands[AT_HLC], "^SHLC=");
- decode_ie(cmsg->HLC, commands[AT_HLC]+5);
- strcpy(commands[AT_HLC] + l - 2, "\r");
- } else if (cip2bchlc[cmsg->CIPValue].hlc) {
- l = strlen(cip2bchlc[cmsg->CIPValue].hlc) + 7;
- commands[AT_HLC] = kmalloc(l, GFP_KERNEL);
- if (!commands[AT_HLC])
- goto oom;
- snprintf(commands[AT_HLC], l, "^SHLC=%s\r",
- cip2bchlc[cmsg->CIPValue].hlc);
+ } else {
+ /* no BC */
+ if (lhlc) {
+ dev_notice(cs->dev, "%s: cannot set HLC without BC\n",
+ "CONNECT_REQ");
+ info = CapiIllMessageParmCoding; /* ? */
+ goto error;
+ }
}
/* check/encode parameter: B Protocol */
@@ -1322,13 +1452,13 @@
bcs->proto2 = L2_HDLC;
break;
case 1:
- bcs->proto2 = L2_BITSYNC;
+ bcs->proto2 = L2_VOICE;
break;
default:
dev_warn(cs->dev,
"B1 Protocol %u unsupported, using Transparent\n",
cmsg->B1protocol);
- bcs->proto2 = L2_BITSYNC;
+ bcs->proto2 = L2_VOICE;
}
if (cmsg->B2protocol != 1)
dev_warn(cs->dev,
@@ -1382,7 +1512,6 @@
goto error;
}
gigaset_schedule_event(cs);
- ap->connected = APCONN_SETUP;
send_conf(iif, ap, skb, CapiSuccess);
return;
@@ -1410,6 +1539,7 @@
_cmsg *cmsg = &iif->acmsg;
struct bc_state *bcs;
struct gigaset_capi_appl *oap;
+ unsigned long flags;
int channel;
/* decode message */
@@ -1429,12 +1559,24 @@
switch (cmsg->Reject) {
case 0: /* Accept */
/* drop all competing applications, keep only this one */
- for (oap = bcs->ap; oap != NULL; oap = oap->bcnext)
- if (oap != ap)
+ spin_lock_irqsave(&bcs->aplock, flags);
+ while (bcs->ap != NULL) {
+ oap = bcs->ap;
+ bcs->ap = oap->bcnext;
+ if (oap != ap) {
+ spin_unlock_irqrestore(&bcs->aplock, flags);
send_disconnect_ind(bcs, oap,
CapiCallGivenToOtherApplication);
+ spin_lock_irqsave(&bcs->aplock, flags);
+ }
+ }
ap->bcnext = NULL;
bcs->ap = ap;
+ spin_unlock_irqrestore(&bcs->aplock, flags);
+
+ bcs->rx_bufsize = ap->rp.datablklen;
+ dev_kfree_skb(bcs->rx_skb);
+ gigaset_new_rx_skb(bcs);
bcs->chstate |= CHS_NOTIFY_LL;
/* check/encode B channel protocol */
@@ -1448,13 +1590,13 @@
bcs->proto2 = L2_HDLC;
break;
case 1:
- bcs->proto2 = L2_BITSYNC;
+ bcs->proto2 = L2_VOICE;
break;
default:
dev_warn(cs->dev,
"B1 Protocol %u unsupported, using Transparent\n",
cmsg->B1protocol);
- bcs->proto2 = L2_BITSYNC;
+ bcs->proto2 = L2_VOICE;
}
if (cmsg->B2protocol != 1)
dev_warn(cs->dev,
@@ -1502,31 +1644,45 @@
send_disconnect_ind(bcs, ap, 0);
/* remove it from the list of listening apps */
+ spin_lock_irqsave(&bcs->aplock, flags);
if (bcs->ap == ap) {
bcs->ap = ap->bcnext;
- if (bcs->ap == NULL)
+ if (bcs->ap == NULL) {
/* last one: stop ev-layer hupD notifications */
+ bcs->apconnstate = APCONN_NONE;
bcs->chstate &= ~CHS_NOTIFY_LL;
+ }
+ spin_unlock_irqrestore(&bcs->aplock, flags);
return;
}
for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) {
if (oap->bcnext == ap) {
oap->bcnext = oap->bcnext->bcnext;
+ spin_unlock_irqrestore(&bcs->aplock, flags);
return;
}
}
+ spin_unlock_irqrestore(&bcs->aplock, flags);
dev_err(cs->dev, "%s: application %u not found\n",
__func__, ap->id);
return;
default: /* Reject */
/* drop all competing applications, keep only this one */
- for (oap = bcs->ap; oap != NULL; oap = oap->bcnext)
- if (oap != ap)
+ spin_lock_irqsave(&bcs->aplock, flags);
+ while (bcs->ap != NULL) {
+ oap = bcs->ap;
+ bcs->ap = oap->bcnext;
+ if (oap != ap) {
+ spin_unlock_irqrestore(&bcs->aplock, flags);
send_disconnect_ind(bcs, oap,
CapiCallGivenToOtherApplication);
+ spin_lock_irqsave(&bcs->aplock, flags);
+ }
+ }
ap->bcnext = NULL;
bcs->ap = ap;
+ spin_unlock_irqrestore(&bcs->aplock, flags);
/* reject call - will trigger DISCONNECT_IND for this app */
dev_info(cs->dev, "%s: Reject=%x\n",
@@ -1549,6 +1705,7 @@
{
struct cardstate *cs = iif->ctr.driverdata;
_cmsg *cmsg = &iif->acmsg;
+ struct bc_state *bcs;
int channel;
/* decode message */
@@ -1563,9 +1720,10 @@
send_conf(iif, ap, skb, CapiIllContrPlciNcci);
return;
}
+ bcs = &cs->bcs[channel-1];
/* mark logical connection active */
- ap->connected = APCONN_ACTIVE;
+ bcs->apconnstate = APCONN_ACTIVE;
/* build NCCI: always 1 (one B3 connection only) */
cmsg->adr.adrNCCI |= 1 << 16;
@@ -1611,7 +1769,7 @@
if (cmsg->Reject) {
/* Reject: clear B3 connect received flag */
- ap->connected = APCONN_SETUP;
+ bcs->apconnstate = APCONN_SETUP;
/* trigger hangup, causing eventual DISCONNECT_IND */
if (!gigaset_add_event(cs, &bcs->at_state,
@@ -1683,11 +1841,11 @@
}
/* skip if DISCONNECT_IND already sent */
- if (!ap->connected)
+ if (!bcs->apconnstate)
return;
/* check for active logical connection */
- if (ap->connected >= APCONN_ACTIVE) {
+ if (bcs->apconnstate >= APCONN_ACTIVE) {
/*
* emit DISCONNECT_B3_IND with cause 0x3301
* use separate cmsg structure, as the content of iif->acmsg
@@ -1736,6 +1894,7 @@
{
struct cardstate *cs = iif->ctr.driverdata;
_cmsg *cmsg = &iif->acmsg;
+ struct bc_state *bcs;
int channel;
/* decode message */
@@ -1751,17 +1910,17 @@
send_conf(iif, ap, skb, CapiIllContrPlciNcci);
return;
}
+ bcs = &cs->bcs[channel-1];
/* reject if logical connection not active */
- if (ap->connected < APCONN_ACTIVE) {
+ if (bcs->apconnstate < APCONN_ACTIVE) {
send_conf(iif, ap, skb,
CapiMessageNotSupportedInCurrentState);
return;
}
/* trigger hangup, causing eventual DISCONNECT_B3_IND */
- if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state,
- EV_HUP, NULL, 0, NULL)) {
+ if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) {
send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR);
return;
}
@@ -1782,11 +1941,14 @@
struct sk_buff *skb)
{
struct cardstate *cs = iif->ctr.driverdata;
+ struct bc_state *bcs;
int channel = CAPIMSG_PLCI_PART(skb->data);
u16 ncci = CAPIMSG_NCCI_PART(skb->data);
u16 msglen = CAPIMSG_LEN(skb->data);
u16 datalen = CAPIMSG_DATALEN(skb->data);
u16 flags = CAPIMSG_FLAGS(skb->data);
+ u16 msgid = CAPIMSG_MSGID(skb->data);
+ u16 handle = CAPIMSG_HANDLE_REQ(skb->data);
/* frequent message, avoid _cmsg overhead */
dump_rawmsg(DEBUG_LLDATA, "DATA_B3_REQ", skb->data);
@@ -1802,6 +1964,7 @@
send_conf(iif, ap, skb, CapiIllContrPlciNcci);
return;
}
+ bcs = &cs->bcs[channel-1];
if (msglen != CAPI_DATA_B3_REQ_LEN && msglen != CAPI_DATA_B3_REQ_LEN64)
dev_notice(cs->dev, "%s: unexpected length %d\n",
"DATA_B3_REQ", msglen);
@@ -1821,7 +1984,7 @@
}
/* reject if logical connection not active */
- if (ap->connected < APCONN_ACTIVE) {
+ if (bcs->apconnstate < APCONN_ACTIVE) {
send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState);
return;
}
@@ -1832,17 +1995,19 @@
skb_pull(skb, msglen);
/* pass to device-specific module */
- if (cs->ops->send_skb(&cs->bcs[channel-1], skb) < 0) {
+ if (cs->ops->send_skb(bcs, skb) < 0) {
send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR);
return;
}
- /* DATA_B3_CONF reply will be sent by gigaset_skb_sent() */
-
/*
- * ToDo: honor unset "delivery confirmation" bit
- * (send DATA_B3_CONF immediately?)
+ * DATA_B3_CONF will be sent by gigaset_skb_sent() only if "delivery
+ * confirmation" bit is set; otherwise we have to send it now
*/
+ if (!(flags & CAPI_FLAGS_DELIVERY_CONFIRMATION))
+ send_data_b3_conf(cs, &iif->ctr, ap->id, msgid, channel, handle,
+ flags ? CapiFlagsNotSupportedByProtocol
+ : CAPI_NOERROR);
}
/*
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index f6f45f2..5d4befb 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -399,8 +399,8 @@
gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel);
clear_at_state(&bcs->at_state);
gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel);
- dev_kfree_skb(bcs->skb);
- bcs->skb = NULL;
+ dev_kfree_skb(bcs->rx_skb);
+ bcs->rx_skb = NULL;
for (i = 0; i < AT_NUM; ++i) {
kfree(bcs->commands[i]);
@@ -634,19 +634,10 @@
bcs->emptycount = 0;
#endif
- gig_dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel);
- bcs->fcs = PPP_INITFCS;
+ bcs->rx_bufsize = 0;
+ bcs->rx_skb = NULL;
+ bcs->rx_fcs = PPP_INITFCS;
bcs->inputstate = 0;
- if (cs->ignoreframes) {
- bcs->skb = NULL;
- } else {
- bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
- if (bcs->skb != NULL)
- skb_reserve(bcs->skb, cs->hw_hdr_len);
- else
- pr_err("out of memory\n");
- }
-
bcs->channel = channel;
bcs->cs = cs;
@@ -658,16 +649,15 @@
for (i = 0; i < AT_NUM; ++i)
bcs->commands[i] = NULL;
+ spin_lock_init(&bcs->aplock);
+ bcs->ap = NULL;
+ bcs->apconnstate = 0;
+
gig_dbg(DEBUG_INIT, " setting up bcs[%d]->hw", channel);
if (cs->ops->initbcshw(bcs))
return bcs;
gig_dbg(DEBUG_INIT, " failed");
-
- gig_dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel);
- dev_kfree_skb(bcs->skb);
- bcs->skb = NULL;
-
return NULL;
}
@@ -839,14 +829,12 @@
bcs->emptycount = 0;
#endif
- bcs->fcs = PPP_INITFCS;
+ bcs->rx_fcs = PPP_INITFCS;
bcs->chstate = 0;
bcs->ignore = cs->ignoreframes;
- if (bcs->ignore) {
- dev_kfree_skb(bcs->skb);
- bcs->skb = NULL;
- }
+ dev_kfree_skb(bcs->rx_skb);
+ bcs->rx_skb = NULL;
cs->ops->reinitbcshw(bcs);
}
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c
index 206c380..ceaef9a 100644
--- a/drivers/isdn/gigaset/ev-layer.c
+++ b/drivers/isdn/gigaset/ev-layer.c
@@ -282,9 +282,7 @@
/* dial */
{EV_DIAL, -1, -1, -1, -1, -1, {ACT_DIAL} },
{RSP_INIT, 0, 0, SEQ_DIAL, 601, 5, {ACT_CMD+AT_BC} },
-{RSP_OK, 601, 601, -1, 602, 5, {ACT_CMD+AT_HLC} },
-{RSP_NULL, 602, 602, -1, 603, 5, {ACT_CMD+AT_PROTO} },
-{RSP_OK, 602, 602, -1, 603, 5, {ACT_CMD+AT_PROTO} },
+{RSP_OK, 601, 601, -1, 603, 5, {ACT_CMD+AT_PROTO} },
{RSP_OK, 603, 603, -1, 604, 5, {ACT_CMD+AT_TYPE} },
{RSP_OK, 604, 604, -1, 605, 5, {ACT_CMD+AT_MSN} },
{RSP_NULL, 605, 605, -1, 606, 5, {ACT_CMD+AT_CLIP} },
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index 05947f9..8738b08 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -45,10 +45,6 @@
#define MAX_EVENTS 64 /* size of event queue */
#define RBUFSIZE 8192
-#define SBUFSIZE 4096 /* sk_buff payload size */
-
-#define TRANSBUFSIZE 768 /* bytes per skb for transparent receive */
-#define MAX_BUF_SIZE (SBUFSIZE - 2) /* Max. size of a data packet from LL */
/* compile time options */
#define GIG_MAJOR 0
@@ -190,10 +186,9 @@
#define AT_BC 3
#define AT_PROTO 4
#define AT_TYPE 5
-#define AT_HLC 6
-#define AT_CLIP 7
+#define AT_CLIP 6
/* total number */
-#define AT_NUM 8
+#define AT_NUM 7
/* variables in struct at_state_t */
#define VAR_ZSAU 0
@@ -380,8 +375,10 @@
struct at_state_t at_state;
- __u16 fcs;
- struct sk_buff *skb;
+ /* receive buffer */
+ unsigned rx_bufsize; /* max size accepted by application */
+ struct sk_buff *rx_skb;
+ __u16 rx_fcs;
int inputstate; /* see INS_XXXX */
int channel;
@@ -406,7 +403,9 @@
struct bas_bc_state *bas; /* usb hardware driver (base) */
} hw;
- void *ap; /* LL application structure */
+ void *ap; /* associated LL application */
+ int apconnstate; /* LL application connection state */
+ spinlock_t aplock;
};
struct cardstate {
@@ -801,8 +800,23 @@
gigaset_schedule_event(bcs->cs);
}
-/* handling routines for sk_buff */
-/* ============================= */
+/* set up next receive skb for data mode */
+static inline struct sk_buff *gigaset_new_rx_skb(struct bc_state *bcs)
+{
+ struct cardstate *cs = bcs->cs;
+ unsigned short hw_hdr_len = cs->hw_hdr_len;
+
+ if (bcs->ignore) {
+ bcs->rx_skb = NULL;
+ } else {
+ bcs->rx_skb = dev_alloc_skb(bcs->rx_bufsize + hw_hdr_len);
+ if (bcs->rx_skb == NULL)
+ dev_warn(cs->dev, "could not allocate skb\n");
+ else
+ skb_reserve(bcs->rx_skb, hw_hdr_len);
+ }
+ return bcs->rx_skb;
+}
/* append received bytes to inbuf */
int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c
index c22e5ac..f01c3c2 100644
--- a/drivers/isdn/gigaset/i4l.c
+++ b/drivers/isdn/gigaset/i4l.c
@@ -16,7 +16,10 @@
#include "gigaset.h"
#include <linux/isdnif.h>
+#define SBUFSIZE 4096 /* sk_buff payload size */
+#define TRANSBUFSIZE 768 /* bytes per skb for transparent receive */
#define HW_HDR_LEN 2 /* Header size used to store ack info */
+#define MAX_BUF_SIZE (SBUFSIZE - HW_HDR_LEN) /* max data packet from LL */
/* == Handling of I4L IO =====================================================*/
@@ -231,6 +234,15 @@
dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n");
return -EBUSY;
}
+ switch (bcs->proto2) {
+ case L2_HDLC:
+ bcs->rx_bufsize = SBUFSIZE;
+ break;
+ default: /* assume transparent */
+ bcs->rx_bufsize = TRANSBUFSIZE;
+ }
+ dev_kfree_skb(bcs->rx_skb);
+ gigaset_new_rx_skb(bcs);
commands = kzalloc(AT_NUM*(sizeof *commands), GFP_ATOMIC);
if (!commands) {
@@ -314,6 +326,15 @@
return -EINVAL;
}
bcs = cs->bcs + ch;
+ switch (bcs->proto2) {
+ case L2_HDLC:
+ bcs->rx_bufsize = SBUFSIZE;
+ break;
+ default: /* assume transparent */
+ bcs->rx_bufsize = TRANSBUFSIZE;
+ }
+ dev_kfree_skb(bcs->rx_skb);
+ gigaset_new_rx_skb(bcs);
if (!gigaset_add_event(cs, &bcs->at_state,
EV_ACCEPT, NULL, 0, NULL))
return -ENOMEM;
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c
index 16fd3bd..2dfd346 100644
--- a/drivers/isdn/gigaset/isocdata.c
+++ b/drivers/isdn/gigaset/isocdata.c
@@ -500,19 +500,18 @@
*/
static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs)
{
- bcs->fcs = crc_ccitt_byte(bcs->fcs, c);
- if (unlikely(bcs->skb == NULL)) {
+ bcs->rx_fcs = crc_ccitt_byte(bcs->rx_fcs, c);
+ if (bcs->rx_skb == NULL)
/* skipping */
return;
- }
- if (unlikely(bcs->skb->len == SBUFSIZE)) {
+ if (bcs->rx_skb->len >= bcs->rx_bufsize) {
dev_warn(bcs->cs->dev, "received oversized packet discarded\n");
bcs->hw.bas->giants++;
- dev_kfree_skb_any(bcs->skb);
- bcs->skb = NULL;
+ dev_kfree_skb_any(bcs->rx_skb);
+ bcs->rx_skb = NULL;
return;
}
- *__skb_put(bcs->skb, 1) = c;
+ *__skb_put(bcs->rx_skb, 1) = c;
}
/* hdlc_flush
@@ -521,18 +520,13 @@
static inline void hdlc_flush(struct bc_state *bcs)
{
/* clear skb or allocate new if not skipping */
- if (likely(bcs->skb != NULL))
- skb_trim(bcs->skb, 0);
- else if (!bcs->ignore) {
- bcs->skb = dev_alloc_skb(SBUFSIZE + bcs->cs->hw_hdr_len);
- if (bcs->skb)
- skb_reserve(bcs->skb, bcs->cs->hw_hdr_len);
- else
- dev_err(bcs->cs->dev, "could not allocate skb\n");
- }
+ if (bcs->rx_skb != NULL)
+ skb_trim(bcs->rx_skb, 0);
+ else
+ gigaset_new_rx_skb(bcs);
/* reset packet state */
- bcs->fcs = PPP_INITFCS;
+ bcs->rx_fcs = PPP_INITFCS;
}
/* hdlc_done
@@ -549,7 +543,7 @@
hdlc_flush(bcs);
return;
}
- procskb = bcs->skb;
+ procskb = bcs->rx_skb;
if (procskb == NULL) {
/* previous error */
gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__);
@@ -560,8 +554,8 @@
bcs->hw.bas->runts++;
dev_kfree_skb_any(procskb);
gigaset_isdn_rcv_err(bcs);
- } else if (bcs->fcs != PPP_GOODFCS) {
- dev_notice(cs->dev, "frame check error (0x%04x)\n", bcs->fcs);
+ } else if (bcs->rx_fcs != PPP_GOODFCS) {
+ dev_notice(cs->dev, "frame check error\n");
bcs->hw.bas->fcserrs++;
dev_kfree_skb_any(procskb);
gigaset_isdn_rcv_err(bcs);
@@ -574,13 +568,8 @@
bcs->hw.bas->goodbytes += len;
gigaset_skb_rcvd(bcs, procskb);
}
-
- bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
- if (bcs->skb)
- skb_reserve(bcs->skb, cs->hw_hdr_len);
- else
- dev_err(cs->dev, "could not allocate skb\n");
- bcs->fcs = PPP_INITFCS;
+ gigaset_new_rx_skb(bcs);
+ bcs->rx_fcs = PPP_INITFCS;
}
/* hdlc_frag
@@ -597,8 +586,8 @@
dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits);
bcs->hw.bas->alignerrs++;
gigaset_isdn_rcv_err(bcs);
- __skb_trim(bcs->skb, 0);
- bcs->fcs = PPP_INITFCS;
+ __skb_trim(bcs->rx_skb, 0);
+ bcs->rx_fcs = PPP_INITFCS;
}
/* bit counts lookup table for HDLC bit unstuffing
@@ -847,7 +836,6 @@
static inline void trans_receive(unsigned char *src, unsigned count,
struct bc_state *bcs)
{
- struct cardstate *cs = bcs->cs;
struct sk_buff *skb;
int dobytes;
unsigned char *dst;
@@ -857,17 +845,11 @@
hdlc_flush(bcs);
return;
}
- skb = bcs->skb;
- if (unlikely(skb == NULL)) {
- bcs->skb = skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
- if (!skb) {
- dev_err(cs->dev, "could not allocate skb\n");
- return;
- }
- skb_reserve(skb, cs->hw_hdr_len);
- }
+ skb = bcs->rx_skb;
+ if (skb == NULL)
+ skb = gigaset_new_rx_skb(bcs);
bcs->hw.bas->goodbytes += skb->len;
- dobytes = TRANSBUFSIZE - skb->len;
+ dobytes = bcs->rx_bufsize - skb->len;
while (count > 0) {
dst = skb_put(skb, count < dobytes ? count : dobytes);
while (count > 0 && dobytes > 0) {
@@ -879,14 +861,10 @@
dump_bytes(DEBUG_STREAM_DUMP,
"rcv data", skb->data, skb->len);
gigaset_skb_rcvd(bcs, skb);
- bcs->skb = skb =
- dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
- if (!skb) {
- dev_err(cs->dev, "could not allocate skb\n");
+ skb = gigaset_new_rx_skb(bcs);
+ if (skb == NULL)
return;
- }
- skb_reserve(skb, cs->hw_hdr_len);
- dobytes = TRANSBUFSIZE;
+ dobytes = bcs->rx_bufsize;
}
}
}
diff --git a/drivers/isdn/hysdn/hysdn_net.c b/drivers/isdn/hysdn/hysdn_net.c
index 72eb926..feec8d8 100644
--- a/drivers/isdn/hysdn/hysdn_net.c
+++ b/drivers/isdn/hysdn/hysdn_net.c
@@ -187,12 +187,13 @@
hysdn_rx_netpkt(hysdn_card * card, unsigned char *buf, unsigned short len)
{
struct net_local *lp = card->netif;
- struct net_device *dev = lp->dev;
+ struct net_device *dev;
struct sk_buff *skb;
if (!lp)
return; /* non existing device */
+ dev = lp->dev;
dev->stats.rx_bytes += len;
skb = dev_alloc_skb(len);
diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c
index 286b501..5dcdf9d 100644
--- a/drivers/leds/leds-bd2802.c
+++ b/drivers/leds/leds-bd2802.c
@@ -742,7 +742,6 @@
for (i--; i >= 0; i--)
device_remove_file(&led->client->dev, bd2802_attributes[i]);
failed_free:
- i2c_set_clientdata(client, NULL);
kfree(led);
return ret;
@@ -759,7 +758,6 @@
bd2802_disable_adv_conf(led);
for (i = 0; i < ARRAY_SIZE(bd2802_attributes); i++)
device_remove_file(&led->client->dev, bd2802_attributes[i]);
- i2c_set_clientdata(client, NULL);
kfree(led);
return 0;
diff --git a/drivers/leds/leds-lp3944.c b/drivers/leds/leds-lp3944.c
index 932a58d..9010c05 100644
--- a/drivers/leds/leds-lp3944.c
+++ b/drivers/leds/leds-lp3944.c
@@ -432,7 +432,6 @@
}
kfree(data);
- i2c_set_clientdata(client, NULL);
return 0;
}
diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c
index 6682175..43d0875 100644
--- a/drivers/leds/leds-pca9532.c
+++ b/drivers/leds/leds-pca9532.c
@@ -320,10 +320,8 @@
mutex_init(&data->update_lock);
err = pca9532_configure(client, data, pca9532_pdata);
- if (err) {
+ if (err)
kfree(data);
- i2c_set_clientdata(client, NULL);
- }
return err;
}
@@ -351,7 +349,6 @@
}
kfree(data);
- i2c_set_clientdata(client, NULL);
return 0;
}
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
index 8ff50f2..66aa3e8 100644
--- a/drivers/leds/leds-pca955x.c
+++ b/drivers/leds/leds-pca955x.c
@@ -342,7 +342,6 @@
}
kfree(pca955x);
- i2c_set_clientdata(client, NULL);
return err;
}
@@ -358,7 +357,6 @@
}
kfree(pca955x);
- i2c_set_clientdata(client, NULL);
return 0;
}
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c
index 9714780..b6e7ddc 100644
--- a/drivers/macintosh/macio_asic.c
+++ b/drivers/macintosh/macio_asic.c
@@ -492,8 +492,8 @@
}
/* Add media bay devices if any */
- pnode = mbdev->ofdev.dev.of_node;
- if (mbdev)
+ if (mbdev) {
+ pnode = mbdev->ofdev.dev.of_node;
for (np = NULL; (np = of_get_next_child(pnode, np)) != NULL;) {
if (macio_skip_device(np))
continue;
@@ -502,10 +502,11 @@
mbdev, root_res) == NULL)
of_node_put(np);
}
+ }
/* Add serial ports if any */
- pnode = sdev->ofdev.dev.of_node;
if (sdev) {
+ pnode = sdev->ofdev.dev.of_node;
for (np = NULL; (np = of_get_next_child(pnode, np)) != NULL;) {
if (macio_skip_device(np))
continue;
@@ -525,7 +526,6 @@
int macio_register_driver(struct macio_driver *drv)
{
/* initialize common driver fields */
- drv->driver.name = drv->name;
drv->driver.bus = &macio_bus_type;
/* register with core */
diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
index 288acce..2fd435b 100644
--- a/drivers/macintosh/mediabay.c
+++ b/drivers/macintosh/mediabay.c
@@ -728,8 +728,10 @@
static struct macio_driver media_bay_driver =
{
- .name = "media-bay",
- .match_table = media_bay_match,
+ .driver = {
+ .name = "media-bay",
+ .of_match_table = media_bay_match,
+ },
.probe = media_bay_attach,
.suspend = media_bay_suspend,
.resume = media_bay_resume
diff --git a/drivers/macintosh/rack-meter.c b/drivers/macintosh/rack-meter.c
index 12946c5..53cce3a 100644
--- a/drivers/macintosh/rack-meter.c
+++ b/drivers/macintosh/rack-meter.c
@@ -584,9 +584,11 @@
};
static struct macio_driver rackmeter_driver = {
- .name = "rackmeter",
- .owner = THIS_MODULE,
- .match_table = rackmeter_match,
+ .driver = {
+ .name = "rackmeter",
+ .owner = THIS_MODULE,
+ .of_match_table = rackmeter_match,
+ },
.probe = rackmeter_probe,
.remove = __devexit_p(rackmeter_remove),
.shutdown = rackmeter_shutdown,
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index 16d82f1..c42eeb4 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -182,7 +182,6 @@
thermostat = NULL;
- i2c_set_clientdata(client, NULL);
kfree(th);
return 0;
@@ -400,7 +399,6 @@
rc = read_reg(th, CONFIG_REG);
if (rc < 0) {
dev_err(&client->dev, "Thermostat failed to read config!\n");
- i2c_set_clientdata(client, NULL);
kfree(th);
return -ENODEV;
}
diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c
index d8257d3..647c6ad 100644
--- a/drivers/macintosh/windfarm_lm75_sensor.c
+++ b/drivers/macintosh/windfarm_lm75_sensor.c
@@ -107,10 +107,8 @@
i2c_set_clientdata(client, lm);
rc = wf_register_sensor(&lm->sens);
- if (rc) {
- i2c_set_clientdata(client, NULL);
+ if (rc)
kfree(lm);
- }
return rc;
}
@@ -216,7 +214,6 @@
/* release sensor */
wf_unregister_sensor(&lm->sens);
- i2c_set_clientdata(client, NULL);
return 0;
}
diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c
index b486eb9..8204113 100644
--- a/drivers/macintosh/windfarm_max6690_sensor.c
+++ b/drivers/macintosh/windfarm_max6690_sensor.c
@@ -81,7 +81,6 @@
rc = wf_register_sensor(&max->sens);
if (rc) {
- i2c_set_clientdata(client, NULL);
kfree(max);
}
diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c
index e20330a..65a8ff3 100644
--- a/drivers/macintosh/windfarm_smu_sat.c
+++ b/drivers/macintosh/windfarm_smu_sat.c
@@ -376,7 +376,6 @@
/* XXX TODO */
sat->i2c = NULL;
- i2c_set_clientdata(client, NULL);
return 0;
}
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 46b3a04..cb20d0b 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2087,6 +2087,7 @@
/* First make sure individual recovery_offsets are correct */
list_for_each_entry(rdev, &mddev->disks, same_set) {
if (rdev->raid_disk >= 0 &&
+ mddev->delta_disks >= 0 &&
!test_bit(In_sync, &rdev->flags) &&
mddev->curr_resync_completed > rdev->recovery_offset)
rdev->recovery_offset = mddev->curr_resync_completed;
@@ -3001,6 +3002,9 @@
return -EINVAL;
}
+ list_for_each_entry(rdev, &mddev->disks, same_set)
+ rdev->new_raid_disk = rdev->raid_disk;
+
/* ->takeover must set new_* and/or delta_disks
* if it succeeds, and may set them when it fails.
*/
@@ -3051,13 +3055,35 @@
mddev->safemode = 0;
}
- module_put(mddev->pers->owner);
- /* Invalidate devices that are now superfluous */
- list_for_each_entry(rdev, &mddev->disks, same_set)
- if (rdev->raid_disk >= mddev->raid_disks) {
- rdev->raid_disk = -1;
+ list_for_each_entry(rdev, &mddev->disks, same_set) {
+ char nm[20];
+ if (rdev->raid_disk < 0)
+ continue;
+ if (rdev->new_raid_disk > mddev->raid_disks)
+ rdev->new_raid_disk = -1;
+ if (rdev->new_raid_disk == rdev->raid_disk)
+ continue;
+ sprintf(nm, "rd%d", rdev->raid_disk);
+ sysfs_remove_link(&mddev->kobj, nm);
+ }
+ list_for_each_entry(rdev, &mddev->disks, same_set) {
+ if (rdev->raid_disk < 0)
+ continue;
+ if (rdev->new_raid_disk == rdev->raid_disk)
+ continue;
+ rdev->raid_disk = rdev->new_raid_disk;
+ if (rdev->raid_disk < 0)
clear_bit(In_sync, &rdev->flags);
+ else {
+ char nm[20];
+ sprintf(nm, "rd%d", rdev->raid_disk);
+ if(sysfs_create_link(&mddev->kobj, &rdev->kobj, nm))
+ printk("md: cannot register %s for %s after level change\n",
+ nm, mdname(mddev));
}
+ }
+
+ module_put(mddev->pers->owner);
mddev->pers = pers;
mddev->private = priv;
strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
@@ -5895,6 +5921,7 @@
atomic_inc(&mddev->openers);
mutex_unlock(&mddev->open_mutex);
+ check_disk_size_change(mddev->gendisk, bdev);
out:
return err;
}
@@ -6846,6 +6873,7 @@
rcu_read_lock();
list_for_each_entry_rcu(rdev, &mddev->disks, same_set)
if (rdev->raid_disk >= 0 &&
+ mddev->delta_disks >= 0 &&
!test_bit(Faulty, &rdev->flags) &&
!test_bit(In_sync, &rdev->flags) &&
rdev->recovery_offset < mddev->curr_resync)
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 7ab5ea1..10597bf 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -78,6 +78,9 @@
int desc_nr; /* descriptor index in the superblock */
int raid_disk; /* role of device in array */
+ int new_raid_disk; /* role that the device will have in
+ * the array after a level-change completes.
+ */
int saved_raid_disk; /* role that device used to have in the
* array and could again if we did a partial
* resync from the bitmap
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index e70f004..563abed 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -173,9 +173,11 @@
list_for_each_entry(rdev1, &mddev->disks, same_set) {
int j = rdev1->raid_disk;
- if (mddev->level == 10)
+ if (mddev->level == 10) {
/* taking over a raid10-n2 array */
j /= 2;
+ rdev1->new_raid_disk = j;
+ }
if (j < 0 || j >= mddev->raid_disks) {
printk(KERN_ERR "md/raid0:%s: bad disk number %d - "
@@ -361,12 +363,6 @@
mddev->private = conf;
}
conf = mddev->private;
- if (conf->scale_raid_disks) {
- int i;
- for (i=0; i < conf->strip_zone[0].nb_dev; i++)
- conf->devlist[i]->raid_disk /= conf->scale_raid_disks;
- /* FIXME update sysfs rd links */
- }
/* calculate array device size */
md_set_array_sectors(mddev, raid0_size(mddev, 0, 0));
@@ -573,7 +569,7 @@
return;
}
-static void *raid0_takeover_raid5(mddev_t *mddev)
+static void *raid0_takeover_raid45(mddev_t *mddev)
{
mdk_rdev_t *rdev;
raid0_conf_t *priv_conf;
@@ -596,6 +592,7 @@
/* Set new parameters */
mddev->new_level = 0;
+ mddev->new_layout = 0;
mddev->new_chunk_sectors = mddev->chunk_sectors;
mddev->raid_disks--;
mddev->delta_disks = -1;
@@ -635,6 +632,7 @@
/* Set new parameters */
mddev->new_level = 0;
+ mddev->new_layout = 0;
mddev->new_chunk_sectors = mddev->chunk_sectors;
mddev->delta_disks = - mddev->raid_disks / 2;
mddev->raid_disks += mddev->delta_disks;
@@ -643,19 +641,22 @@
mddev->recovery_cp = MaxSector;
create_strip_zones(mddev, &priv_conf);
- priv_conf->scale_raid_disks = 2;
return priv_conf;
}
static void *raid0_takeover(mddev_t *mddev)
{
/* raid0 can take over:
+ * raid4 - if all data disks are active.
* raid5 - providing it is Raid4 layout and one disk is faulty
* raid10 - assuming we have all necessary active disks
*/
+ if (mddev->level == 4)
+ return raid0_takeover_raid45(mddev);
+
if (mddev->level == 5) {
if (mddev->layout == ALGORITHM_PARITY_N)
- return raid0_takeover_raid5(mddev);
+ return raid0_takeover_raid45(mddev);
printk(KERN_ERR "md/raid0:%s: Raid can only takeover Raid5 with layout: %d\n",
mdname(mddev), ALGORITHM_PARITY_N);
diff --git a/drivers/md/raid0.h b/drivers/md/raid0.h
index d724e66..91f8e87 100644
--- a/drivers/md/raid0.h
+++ b/drivers/md/raid0.h
@@ -13,9 +13,6 @@
struct strip_zone *strip_zone;
mdk_rdev_t **devlist; /* lists of rdevs, pointed to by strip_zone->dev */
int nr_strip_zones;
- int scale_raid_disks; /* divide rdev->raid_disks by this in run()
- * to handle conversion from raid10
- */
};
typedef struct raid0_private_data raid0_conf_t;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 0372499..42e64e4 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1482,14 +1482,14 @@
int sectors = r10_bio->sectors;
mdk_rdev_t*rdev;
int max_read_errors = atomic_read(&mddev->max_corr_read_errors);
+ int d = r10_bio->devs[r10_bio->read_slot].devnum;
rcu_read_lock();
- {
- int d = r10_bio->devs[r10_bio->read_slot].devnum;
+ rdev = rcu_dereference(conf->mirrors[d].rdev);
+ if (rdev) { /* If rdev is not NULL */
char b[BDEVNAME_SIZE];
int cur_read_error_count = 0;
- rdev = rcu_dereference(conf->mirrors[d].rdev);
bdevname(rdev->bdev, b);
if (test_bit(Faulty, &rdev->flags)) {
@@ -1530,7 +1530,7 @@
rcu_read_lock();
do {
- int d = r10_bio->devs[sl].devnum;
+ d = r10_bio->devs[sl].devnum;
rdev = rcu_dereference(conf->mirrors[d].rdev);
if (rdev &&
test_bit(In_sync, &rdev->flags)) {
@@ -1564,7 +1564,7 @@
rcu_read_lock();
while (sl != r10_bio->read_slot) {
char b[BDEVNAME_SIZE];
- int d;
+
if (sl==0)
sl = conf->copies;
sl--;
@@ -1601,7 +1601,7 @@
}
sl = start;
while (sl != r10_bio->read_slot) {
- int d;
+
if (sl==0)
sl = conf->copies;
sl--;
@@ -2161,22 +2161,22 @@
sector_t stride, size;
int err = -EINVAL;
- if (mddev->chunk_sectors < (PAGE_SIZE >> 9) ||
- !is_power_of_2(mddev->chunk_sectors)) {
+ if (mddev->new_chunk_sectors < (PAGE_SIZE >> 9) ||
+ !is_power_of_2(mddev->new_chunk_sectors)) {
printk(KERN_ERR "md/raid10:%s: chunk size must be "
"at least PAGE_SIZE(%ld) and be a power of 2.\n",
mdname(mddev), PAGE_SIZE);
goto out;
}
- nc = mddev->layout & 255;
- fc = (mddev->layout >> 8) & 255;
- fo = mddev->layout & (1<<16);
+ nc = mddev->new_layout & 255;
+ fc = (mddev->new_layout >> 8) & 255;
+ fo = mddev->new_layout & (1<<16);
if ((nc*fc) <2 || (nc*fc) > mddev->raid_disks ||
- (mddev->layout >> 17)) {
+ (mddev->new_layout >> 17)) {
printk(KERN_ERR "md/raid10:%s: unsupported raid10 layout: 0x%8x\n",
- mdname(mddev), mddev->layout);
+ mdname(mddev), mddev->new_layout);
goto out;
}
@@ -2241,7 +2241,6 @@
if (!conf->thread)
goto out;
- conf->scale_disks = 0;
conf->mddev = mddev;
return conf;
@@ -2300,11 +2299,6 @@
if (disk_idx >= conf->raid_disks
|| disk_idx < 0)
continue;
- if (conf->scale_disks) {
- disk_idx *= conf->scale_disks;
- rdev->raid_disk = disk_idx;
- /* MOVE 'rd%d' link !! */
- }
disk = conf->mirrors + disk_idx;
disk->rdev = rdev;
@@ -2435,26 +2429,22 @@
return ERR_PTR(-EINVAL);
}
- /* Update slot numbers to obtain
- * degraded raid10 with missing mirrors
- */
- list_for_each_entry(rdev, &mddev->disks, same_set) {
- rdev->raid_disk *= 2;
- }
-
/* Set new parameters */
mddev->new_level = 10;
/* new layout: far_copies = 1, near_copies = 2 */
mddev->new_layout = (1<<8) + 2;
mddev->new_chunk_sectors = mddev->chunk_sectors;
mddev->delta_disks = mddev->raid_disks;
- mddev->degraded = mddev->raid_disks;
mddev->raid_disks *= 2;
/* make sure it will be not marked as dirty */
mddev->recovery_cp = MaxSector;
conf = setup_conf(mddev);
- conf->scale_disks = 2;
+ if (!IS_ERR(conf))
+ list_for_each_entry(rdev, &mddev->disks, same_set)
+ if (rdev->raid_disk >= 0)
+ rdev->new_raid_disk = rdev->raid_disk * 2;
+
return conf;
}
diff --git a/drivers/md/raid10.h b/drivers/md/raid10.h
index 3824a08..2316ac2 100644
--- a/drivers/md/raid10.h
+++ b/drivers/md/raid10.h
@@ -38,11 +38,6 @@
int chunk_shift; /* shift from chunks to sectors */
sector_t chunk_mask;
- int scale_disks; /* When starting array, multiply
- * each ->raid_disk by this.
- * Need for raid0->raid10 migration
- */
-
struct list_head retry_list;
/* queue pending writes and submit them on unplug */
struct bio_list pending_bio_list;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index d2c0f94..96c6902 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -277,12 +277,13 @@
return sh;
}
-static void shrink_buffers(struct stripe_head *sh, int num)
+static void shrink_buffers(struct stripe_head *sh)
{
struct page *p;
int i;
+ int num = sh->raid_conf->pool_size;
- for (i=0; i<num ; i++) {
+ for (i = 0; i < num ; i++) {
p = sh->dev[i].page;
if (!p)
continue;
@@ -291,11 +292,12 @@
}
}
-static int grow_buffers(struct stripe_head *sh, int num)
+static int grow_buffers(struct stripe_head *sh)
{
int i;
+ int num = sh->raid_conf->pool_size;
- for (i=0; i<num; i++) {
+ for (i = 0; i < num; i++) {
struct page *page;
if (!(page = alloc_page(GFP_KERNEL))) {
@@ -364,6 +366,73 @@
return NULL;
}
+/*
+ * Need to check if array has failed when deciding whether to:
+ * - start an array
+ * - remove non-faulty devices
+ * - add a spare
+ * - allow a reshape
+ * This determination is simple when no reshape is happening.
+ * However if there is a reshape, we need to carefully check
+ * both the before and after sections.
+ * This is because some failed devices may only affect one
+ * of the two sections, and some non-in_sync devices may
+ * be insync in the section most affected by failed devices.
+ */
+static int has_failed(raid5_conf_t *conf)
+{
+ int degraded;
+ int i;
+ if (conf->mddev->reshape_position == MaxSector)
+ return conf->mddev->degraded > conf->max_degraded;
+
+ rcu_read_lock();
+ degraded = 0;
+ for (i = 0; i < conf->previous_raid_disks; i++) {
+ mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev);
+ if (!rdev || test_bit(Faulty, &rdev->flags))
+ degraded++;
+ else if (test_bit(In_sync, &rdev->flags))
+ ;
+ else
+ /* not in-sync or faulty.
+ * If the reshape increases the number of devices,
+ * this is being recovered by the reshape, so
+ * this 'previous' section is not in_sync.
+ * If the number of devices is being reduced however,
+ * the device can only be part of the array if
+ * we are reverting a reshape, so this section will
+ * be in-sync.
+ */
+ if (conf->raid_disks >= conf->previous_raid_disks)
+ degraded++;
+ }
+ rcu_read_unlock();
+ if (degraded > conf->max_degraded)
+ return 1;
+ rcu_read_lock();
+ degraded = 0;
+ for (i = 0; i < conf->raid_disks; i++) {
+ mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev);
+ if (!rdev || test_bit(Faulty, &rdev->flags))
+ degraded++;
+ else if (test_bit(In_sync, &rdev->flags))
+ ;
+ else
+ /* not in-sync or faulty.
+ * If reshape increases the number of devices, this
+ * section has already been recovered, else it
+ * almost certainly hasn't.
+ */
+ if (conf->raid_disks <= conf->previous_raid_disks)
+ degraded++;
+ }
+ rcu_read_unlock();
+ if (degraded > conf->max_degraded)
+ return 1;
+ return 0;
+}
+
static void unplug_slaves(mddev_t *mddev);
static void raid5_unplug_device(struct request_queue *q);
@@ -1240,19 +1309,18 @@
static int grow_one_stripe(raid5_conf_t *conf)
{
struct stripe_head *sh;
- int disks = max(conf->raid_disks, conf->previous_raid_disks);
sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL);
if (!sh)
return 0;
- memset(sh, 0, sizeof(*sh) + (disks-1)*sizeof(struct r5dev));
+ memset(sh, 0, sizeof(*sh) + (conf->pool_size-1)*sizeof(struct r5dev));
sh->raid_conf = conf;
spin_lock_init(&sh->lock);
#ifdef CONFIG_MULTICORE_RAID456
init_waitqueue_head(&sh->ops.wait_for_ops);
#endif
- if (grow_buffers(sh, disks)) {
- shrink_buffers(sh, disks);
+ if (grow_buffers(sh)) {
+ shrink_buffers(sh);
kmem_cache_free(conf->slab_cache, sh);
return 0;
}
@@ -1468,7 +1536,7 @@
if (!sh)
return 0;
BUG_ON(atomic_read(&sh->count));
- shrink_buffers(sh, conf->pool_size);
+ shrink_buffers(sh);
kmem_cache_free(conf->slab_cache, sh);
atomic_dec(&conf->active_stripes);
return 1;
@@ -2963,7 +3031,6 @@
mdk_rdev_t *rdev;
dev = &sh->dev[i];
- clear_bit(R5_Insync, &dev->flags);
pr_debug("check %d: state 0x%lx toread %p read %p write %p "
"written %p\n", i, dev->flags, dev->toread, dev->read,
@@ -3000,17 +3067,27 @@
blocked_rdev = rdev;
atomic_inc(&rdev->nr_pending);
}
- if (!rdev || !test_bit(In_sync, &rdev->flags)) {
+ clear_bit(R5_Insync, &dev->flags);
+ if (!rdev)
+ /* Not in-sync */;
+ else if (test_bit(In_sync, &rdev->flags))
+ set_bit(R5_Insync, &dev->flags);
+ else {
+ /* could be in-sync depending on recovery/reshape status */
+ if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset)
+ set_bit(R5_Insync, &dev->flags);
+ }
+ if (!test_bit(R5_Insync, &dev->flags)) {
/* The ReadError flag will just be confusing now */
clear_bit(R5_ReadError, &dev->flags);
clear_bit(R5_ReWrite, &dev->flags);
}
- if (!rdev || !test_bit(In_sync, &rdev->flags)
- || test_bit(R5_ReadError, &dev->flags)) {
+ if (test_bit(R5_ReadError, &dev->flags))
+ clear_bit(R5_Insync, &dev->flags);
+ if (!test_bit(R5_Insync, &dev->flags)) {
s.failed++;
s.failed_num = i;
- } else
- set_bit(R5_Insync, &dev->flags);
+ }
}
rcu_read_unlock();
@@ -3244,7 +3321,6 @@
for (i=disks; i--; ) {
mdk_rdev_t *rdev;
dev = &sh->dev[i];
- clear_bit(R5_Insync, &dev->flags);
pr_debug("check %d: state 0x%lx read %p write %p written %p\n",
i, dev->flags, dev->toread, dev->towrite, dev->written);
@@ -3282,18 +3358,28 @@
blocked_rdev = rdev;
atomic_inc(&rdev->nr_pending);
}
- if (!rdev || !test_bit(In_sync, &rdev->flags)) {
+ clear_bit(R5_Insync, &dev->flags);
+ if (!rdev)
+ /* Not in-sync */;
+ else if (test_bit(In_sync, &rdev->flags))
+ set_bit(R5_Insync, &dev->flags);
+ else {
+ /* in sync if before recovery_offset */
+ if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset)
+ set_bit(R5_Insync, &dev->flags);
+ }
+ if (!test_bit(R5_Insync, &dev->flags)) {
/* The ReadError flag will just be confusing now */
clear_bit(R5_ReadError, &dev->flags);
clear_bit(R5_ReWrite, &dev->flags);
}
- if (!rdev || !test_bit(In_sync, &rdev->flags)
- || test_bit(R5_ReadError, &dev->flags)) {
+ if (test_bit(R5_ReadError, &dev->flags))
+ clear_bit(R5_Insync, &dev->flags);
+ if (!test_bit(R5_Insync, &dev->flags)) {
if (s.failed < 2)
r6s.failed_num[s.failed] = i;
s.failed++;
- } else
- set_bit(R5_Insync, &dev->flags);
+ }
}
rcu_read_unlock();
@@ -4971,8 +5057,10 @@
list_for_each_entry(rdev, &mddev->disks, same_set) {
if (rdev->raid_disk < 0)
continue;
- if (test_bit(In_sync, &rdev->flags))
+ if (test_bit(In_sync, &rdev->flags)) {
working_disks++;
+ continue;
+ }
/* This disc is not fully in-sync. However if it
* just stored parity (beyond the recovery_offset),
* when we don't need to be concerned about the
@@ -5005,7 +5093,7 @@
mddev->degraded = (max(conf->raid_disks, conf->previous_raid_disks)
- working_disks);
- if (mddev->degraded > conf->max_degraded) {
+ if (has_failed(conf)) {
printk(KERN_ERR "md/raid:%s: not enough operational devices"
" (%d/%d failed)\n",
mdname(mddev), mddev->degraded, conf->raid_disks);
@@ -5207,6 +5295,7 @@
for (i = 0; i < conf->raid_disks; i++) {
tmp = conf->disks + i;
if (tmp->rdev
+ && tmp->rdev->recovery_offset == MaxSector
&& !test_bit(Faulty, &tmp->rdev->flags)
&& !test_and_set_bit(In_sync, &tmp->rdev->flags)) {
unsigned long flags;
@@ -5242,7 +5331,7 @@
* isn't possible.
*/
if (!test_bit(Faulty, &rdev->flags) &&
- mddev->degraded <= conf->max_degraded &&
+ !has_failed(conf) &&
number < conf->raid_disks) {
err = -EBUSY;
goto abort;
@@ -5270,7 +5359,7 @@
int first = 0;
int last = conf->raid_disks - 1;
- if (mddev->degraded > conf->max_degraded)
+ if (has_failed(conf))
/* no point adding a device */
return -EINVAL;
@@ -5362,7 +5451,7 @@
if (mddev->bitmap)
/* Cannot grow a bitmap yet */
return -EBUSY;
- if (mddev->degraded > conf->max_degraded)
+ if (has_failed(conf))
return -EINVAL;
if (mddev->delta_disks < 0) {
/* We might be able to shrink, but the devices must
@@ -5437,8 +5526,13 @@
/* Add some new drives, as many as will fit.
* We know there are enough to make the newly sized array work.
+ * Don't add devices if we are reducing the number of
+ * devices in the array. This is because it is not possible
+ * to correctly record the "partially reconstructed" state of
+ * such devices during the reshape and confusion could result.
*/
- list_for_each_entry(rdev, &mddev->disks, same_set)
+ if (mddev->delta_disks >= 0)
+ list_for_each_entry(rdev, &mddev->disks, same_set)
if (rdev->raid_disk < 0 &&
!test_bit(Faulty, &rdev->flags)) {
if (raid5_add_disk(mddev, rdev) == 0) {
@@ -5460,7 +5554,7 @@
}
/* When a reshape changes the number of devices, ->degraded
- * is measured against the large of the pre and post number of
+ * is measured against the larger of the pre and post number of
* devices.*/
if (mddev->delta_disks > 0) {
spin_lock_irqsave(&conf->device_lock, flags);
diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig
index 195c6cf..d22a8ec 100644
--- a/drivers/media/IR/Kconfig
+++ b/drivers/media/IR/Kconfig
@@ -13,6 +13,7 @@
config IR_NEC_DECODER
tristate "Enable IR raw decoder for the NEC protocol"
depends on IR_CORE
+ select BITREVERSE
default y
---help---
@@ -22,6 +23,7 @@
config IR_RC5_DECODER
tristate "Enable IR raw decoder for the RC-5 protocol"
depends on IR_CORE
+ select BITREVERSE
default y
---help---
diff --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c
index 5e20456..4bbd45f 100644
--- a/drivers/media/IR/imon.c
+++ b/drivers/media/IR/imon.c
@@ -94,6 +94,7 @@
bool display_supported; /* not all controllers do */
bool display_isopen; /* display port has been opened */
+ bool rf_device; /* true if iMON 2.4G LT/DT RF device */
bool rf_isassociating; /* RF remote associating */
bool dev_present_intf0; /* USB device presence, interface 0 */
bool dev_present_intf1; /* USB device presence, interface 1 */
@@ -385,7 +386,7 @@
err("%s: display port is already open", __func__);
retval = -EBUSY;
} else {
- ictx->display_isopen = 1;
+ ictx->display_isopen = true;
file->private_data = ictx;
dev_dbg(ictx->dev, "display port opened\n");
}
@@ -422,7 +423,7 @@
err("%s: display is not open", __func__);
retval = -EIO;
} else {
- ictx->display_isopen = 0;
+ ictx->display_isopen = false;
dev_dbg(ictx->dev, "display port closed\n");
if (!ictx->dev_present_intf0) {
/*
@@ -491,12 +492,12 @@
}
init_completion(&ictx->tx.finished);
- ictx->tx.busy = 1;
+ ictx->tx.busy = true;
smp_rmb(); /* ensure later readers know we're busy */
retval = usb_submit_urb(ictx->tx_urb, GFP_KERNEL);
if (retval) {
- ictx->tx.busy = 0;
+ ictx->tx.busy = false;
smp_rmb(); /* ensure later readers know we're not busy */
err("%s: error submitting urb(%d)", __func__, retval);
} else {
@@ -682,7 +683,7 @@
return -ENODEV;
mutex_lock(&ictx->lock);
- ictx->rf_isassociating = 1;
+ ictx->rf_isassociating = true;
send_associate_24g(ictx);
mutex_unlock(&ictx->lock);
@@ -950,7 +951,7 @@
ictx->tx.status = urb->status;
/* notify waiters that write has finished */
- ictx->tx.busy = 0;
+ ictx->tx.busy = false;
smp_rmb(); /* ensure later readers know we're not busy */
complete(&ictx->tx.finished);
}
@@ -1215,7 +1216,7 @@
{
char rel_x = 0x00, rel_y = 0x00;
u8 right_shift = 1;
- bool mouse_input = 1;
+ bool mouse_input = true;
int dir = 0;
/* newer iMON device PAD or mouse button */
@@ -1246,7 +1247,7 @@
} else if (ictx->kc == KEY_CHANNELDOWN && (buf[2] & 0x40) != 0x40) {
dir = -1;
} else
- mouse_input = 0;
+ mouse_input = false;
if (mouse_input) {
dev_dbg(ictx->dev, "sending mouse data via input subsystem\n");
@@ -1450,7 +1451,7 @@
unsigned char *buf = urb->transfer_buffer;
struct device *dev = ictx->dev;
u32 kc;
- bool norelease = 0;
+ bool norelease = false;
int i;
u64 temp_key;
u64 panel_key = 0;
@@ -1465,7 +1466,7 @@
idev = ictx->idev;
/* filter out junk data on the older 0xffdc imon devices */
- if ((buf[0] == 0xff) && (buf[7] == 0xff))
+ if ((buf[0] == 0xff) && (buf[1] == 0xff) && (buf[2] == 0xff))
return;
/* Figure out what key was pressed */
@@ -1517,7 +1518,7 @@
!(buf[1] & 0x1 || buf[1] >> 2 & 0x1))) {
len = 8;
imon_pad_to_keys(ictx, buf);
- norelease = 1;
+ norelease = true;
}
if (debug) {
@@ -1580,7 +1581,7 @@
(buf[6] == 0x5E && buf[7] == 0xDF))) { /* DT */
dev_warn(dev, "%s: remote associated refid=%02X\n",
__func__, buf[1]);
- ictx->rf_isassociating = 0;
+ ictx->rf_isassociating = false;
}
}
@@ -1790,9 +1791,9 @@
int ifnum = iface_desc->desc.bInterfaceNumber;
int num_endpts = iface_desc->desc.bNumEndpoints;
int i, ep_dir, ep_type;
- bool ir_ep_found = 0;
- bool display_ep_found = 0;
- bool tx_control = 0;
+ bool ir_ep_found = false;
+ bool display_ep_found = false;
+ bool tx_control = false;
/*
* Scan the endpoint list and set:
@@ -1808,13 +1809,13 @@
ep_type == USB_ENDPOINT_XFER_INT) {
rx_endpoint = ep;
- ir_ep_found = 1;
+ ir_ep_found = true;
dev_dbg(ictx->dev, "%s: found IR endpoint\n", __func__);
} else if (!display_ep_found && ep_dir == USB_DIR_OUT &&
ep_type == USB_ENDPOINT_XFER_INT) {
tx_endpoint = ep;
- display_ep_found = 1;
+ display_ep_found = true;
dev_dbg(ictx->dev, "%s: found display endpoint\n", __func__);
}
}
@@ -1835,8 +1836,8 @@
* newer iMON devices that use control urb instead of interrupt
*/
if (!display_ep_found) {
- tx_control = 1;
- display_ep_found = 1;
+ tx_control = true;
+ display_ep_found = true;
dev_dbg(ictx->dev, "%s: device uses control endpoint, not "
"interface OUT endpoint\n", __func__);
}
@@ -1847,7 +1848,7 @@
* and without... :\
*/
if (ictx->display_type == IMON_DISPLAY_TYPE_NONE) {
- display_ep_found = 0;
+ display_ep_found = false;
dev_dbg(ictx->dev, "%s: device has no display\n", __func__);
}
@@ -1856,7 +1857,7 @@
* that refers to e.g. /dev/lcd0 (a character device LCD or VFD).
*/
if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) {
- display_ep_found = 0;
+ display_ep_found = false;
dev_dbg(ictx->dev, "%s: iMON Touch device found\n", __func__);
}
@@ -1905,9 +1906,10 @@
ictx->dev = dev;
ictx->usbdev_intf0 = usb_get_dev(interface_to_usbdev(intf));
- ictx->dev_present_intf0 = 1;
+ ictx->dev_present_intf0 = true;
ictx->rx_urb_intf0 = rx_urb;
ictx->tx_urb = tx_urb;
+ ictx->rf_device = false;
ictx->vendor = le16_to_cpu(ictx->usbdev_intf0->descriptor.idVendor);
ictx->product = le16_to_cpu(ictx->usbdev_intf0->descriptor.idProduct);
@@ -1979,7 +1981,7 @@
}
ictx->usbdev_intf1 = usb_get_dev(interface_to_usbdev(intf));
- ictx->dev_present_intf1 = 1;
+ ictx->dev_present_intf1 = true;
ictx->rx_urb_intf1 = rx_urb;
ret = -ENODEV;
@@ -2047,6 +2049,12 @@
dev_info(ictx->dev, "0xffdc iMON Knob, iMON IR");
ictx->display_supported = false;
break;
+ /* iMON 2.4G LT (usb stick), no display, iMON RF */
+ case 0x4e:
+ dev_info(ictx->dev, "0xffdc iMON 2.4G LT, iMON RF");
+ ictx->display_supported = false;
+ ictx->rf_device = true;
+ break;
/* iMON VFD, no IR (does have vol knob tho) */
case 0x35:
dev_info(ictx->dev, "0xffdc iMON VFD + knob, no IR");
@@ -2197,15 +2205,6 @@
goto fail;
}
- if (product == 0xffdc) {
- /* RF products *also* use 0xffdc... sigh... */
- sysfs_err = sysfs_create_group(&interface->dev.kobj,
- &imon_rf_attribute_group);
- if (sysfs_err)
- err("%s: Could not create RF sysfs entries(%d)",
- __func__, sysfs_err);
- }
-
} else {
/* this is the secondary interface on the device */
ictx = imon_init_intf1(interface, first_if_ctx);
@@ -2233,6 +2232,14 @@
imon_set_display_type(ictx, interface);
+ if (product == 0xffdc && ictx->rf_device) {
+ sysfs_err = sysfs_create_group(&interface->dev.kobj,
+ &imon_rf_attribute_group);
+ if (sysfs_err)
+ err("%s: Could not create RF sysfs entries(%d)",
+ __func__, sysfs_err);
+ }
+
if (ictx->display_supported)
imon_init_display(ictx, interface);
}
@@ -2297,7 +2304,7 @@
}
if (ifnum == 0) {
- ictx->dev_present_intf0 = 0;
+ ictx->dev_present_intf0 = false;
usb_kill_urb(ictx->rx_urb_intf0);
input_unregister_device(ictx->idev);
if (ictx->display_supported) {
@@ -2307,7 +2314,7 @@
usb_deregister_dev(interface, &imon_vfd_class);
}
} else {
- ictx->dev_present_intf1 = 0;
+ ictx->dev_present_intf1 = false;
usb_kill_urb(ictx->rx_urb_intf1);
if (ictx->display_type == IMON_DISPLAY_TYPE_VGA)
input_unregister_device(ictx->touch);
diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c
index 9374a00..94a8577 100644
--- a/drivers/media/IR/ir-keytable.c
+++ b/drivers/media/IR/ir-keytable.c
@@ -490,11 +490,12 @@
if (rc < 0)
goto out_table;
- if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) {
- rc = ir_raw_event_register(input_dev);
- if (rc < 0)
- goto out_event;
- }
+ if (ir_dev->props)
+ if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) {
+ rc = ir_raw_event_register(input_dev);
+ if (rc < 0)
+ goto out_event;
+ }
IR_dprintk(1, "Registered input device on %s for %s remote.\n",
driver_name, rc_tab->name);
@@ -530,8 +531,10 @@
IR_dprintk(1, "Freed keycode table\n");
del_timer_sync(&ir_dev->timer_keyup);
- if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW)
- ir_raw_event_unregister(input_dev);
+ if (ir_dev->props)
+ if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW)
+ ir_raw_event_unregister(input_dev);
+
rc_tab = &ir_dev->rc_tab;
rc_tab->size = 0;
kfree(rc_tab->scan);
diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c
index d7da63e..2098dd1 100644
--- a/drivers/media/IR/ir-sysfs.c
+++ b/drivers/media/IR/ir-sysfs.c
@@ -221,9 +221,10 @@
if (unlikely(devno < 0))
return devno;
- if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
- ir_dev->dev.type = &rc_dev_type;
- else
+ if (ir_dev->props) {
+ if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
+ ir_dev->dev.type = &rc_dev_type;
+ } else
ir_dev->dev.type = &ir_raw_dev_type;
ir_dev->dev.class = &ir_input_class;
diff --git a/drivers/media/IR/keymaps/Makefile b/drivers/media/IR/keymaps/Makefile
index ec25258..aea649f 100644
--- a/drivers/media/IR/keymaps/Makefile
+++ b/drivers/media/IR/keymaps/Makefile
@@ -6,7 +6,8 @@
rc-avermedia.o \
rc-avermedia-cardbus.o \
rc-avermedia-dvbt.o \
- rc-avermedia-m135a-rm-jx.o \
+ rc-avermedia-m135a.o \
+ rc-avermedia-m733a-rm-k6.o \
rc-avertv-303.o \
rc-behold.o \
rc-behold-columbus.o \
diff --git a/drivers/media/IR/keymaps/rc-avermedia-m135a-rm-jx.c b/drivers/media/IR/keymaps/rc-avermedia-m135a-rm-jx.c
deleted file mode 100644
index 101e7ea..0000000
--- a/drivers/media/IR/keymaps/rc-avermedia-m135a-rm-jx.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/* avermedia-m135a-rm-jx.h - Keytable for avermedia_m135a_rm_jx Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
- *
- * 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 <media/rc-map.h>
-
-/*
- * Avermedia M135A with IR model RM-JX
- * The same codes exist on both Positivo (BR) and original IR
- * Mauro Carvalho Chehab <mchehab@infradead.org>
- */
-
-static struct ir_scancode avermedia_m135a_rm_jx[] = {
- { 0x0200, KEY_POWER2 },
- { 0x022e, KEY_DOT }, /* '.' */
- { 0x0201, KEY_MODE }, /* TV/FM or SOURCE */
-
- { 0x0205, KEY_1 },
- { 0x0206, KEY_2 },
- { 0x0207, KEY_3 },
- { 0x0209, KEY_4 },
- { 0x020a, KEY_5 },
- { 0x020b, KEY_6 },
- { 0x020d, KEY_7 },
- { 0x020e, KEY_8 },
- { 0x020f, KEY_9 },
- { 0x0211, KEY_0 },
-
- { 0x0213, KEY_RIGHT }, /* -> or L */
- { 0x0212, KEY_LEFT }, /* <- or R */
-
- { 0x0217, KEY_SLEEP }, /* Capturar Imagem or Snapshot */
- { 0x0210, KEY_SHUFFLE }, /* Amostra or 16 chan prev */
-
- { 0x0303, KEY_CHANNELUP },
- { 0x0302, KEY_CHANNELDOWN },
- { 0x021f, KEY_VOLUMEUP },
- { 0x021e, KEY_VOLUMEDOWN },
- { 0x020c, KEY_ENTER }, /* Full Screen */
-
- { 0x0214, KEY_MUTE },
- { 0x0208, KEY_AUDIO },
-
- { 0x0203, KEY_TEXT }, /* Teletext */
- { 0x0204, KEY_EPG },
- { 0x022b, KEY_TV2 }, /* TV2 or PIP */
-
- { 0x021d, KEY_RED },
- { 0x021c, KEY_YELLOW },
- { 0x0301, KEY_GREEN },
- { 0x0300, KEY_BLUE },
-
- { 0x021a, KEY_PLAYPAUSE },
- { 0x0219, KEY_RECORD },
- { 0x0218, KEY_PLAY },
- { 0x021b, KEY_STOP },
-};
-
-static struct rc_keymap avermedia_m135a_rm_jx_map = {
- .map = {
- .scan = avermedia_m135a_rm_jx,
- .size = ARRAY_SIZE(avermedia_m135a_rm_jx),
- .ir_type = IR_TYPE_NEC,
- .name = RC_MAP_AVERMEDIA_M135A_RM_JX,
- }
-};
-
-static int __init init_rc_map_avermedia_m135a_rm_jx(void)
-{
- return ir_register_map(&avermedia_m135a_rm_jx_map);
-}
-
-static void __exit exit_rc_map_avermedia_m135a_rm_jx(void)
-{
- ir_unregister_map(&avermedia_m135a_rm_jx_map);
-}
-
-module_init(init_rc_map_avermedia_m135a_rm_jx)
-module_exit(exit_rc_map_avermedia_m135a_rm_jx)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/IR/keymaps/rc-avermedia-m135a.c b/drivers/media/IR/keymaps/rc-avermedia-m135a.c
new file mode 100644
index 0000000..e4471fb
--- /dev/null
+++ b/drivers/media/IR/keymaps/rc-avermedia-m135a.c
@@ -0,0 +1,147 @@
+/* avermedia-m135a.c - Keytable for Avermedia M135A Remote Controllers
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
+ * Copyright (c) 2010 by Herton Ronaldo Krzesinski <herton@mandriva.com.br>
+ *
+ * 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 <media/rc-map.h>
+
+/*
+ * Avermedia M135A with RM-JX and RM-K6 remote controls
+ *
+ * On Avermedia M135A with IR model RM-JX, the same codes exist on both
+ * Positivo (BR) and original IR, initial version and remote control codes
+ * added by Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ * Positivo also ships Avermedia M135A with model RM-K6, extra control
+ * codes added by Herton Ronaldo Krzesinski <herton@mandriva.com.br>
+ */
+
+static struct ir_scancode avermedia_m135a[] = {
+ /* RM-JX */
+ { 0x0200, KEY_POWER2 },
+ { 0x022e, KEY_DOT }, /* '.' */
+ { 0x0201, KEY_MODE }, /* TV/FM or SOURCE */
+
+ { 0x0205, KEY_1 },
+ { 0x0206, KEY_2 },
+ { 0x0207, KEY_3 },
+ { 0x0209, KEY_4 },
+ { 0x020a, KEY_5 },
+ { 0x020b, KEY_6 },
+ { 0x020d, KEY_7 },
+ { 0x020e, KEY_8 },
+ { 0x020f, KEY_9 },
+ { 0x0211, KEY_0 },
+
+ { 0x0213, KEY_RIGHT }, /* -> or L */
+ { 0x0212, KEY_LEFT }, /* <- or R */
+
+ { 0x0217, KEY_SLEEP }, /* Capturar Imagem or Snapshot */
+ { 0x0210, KEY_SHUFFLE }, /* Amostra or 16 chan prev */
+
+ { 0x0303, KEY_CHANNELUP },
+ { 0x0302, KEY_CHANNELDOWN },
+ { 0x021f, KEY_VOLUMEUP },
+ { 0x021e, KEY_VOLUMEDOWN },
+ { 0x020c, KEY_ENTER }, /* Full Screen */
+
+ { 0x0214, KEY_MUTE },
+ { 0x0208, KEY_AUDIO },
+
+ { 0x0203, KEY_TEXT }, /* Teletext */
+ { 0x0204, KEY_EPG },
+ { 0x022b, KEY_TV2 }, /* TV2 or PIP */
+
+ { 0x021d, KEY_RED },
+ { 0x021c, KEY_YELLOW },
+ { 0x0301, KEY_GREEN },
+ { 0x0300, KEY_BLUE },
+
+ { 0x021a, KEY_PLAYPAUSE },
+ { 0x0219, KEY_RECORD },
+ { 0x0218, KEY_PLAY },
+ { 0x021b, KEY_STOP },
+
+ /* RM-K6 */
+ { 0x0401, KEY_POWER2 },
+ { 0x0406, KEY_MUTE },
+ { 0x0408, KEY_MODE }, /* TV/FM */
+
+ { 0x0409, KEY_1 },
+ { 0x040a, KEY_2 },
+ { 0x040b, KEY_3 },
+ { 0x040c, KEY_4 },
+ { 0x040d, KEY_5 },
+ { 0x040e, KEY_6 },
+ { 0x040f, KEY_7 },
+ { 0x0410, KEY_8 },
+ { 0x0411, KEY_9 },
+ { 0x044c, KEY_DOT }, /* '.' */
+ { 0x0412, KEY_0 },
+ { 0x0407, KEY_REFRESH }, /* Refresh/Reload */
+
+ { 0x0413, KEY_AUDIO },
+ { 0x0440, KEY_SCREEN }, /* Full Screen toggle */
+ { 0x0441, KEY_HOME },
+ { 0x0442, KEY_BACK },
+ { 0x0447, KEY_UP },
+ { 0x0448, KEY_DOWN },
+ { 0x0449, KEY_LEFT },
+ { 0x044a, KEY_RIGHT },
+ { 0x044b, KEY_OK },
+ { 0x0404, KEY_VOLUMEUP },
+ { 0x0405, KEY_VOLUMEDOWN },
+ { 0x0402, KEY_CHANNELUP },
+ { 0x0403, KEY_CHANNELDOWN },
+
+ { 0x0443, KEY_RED },
+ { 0x0444, KEY_GREEN },
+ { 0x0445, KEY_YELLOW },
+ { 0x0446, KEY_BLUE },
+
+ { 0x0414, KEY_TEXT },
+ { 0x0415, KEY_EPG },
+ { 0x041a, KEY_TV2 }, /* PIP */
+ { 0x041b, KEY_MHP }, /* Snapshot */
+
+ { 0x0417, KEY_RECORD },
+ { 0x0416, KEY_PLAYPAUSE },
+ { 0x0418, KEY_STOP },
+ { 0x0419, KEY_PAUSE },
+
+ { 0x041f, KEY_PREVIOUS },
+ { 0x041c, KEY_REWIND },
+ { 0x041d, KEY_FORWARD },
+ { 0x041e, KEY_NEXT },
+};
+
+static struct rc_keymap avermedia_m135a_map = {
+ .map = {
+ .scan = avermedia_m135a,
+ .size = ARRAY_SIZE(avermedia_m135a),
+ .ir_type = IR_TYPE_NEC,
+ .name = RC_MAP_AVERMEDIA_M135A,
+ }
+};
+
+static int __init init_rc_map_avermedia_m135a(void)
+{
+ return ir_register_map(&avermedia_m135a_map);
+}
+
+static void __exit exit_rc_map_avermedia_m135a(void)
+{
+ ir_unregister_map(&avermedia_m135a_map);
+}
+
+module_init(init_rc_map_avermedia_m135a)
+module_exit(exit_rc_map_avermedia_m135a)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/IR/keymaps/rc-avermedia-m733a-rm-k6.c b/drivers/media/IR/keymaps/rc-avermedia-m733a-rm-k6.c
new file mode 100644
index 0000000..cf8d457
--- /dev/null
+++ b/drivers/media/IR/keymaps/rc-avermedia-m733a-rm-k6.c
@@ -0,0 +1,95 @@
+/* avermedia-m733a-rm-k6.h - Keytable for avermedia_m733a_rm_k6 Remote Controller
+ *
+ * Copyright (c) 2010 by Herton Ronaldo Krzesinski <herton@mandriva.com.br>
+ *
+ * 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 <media/rc-map.h>
+
+/*
+ * Avermedia M733A with IR model RM-K6
+ * This is the stock remote controller used with Positivo machines with M733A
+ * Herton Ronaldo Krzesinski <herton@mandriva.com.br>
+ */
+
+static struct ir_scancode avermedia_m733a_rm_k6[] = {
+ { 0x0401, KEY_POWER2 },
+ { 0x0406, KEY_MUTE },
+ { 0x0408, KEY_MODE }, /* TV/FM */
+
+ { 0x0409, KEY_1 },
+ { 0x040a, KEY_2 },
+ { 0x040b, KEY_3 },
+ { 0x040c, KEY_4 },
+ { 0x040d, KEY_5 },
+ { 0x040e, KEY_6 },
+ { 0x040f, KEY_7 },
+ { 0x0410, KEY_8 },
+ { 0x0411, KEY_9 },
+ { 0x044c, KEY_DOT }, /* '.' */
+ { 0x0412, KEY_0 },
+ { 0x0407, KEY_REFRESH }, /* Refresh/Reload */
+
+ { 0x0413, KEY_AUDIO },
+ { 0x0440, KEY_SCREEN }, /* Full Screen toggle */
+ { 0x0441, KEY_HOME },
+ { 0x0442, KEY_BACK },
+ { 0x0447, KEY_UP },
+ { 0x0448, KEY_DOWN },
+ { 0x0449, KEY_LEFT },
+ { 0x044a, KEY_RIGHT },
+ { 0x044b, KEY_OK },
+ { 0x0404, KEY_VOLUMEUP },
+ { 0x0405, KEY_VOLUMEDOWN },
+ { 0x0402, KEY_CHANNELUP },
+ { 0x0403, KEY_CHANNELDOWN },
+
+ { 0x0443, KEY_RED },
+ { 0x0444, KEY_GREEN },
+ { 0x0445, KEY_YELLOW },
+ { 0x0446, KEY_BLUE },
+
+ { 0x0414, KEY_TEXT },
+ { 0x0415, KEY_EPG },
+ { 0x041a, KEY_TV2 }, /* PIP */
+ { 0x041b, KEY_MHP }, /* Snapshot */
+
+ { 0x0417, KEY_RECORD },
+ { 0x0416, KEY_PLAYPAUSE },
+ { 0x0418, KEY_STOP },
+ { 0x0419, KEY_PAUSE },
+
+ { 0x041f, KEY_PREVIOUS },
+ { 0x041c, KEY_REWIND },
+ { 0x041d, KEY_FORWARD },
+ { 0x041e, KEY_NEXT },
+};
+
+static struct rc_keymap avermedia_m733a_rm_k6_map = {
+ .map = {
+ .scan = avermedia_m733a_rm_k6,
+ .size = ARRAY_SIZE(avermedia_m733a_rm_k6),
+ .ir_type = IR_TYPE_NEC,
+ .name = RC_MAP_AVERMEDIA_M733A_RM_K6,
+ }
+};
+
+static int __init init_rc_map_avermedia_m733a_rm_k6(void)
+{
+ return ir_register_map(&avermedia_m733a_rm_k6_map);
+}
+
+static void __exit exit_rc_map_avermedia_m733a_rm_k6(void)
+{
+ ir_unregister_map(&avermedia_m733a_rm_k6_map);
+}
+
+module_init(init_rc_map_avermedia_m733a_rm_k6)
+module_exit(exit_rc_map_avermedia_m733a_rm_k6)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c
index b762e56..bca07c0 100644
--- a/drivers/media/dvb/dm1105/dm1105.c
+++ b/drivers/media/dvb/dm1105/dm1105.c
@@ -594,7 +594,7 @@
int __devinit dm1105_ir_init(struct dm1105_dev *dm1105)
{
struct input_dev *input_dev;
- char *ir_codes = NULL;
+ char *ir_codes = RC_MAP_DM1105_NEC;
int err = -ENOMEM;
input_dev = input_allocate_device();
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index f6dac2b..6c3a8a0 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -351,6 +351,7 @@
const u8 *ts, *ts_end, *from_where = NULL;
u8 ts_remain = 0, how_much = 0, new_ts = 1;
struct ethhdr *ethh = NULL;
+ bool error = false;
#ifdef ULE_DEBUG
/* The code inside ULE_DEBUG keeps a history of the last 100 TS cells processed. */
@@ -460,10 +461,16 @@
/* Drop partly decoded SNDU, reset state, resync on PUSI. */
if (priv->ule_skb) {
- dev_kfree_skb( priv->ule_skb );
+ error = true;
+ dev_kfree_skb(priv->ule_skb);
+ }
+
+ if (error || priv->ule_sndu_remain) {
dev->stats.rx_errors++;
dev->stats.rx_frame_errors++;
+ error = false;
}
+
reset_ule(priv);
priv->need_pusi = 1;
continue;
@@ -535,6 +542,7 @@
from_where += 2;
}
+ priv->ule_sndu_remain = priv->ule_sndu_len + 2;
/*
* State of current TS:
* ts_remain (remaining bytes in the current TS cell)
@@ -544,6 +552,7 @@
*/
switch (ts_remain) {
case 1:
+ priv->ule_sndu_remain--;
priv->ule_sndu_type = from_where[0] << 8;
priv->ule_sndu_type_1 = 1; /* first byte of ule_type is set. */
ts_remain -= 1; from_where += 1;
@@ -557,6 +566,7 @@
default: /* complete ULE header is present in current TS. */
/* Extract ULE type field. */
if (priv->ule_sndu_type_1) {
+ priv->ule_sndu_type_1 = 0;
priv->ule_sndu_type |= from_where[0];
from_where += 1; /* points to payload start. */
ts_remain -= 1;
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index e5f91f1..553b48a 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -76,6 +76,7 @@
select DVB_S5H1411 if !DVB_FE_CUSTOMISE
select DVB_LGDT3305 if !DVB_FE_CUSTOMISE
select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE
+ select DVB_TUNER_DIB0090 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
@@ -134,6 +135,7 @@
select DVB_TDA1004X if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE
+ select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
help
Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver.
Currently, only devices with a product id of
@@ -264,7 +266,7 @@
select DVB_STB6000 if !DVB_FE_CUSTOMISE
select DVB_CX24116 if !DVB_FE_CUSTOMISE
select DVB_SI21XX if !DVB_FE_CUSTOMISE
- select DVB_TDA10021 if !DVB_FE_CUSTOMISE
+ select DVB_TDA10023 if !DVB_FE_CUSTOMISE
select DVB_MT312 if !DVB_FE_CUSTOMISE
select DVB_ZL10039 if !DVB_FE_CUSTOMISE
select DVB_DS3000 if !DVB_FE_CUSTOMISE
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index 0eb4908..11e9e85 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -1026,8 +1026,10 @@
cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
- &cxusb_dualdig4_rev2_config) < 0)
+ &cxusb_dualdig4_rev2_config) < 0) {
+ printk(KERN_WARNING "Unable to enumerate dib7000p\n");
return -ENODEV;
+ }
adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
&cxusb_dualdig4_rev2_config);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 085c4e4..b4afe6f 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -198,6 +198,7 @@
#define USB_PID_AVERMEDIA_A850 0x850a
#define USB_PID_AVERMEDIA_A805 0xa805
#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006
+#define USB_PID_TECHNOTREND_CONNECT_CT3650 0x300d
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081
#define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058
diff --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/dvb/dvb-usb/ttusb2.c
index 20ca9d9..a6de489 100644
--- a/drivers/media/dvb/dvb-usb/ttusb2.c
+++ b/drivers/media/dvb/dvb-usb/ttusb2.c
@@ -29,6 +29,8 @@
#include "tda826x.h"
#include "tda10086.h"
+#include "tda1002x.h"
+#include "tda827x.h"
#include "lnbp21.h"
/* debug */
@@ -150,7 +152,17 @@
.xtal_freq = TDA10086_XTAL_16M,
};
-static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap)
+static struct tda10023_config tda10023_config = {
+ .demod_address = 0x0c,
+ .invert = 0,
+ .xtal = 16000000,
+ .pll_m = 11,
+ .pll_p = 3,
+ .pll_n = 1,
+ .deltaf = 0xa511,
+};
+
+static int ttusb2_frontend_tda10086_attach(struct dvb_usb_adapter *adap)
{
if (usb_set_interface(adap->dev->udev,0,3) < 0)
err("set interface to alts=3 failed");
@@ -163,7 +175,27 @@
return 0;
}
-static int ttusb2_tuner_attach(struct dvb_usb_adapter *adap)
+static int ttusb2_frontend_tda10023_attach(struct dvb_usb_adapter *adap)
+{
+ if (usb_set_interface(adap->dev->udev, 0, 3) < 0)
+ err("set interface to alts=3 failed");
+ if ((adap->fe = dvb_attach(tda10023_attach, &tda10023_config, &adap->dev->i2c_adap, 0x48)) == NULL) {
+ deb_info("TDA10023 attach failed\n");
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static int ttusb2_tuner_tda827x_attach(struct dvb_usb_adapter *adap)
+{
+ if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL) {
+ printk(KERN_ERR "%s: No tda827x found!\n", __func__);
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static int ttusb2_tuner_tda826x_attach(struct dvb_usb_adapter *adap)
{
if (dvb_attach(tda826x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) {
deb_info("TDA8263 attach failed\n");
@@ -180,6 +212,7 @@
/* DVB USB Driver stuff */
static struct dvb_usb_device_properties ttusb2_properties;
static struct dvb_usb_device_properties ttusb2_properties_s2400;
+static struct dvb_usb_device_properties ttusb2_properties_ct3650;
static int ttusb2_probe(struct usb_interface *intf,
const struct usb_device_id *id)
@@ -187,6 +220,8 @@
if (0 == dvb_usb_device_init(intf, &ttusb2_properties,
THIS_MODULE, NULL, adapter_nr) ||
0 == dvb_usb_device_init(intf, &ttusb2_properties_s2400,
+ THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf, &ttusb2_properties_ct3650,
THIS_MODULE, NULL, adapter_nr))
return 0;
return -ENODEV;
@@ -197,6 +232,8 @@
{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_450E) },
{ USB_DEVICE(USB_VID_TECHNOTREND,
USB_PID_TECHNOTREND_CONNECT_S2400) },
+ { USB_DEVICE(USB_VID_TECHNOTREND,
+ USB_PID_TECHNOTREND_CONNECT_CT3650) },
{} /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, ttusb2_table);
@@ -214,8 +251,8 @@
{
.streaming_ctrl = NULL, // ttusb2_streaming_ctrl,
- .frontend_attach = ttusb2_frontend_attach,
- .tuner_attach = ttusb2_tuner_attach,
+ .frontend_attach = ttusb2_frontend_tda10086_attach,
+ .tuner_attach = ttusb2_tuner_tda826x_attach,
/* parameter for the MPEG2-data transfer */
.stream = {
@@ -266,8 +303,8 @@
{
.streaming_ctrl = NULL,
- .frontend_attach = ttusb2_frontend_attach,
- .tuner_attach = ttusb2_tuner_attach,
+ .frontend_attach = ttusb2_frontend_tda10086_attach,
+ .tuner_attach = ttusb2_tuner_tda826x_attach,
/* parameter for the MPEG2-data transfer */
.stream = {
@@ -301,6 +338,52 @@
}
};
+static struct dvb_usb_device_properties ttusb2_properties_ct3650 = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = CYPRESS_FX2,
+
+ .size_of_priv = sizeof(struct ttusb2_state),
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .streaming_ctrl = NULL,
+
+ .frontend_attach = ttusb2_frontend_tda10023_attach,
+ .tuner_attach = ttusb2_tuner_tda827x_attach,
+
+ /* parameter for the MPEG2-data transfer */
+ .stream = {
+ .type = USB_ISOC,
+ .count = 5,
+ .endpoint = 0x02,
+ .u = {
+ .isoc = {
+ .framesperurb = 4,
+ .framesize = 940,
+ .interval = 1,
+ }
+ }
+ }
+ },
+ },
+
+ .power_ctrl = ttusb2_power_ctrl,
+ .identify_state = ttusb2_identify_state,
+
+ .i2c_algo = &ttusb2_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+
+ .num_device_descs = 1,
+ .devices = {
+ { "Technotrend TT-connect CT-3650",
+ .warm_ids = { &ttusb2_table[3], NULL },
+ },
+ }
+};
+
static struct usb_driver ttusb2_driver = {
.name = "dvb_usb_ttusb2",
.probe = ttusb2_probe,
diff --git a/drivers/media/dvb/firewire/firedtv-1394.c b/drivers/media/dvb/firewire/firedtv-1394.c
index 26333b4..b34ca7a 100644
--- a/drivers/media/dvb/firewire/firedtv-1394.c
+++ b/drivers/media/dvb/firewire/firedtv-1394.c
@@ -58,7 +58,7 @@
num = hpsb_iso_n_ready(iso);
if (!fdtv) {
- dev_err(fdtv->device, "received at unknown iso channel\n");
+ pr_err("received at unknown iso channel\n");
goto out;
}
diff --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb/frontends/au8522_decoder.c
index 68dba3a..29cdbfe 100644
--- a/drivers/media/dvb/frontends/au8522_decoder.c
+++ b/drivers/media/dvb/frontends/au8522_decoder.c
@@ -567,30 +567,6 @@
/* ----------------------------------------------------------------------- */
-static int au8522_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
-{
- switch (fmt->type) {
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static int au8522_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
-{
- switch (fmt->type) {
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- /* Not yet implemented */
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int au8522_g_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg)
@@ -772,8 +748,6 @@
static const struct v4l2_subdev_video_ops au8522_video_ops = {
.s_routing = au8522_s_video_routing,
- .g_fmt = au8522_g_fmt,
- .s_fmt = au8522_s_fmt,
.s_stream = au8522_s_stream,
};
diff --git a/drivers/media/dvb/frontends/ds3000.c b/drivers/media/dvb/frontends/ds3000.c
index 78001e8..fc61d92 100644
--- a/drivers/media/dvb/frontends/ds3000.c
+++ b/drivers/media/dvb/frontends/ds3000.c
@@ -969,15 +969,12 @@
dprintk("%s\n", __func__);
/* allocate memory for the internal state */
- state = kmalloc(sizeof(struct ds3000_state), GFP_KERNEL);
+ state = kzalloc(sizeof(struct ds3000_state), GFP_KERNEL);
if (state == NULL) {
printk(KERN_ERR "Unable to kmalloc\n");
goto error2;
}
- /* setup the state */
- memset(state, 0, sizeof(struct ds3000_state));
-
state->config = config;
state->i2c = i2c;
state->prevUCBS2 = 0;
diff --git a/drivers/media/dvb/frontends/stv6110x.c b/drivers/media/dvb/frontends/stv6110x.c
index 42591ce..f36cab1 100644
--- a/drivers/media/dvb/frontends/stv6110x.c
+++ b/drivers/media/dvb/frontends/stv6110x.c
@@ -303,7 +303,10 @@
static int stv6110x_sleep(struct dvb_frontend *fe)
{
- return stv6110x_set_mode(fe, TUNER_SLEEP);
+ if (fe->tuner_priv)
+ return stv6110x_set_mode(fe, TUNER_SLEEP);
+
+ return 0;
}
static int stv6110x_get_status(struct dvb_frontend *fe, u32 *status)
diff --git a/drivers/media/dvb/ngene/ngene-cards.c b/drivers/media/dvb/ngene/ngene-cards.c
index 692c3e2..4692a41 100644
--- a/drivers/media/dvb/ngene/ngene-cards.c
+++ b/drivers/media/dvb/ngene/ngene-cards.c
@@ -217,6 +217,19 @@
.fw_version = 15,
};
+static struct ngene_info ngene_info_duoFlexS2 = {
+ .type = NGENE_SIDEWINDER,
+ .name = "Digital Devices DuoFlex S2 miniPCIe",
+ .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN},
+ .demod_attach = {demod_attach_stv0900, demod_attach_stv0900},
+ .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110},
+ .fe_config = {&fe_cineS2, &fe_cineS2},
+ .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1},
+ .lnb = {0x0a, 0x08},
+ .tsf = {3, 3},
+ .fw_version = 15,
+};
+
static struct ngene_info ngene_info_m780 = {
.type = NGENE_APP,
.name = "Aver M780 ATSC/QAM-B",
@@ -256,6 +269,8 @@
NGENE_ID(0x18c3, 0xdb01, ngene_info_satixS2),
NGENE_ID(0x18c3, 0xdb02, ngene_info_satixS2v2),
NGENE_ID(0x18c3, 0xdd00, ngene_info_cineS2v5),
+ NGENE_ID(0x18c3, 0xdd10, ngene_info_duoFlexS2),
+ NGENE_ID(0x18c3, 0xdd20, ngene_info_duoFlexS2),
NGENE_ID(0x1461, 0x062e, ngene_info_m780),
{0}
};
diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c
index c8b4dfa..4caeb16 100644
--- a/drivers/media/dvb/ngene/ngene-core.c
+++ b/drivers/media/dvb/ngene/ngene-core.c
@@ -53,8 +53,6 @@
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-#define COMMAND_TIMEOUT_WORKAROUND
-
#define dprintk if (debug) printk
#define ngwriteb(dat, adr) writeb((dat), (char *)(dev->iomem + (adr)))
@@ -147,24 +145,24 @@
} else {
if (chan->HWState == HWSTATE_RUN) {
u32 Flags = 0;
+ IBufferExchange *exch1 = chan->pBufferExchange;
+ IBufferExchange *exch2 = chan->pBufferExchange2;
if (Cur->ngeneBuffer.SR.Flags & 0x01)
Flags |= BEF_EVEN_FIELD;
if (Cur->ngeneBuffer.SR.Flags & 0x20)
Flags |= BEF_OVERFLOW;
- if (chan->pBufferExchange)
- chan->pBufferExchange(chan,
- Cur->Buffer1,
- chan->
- Capture1Length,
- Cur->ngeneBuffer.
- SR.Clock, Flags);
- if (chan->pBufferExchange2)
- chan->pBufferExchange2(chan,
- Cur->Buffer2,
- chan->
- Capture2Length,
- Cur->ngeneBuffer.
- SR.Clock, Flags);
+ spin_unlock_irq(&chan->state_lock);
+ if (exch1)
+ exch1(chan, Cur->Buffer1,
+ chan->Capture1Length,
+ Cur->ngeneBuffer.SR.Clock,
+ Flags);
+ if (exch2)
+ exch2(chan, Cur->Buffer2,
+ chan->Capture2Length,
+ Cur->ngeneBuffer.SR.Clock,
+ Flags);
+ spin_lock_irq(&chan->state_lock);
} else if (chan->HWState != HWSTATE_STOP)
chan->HWState = HWSTATE_RUN;
}
@@ -572,11 +570,7 @@
u16 BsSPI = ((stream & 1) ? 0x9800 : 0x9700);
u16 BsSDO = 0x9B00;
- /* down(&dev->stream_mutex); */
- while (down_trylock(&dev->stream_mutex)) {
- printk(KERN_INFO DEVICE_NAME ": SC locked\n");
- msleep(1);
- }
+ down(&dev->stream_mutex);
memset(&com, 0, sizeof(com));
com.cmd.hdr.Opcode = CMD_CONTROL;
com.cmd.hdr.Length = sizeof(struct FW_STREAM_CONTROL) - 2;
@@ -1252,14 +1246,17 @@
version = 15;
size = 23466;
fw_name = "ngene_15.fw";
+ dev->cmd_timeout_workaround = true;
break;
case 16:
size = 23498;
fw_name = "ngene_16.fw";
+ dev->cmd_timeout_workaround = true;
break;
case 17:
size = 24446;
fw_name = "ngene_17.fw";
+ dev->cmd_timeout_workaround = true;
break;
}
@@ -1299,11 +1296,16 @@
ngwritel(0, NGENE_EVENT);
ngwritel(0, NGENE_EVENT_HI);
free_irq(dev->pci_dev->irq, dev);
+#ifdef CONFIG_PCI_MSI
+ if (dev->msi_enabled)
+ pci_disable_msi(dev->pci_dev);
+#endif
}
static int ngene_start(struct ngene *dev)
{
int stat;
+ unsigned long flags;
int i;
pci_set_master(dev->pci_dev);
@@ -1333,6 +1335,28 @@
if (stat < 0)
goto fail;
+#ifdef CONFIG_PCI_MSI
+ /* enable MSI if kernel and card support it */
+ if (pci_msi_enabled() && dev->card_info->msi_supported) {
+ ngwritel(0, NGENE_INT_ENABLE);
+ free_irq(dev->pci_dev->irq, dev);
+ stat = pci_enable_msi(dev->pci_dev);
+ if (stat) {
+ printk(KERN_INFO DEVICE_NAME
+ ": MSI not available\n");
+ flags = IRQF_SHARED;
+ } else {
+ flags = 0;
+ dev->msi_enabled = true;
+ }
+ stat = request_irq(dev->pci_dev->irq, irq_handler,
+ flags, "nGene", dev);
+ if (stat < 0)
+ goto fail2;
+ ngwritel(1, NGENE_INT_ENABLE);
+ }
+#endif
+
stat = ngene_i2c_init(dev, 0);
if (stat < 0)
goto fail;
@@ -1358,10 +1382,18 @@
bconf = BUFFER_CONFIG_3333;
stat = ngene_command_config_buf(dev, bconf);
}
- return stat;
+ if (!stat)
+ return stat;
+
+ /* otherwise error: fall through */
fail:
ngwritel(0, NGENE_INT_ENABLE);
free_irq(dev->pci_dev->irq, dev);
+#ifdef CONFIG_PCI_MSI
+fail2:
+ if (dev->msi_enabled)
+ pci_disable_msi(dev->pci_dev);
+#endif
return stat;
}
@@ -1379,10 +1411,8 @@
struct ngene_info *ni = dev->card_info;
int io = ni->io_type[chan->number];
-#ifdef COMMAND_TIMEOUT_WORKAROUND
- if (chan->running)
+ if (chan->dev->cmd_timeout_workaround && chan->running)
set_transfer(chan, 0);
-#endif
tasklet_kill(&chan->demux_tasklet);
diff --git a/drivers/media/dvb/ngene/ngene-dvb.c b/drivers/media/dvb/ngene/ngene-dvb.c
index 96013eb..48f980b 100644
--- a/drivers/media/dvb/ngene/ngene-dvb.c
+++ b/drivers/media/dvb/ngene/ngene-dvb.c
@@ -37,15 +37,12 @@
#include <linux/pci.h>
#include <linux/smp_lock.h>
#include <linux/timer.h>
-#include <linux/version.h>
#include <linux/byteorder/generic.h>
#include <linux/firmware.h>
#include <linux/vmalloc.h>
#include "ngene.h"
-#define COMMAND_TIMEOUT_WORKAROUND
-
/****************************************************************************/
/* COMMAND API interface ****************************************************/
@@ -69,9 +66,7 @@
struct ngene_channel *chan = priv;
-#ifdef COMMAND_TIMEOUT_WORKAROUND
if (chan->users > 0)
-#endif
dvb_dmx_swfilter(&chan->demux, buf, len);
return NULL;
}
@@ -106,11 +101,8 @@
struct ngene_channel *chan = dvbdmx->priv;
if (chan->users == 0) {
-#ifdef COMMAND_TIMEOUT_WORKAROUND
- if (!chan->running)
-#endif
+ if (!chan->dev->cmd_timeout_workaround || !chan->running)
set_transfer(chan, 1);
- /* msleep(10); */
}
return ++chan->users;
@@ -124,9 +116,8 @@
if (--chan->users)
return chan->users;
-#ifndef COMMAND_TIMEOUT_WORKAROUND
- set_transfer(chan, 0);
-#endif
+ if (!chan->dev->cmd_timeout_workaround)
+ set_transfer(chan, 0);
return 0;
}
diff --git a/drivers/media/dvb/ngene/ngene-i2c.c b/drivers/media/dvb/ngene/ngene-i2c.c
index 2ef54ca6..477fe0a 100644
--- a/drivers/media/dvb/ngene/ngene-i2c.c
+++ b/drivers/media/dvb/ngene/ngene-i2c.c
@@ -39,7 +39,6 @@
#include <linux/pci_ids.h>
#include <linux/smp_lock.h>
#include <linux/timer.h>
-#include <linux/version.h>
#include <linux/byteorder/generic.h>
#include <linux/firmware.h>
#include <linux/vmalloc.h>
diff --git a/drivers/media/dvb/ngene/ngene.h b/drivers/media/dvb/ngene/ngene.h
index 676fcbb..8fb4200 100644
--- a/drivers/media/dvb/ngene/ngene.h
+++ b/drivers/media/dvb/ngene/ngene.h
@@ -725,6 +725,8 @@
u32 device_version;
u32 fw_interface_version;
u32 icounts;
+ bool msi_enabled;
+ bool cmd_timeout_workaround;
u8 *CmdDoneByte;
int BootFirmware;
@@ -797,6 +799,7 @@
#define NGENE_VBOX_V2 7
int fw_version;
+ bool msi_supported;
char *name;
int io_type[MAX_STREAM];
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig
index d8d4214..32a7ec6 100644
--- a/drivers/media/dvb/ttpci/Kconfig
+++ b/drivers/media/dvb/ttpci/Kconfig
@@ -68,13 +68,14 @@
select DVB_VES1820 if !DVB_FE_CUSTOMISE
select DVB_L64781 if !DVB_FE_CUSTOMISE
select DVB_TDA8083 if !DVB_FE_CUSTOMISE
- select DVB_TDA10021 if !DVB_FE_CUSTOMISE
- select DVB_TDA10023 if !DVB_FE_CUSTOMISE
select DVB_S5H1420 if !DVB_FE_CUSTOMISE
select DVB_TDA10086 if !DVB_FE_CUSTOMISE
select DVB_TDA826X if !DVB_FE_CUSTOMISE
select DVB_LNBP21 if !DVB_FE_CUSTOMISE
select DVB_TDA1004X if !DVB_FE_CUSTOMISE
+ select DVB_ISL6423 if !DVB_FE_CUSTOMISE
+ select DVB_STV090x if !DVB_FE_CUSTOMISE
+ select DVB_STV6110x if !DVB_FE_CUSTOMISE
help
Support for simple SAA7146 based DVB cards (so called Budget-
or Nova-PCI cards) without onboard MPEG2 decoder, and without
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index 4617143..13ac9e3 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -215,6 +215,7 @@
break;
case 0x1010:
case 0x1017:
+ case 0x1019:
case 0x101a:
/* for the Technotrend 1500 bundled remote */
ir_codes = RC_MAP_TT_1500;
diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c
index a5844d0..67a4ec8 100644
--- a/drivers/media/radio/si470x/radio-si470x-i2c.c
+++ b/drivers/media/radio/si470x/radio-si470x-i2c.c
@@ -482,7 +482,6 @@
cancel_work_sync(&radio->radio_work);
video_unregister_device(radio->videodev);
kfree(radio);
- i2c_set_clientdata(client, NULL);
return 0;
}
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index ad9e6f9..bdbc9d3 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -646,7 +646,7 @@
config VIDEO_BWQCAM
tristate "Quickcam BW Video For Linux"
- depends on PARPORT && VIDEO_V4L1
+ depends on PARPORT && VIDEO_V4L2
help
Say Y have if you the black and white version of the QuickCam
camera. See the next option for the color version.
@@ -656,7 +656,7 @@
config VIDEO_CQCAM
tristate "QuickCam Colour Video For Linux (EXPERIMENTAL)"
- depends on EXPERIMENTAL && PARPORT && VIDEO_V4L1
+ depends on EXPERIMENTAL && PARPORT && VIDEO_V4L2
help
This is the video4linux driver for the colour version of the
Connectix QuickCam. If you have one of these cameras, say Y here,
diff --git a/drivers/media/video/ak881x.c b/drivers/media/video/ak881x.c
index 35390d4..1573392 100644
--- a/drivers/media/video/ak881x.c
+++ b/drivers/media/video/ak881x.c
@@ -11,6 +11,7 @@
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/platform_device.h>
+#include <linux/slab.h>
#include <linux/videodev2.h>
#include <media/ak881x.h>
@@ -141,7 +142,7 @@
return ak881x_try_g_mbus_fmt(sd, mf);
}
-static int ak881x_enum_mbus_fmt(struct v4l2_subdev *sd, int index,
+static int ak881x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
enum v4l2_mbus_pixelcode *code)
{
if (index)
diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c
index 3c9e754..935e0c9 100644
--- a/drivers/media/video/bw-qcam.c
+++ b/drivers/media/video/bw-qcam.c
@@ -66,19 +66,58 @@
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/fs.h>
-#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/parport.h>
#include <linux/sched.h>
-#include <linux/videodev.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
+#include <linux/version.h>
+#include <linux/videodev2.h>
#include <linux/mutex.h>
#include <asm/uaccess.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
-#include "bw-qcam.h"
+/* One from column A... */
+#define QC_NOTSET 0
+#define QC_UNIDIR 1
+#define QC_BIDIR 2
+#define QC_SERIAL 3
+
+/* ... and one from column B */
+#define QC_ANY 0x00
+#define QC_FORCE_UNIDIR 0x10
+#define QC_FORCE_BIDIR 0x20
+#define QC_FORCE_SERIAL 0x30
+/* in the port_mode member */
+
+#define QC_MODE_MASK 0x07
+#define QC_FORCE_MASK 0x70
+
+#define MAX_HEIGHT 243
+#define MAX_WIDTH 336
+
+/* Bit fields for status flags */
+#define QC_PARAM_CHANGE 0x01 /* Camera status change has occurred */
+
+struct qcam {
+ struct v4l2_device v4l2_dev;
+ struct video_device vdev;
+ struct pardevice *pdev;
+ struct parport *pport;
+ struct mutex lock;
+ int width, height;
+ int bpp;
+ int mode;
+ int contrast, brightness, whitebal;
+ int port_mode;
+ int transfer_scale;
+ int top, left;
+ int status;
+ unsigned int saved_bits;
+ unsigned long in_use;
+};
static unsigned int maxpoll = 250; /* Maximum busy-loop count for qcam I/O */
static unsigned int yieldlines = 4; /* Yield after this many during capture */
@@ -93,22 +132,26 @@
* immediately attempt to initialize qcam */
module_param(force_init, int, 0);
-static inline int read_lpstatus(struct qcam_device *q)
+#define MAX_CAMS 4
+static struct qcam *qcams[MAX_CAMS];
+static unsigned int num_cams;
+
+static inline int read_lpstatus(struct qcam *q)
{
return parport_read_status(q->pport);
}
-static inline int read_lpdata(struct qcam_device *q)
+static inline int read_lpdata(struct qcam *q)
{
return parport_read_data(q->pport);
}
-static inline void write_lpdata(struct qcam_device *q, int d)
+static inline void write_lpdata(struct qcam *q, int d)
{
parport_write_data(q->pport, d);
}
-static inline void write_lpcontrol(struct qcam_device *q, int d)
+static void write_lpcontrol(struct qcam *q, int d)
{
if (d & 0x20) {
/* Set bidirectional mode to reverse (data in) */
@@ -124,126 +167,11 @@
parport_write_control(q->pport, d);
}
-static int qc_waithand(struct qcam_device *q, int val);
-static int qc_command(struct qcam_device *q, int command);
-static int qc_readparam(struct qcam_device *q);
-static int qc_setscanmode(struct qcam_device *q);
-static int qc_readbytes(struct qcam_device *q, char buffer[]);
-
-static struct video_device qcam_template;
-
-static int qc_calibrate(struct qcam_device *q)
-{
- /*
- * Bugfix by Hanno Mueller hmueller@kabel.de, Mai 21 96
- * The white balance is an individiual value for each
- * quickcam.
- */
-
- int value;
- int count = 0;
-
- qc_command(q, 27); /* AutoAdjustOffset */
- qc_command(q, 0); /* Dummy Parameter, ignored by the camera */
-
- /* GetOffset (33) will read 255 until autocalibration */
- /* is finished. After that, a value of 1-254 will be */
- /* returned. */
-
- do {
- qc_command(q, 33);
- value = qc_readparam(q);
- mdelay(1);
- schedule();
- count++;
- } while (value == 0xff && count < 2048);
-
- q->whitebal = value;
- return value;
-}
-
-/* Initialize the QuickCam driver control structure. This is where
- * defaults are set for people who don't have a config file.*/
-
-static struct qcam_device *qcam_init(struct parport *port)
-{
- struct qcam_device *q;
-
- q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL);
- if (q == NULL)
- return NULL;
-
- q->pport = port;
- q->pdev = parport_register_device(port, "bw-qcam", NULL, NULL,
- NULL, 0, NULL);
- if (q->pdev == NULL) {
- printk(KERN_ERR "bw-qcam: couldn't register for %s.\n",
- port->name);
- kfree(q);
- return NULL;
- }
-
- memcpy(&q->vdev, &qcam_template, sizeof(qcam_template));
-
- mutex_init(&q->lock);
-
- q->port_mode = (QC_ANY | QC_NOTSET);
- q->width = 320;
- q->height = 240;
- q->bpp = 4;
- q->transfer_scale = 2;
- q->contrast = 192;
- q->brightness = 180;
- q->whitebal = 105;
- q->top = 1;
- q->left = 14;
- q->mode = -1;
- q->status = QC_PARAM_CHANGE;
- return q;
-}
-
-
-/* qc_command is probably a bit of a misnomer -- it's used to send
- * bytes *to* the camera. Generally, these bytes are either commands
- * or arguments to commands, so the name fits, but it still bugs me a
- * bit. See the documentation for a list of commands. */
-
-static int qc_command(struct qcam_device *q, int command)
-{
- int n1, n2;
- int cmd;
-
- write_lpdata(q, command);
- write_lpcontrol(q, 6);
-
- n1 = qc_waithand(q, 1);
-
- write_lpcontrol(q, 0xe);
- n2 = qc_waithand(q, 0);
-
- cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
- return cmd;
-}
-
-static int qc_readparam(struct qcam_device *q)
-{
- int n1, n2;
- int cmd;
-
- write_lpcontrol(q, 6);
- n1 = qc_waithand(q, 1);
-
- write_lpcontrol(q, 0xe);
- n2 = qc_waithand(q, 0);
-
- cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
- return cmd;
-}
/* qc_waithand busy-waits for a handshake signal from the QuickCam.
* Almost all communication with the camera requires handshaking. */
-static int qc_waithand(struct qcam_device *q, int val)
+static int qc_waithand(struct qcam *q, int val)
{
int status;
int runs = 0;
@@ -286,7 +214,7 @@
* (bit 3 of status register). It also returns the last value read,
* since this data is useful. */
-static unsigned int qc_waithand2(struct qcam_device *q, int val)
+static unsigned int qc_waithand2(struct qcam *q, int val)
{
unsigned int status;
int runs = 0;
@@ -309,6 +237,43 @@
return status;
}
+/* qc_command is probably a bit of a misnomer -- it's used to send
+ * bytes *to* the camera. Generally, these bytes are either commands
+ * or arguments to commands, so the name fits, but it still bugs me a
+ * bit. See the documentation for a list of commands. */
+
+static int qc_command(struct qcam *q, int command)
+{
+ int n1, n2;
+ int cmd;
+
+ write_lpdata(q, command);
+ write_lpcontrol(q, 6);
+
+ n1 = qc_waithand(q, 1);
+
+ write_lpcontrol(q, 0xe);
+ n2 = qc_waithand(q, 0);
+
+ cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
+ return cmd;
+}
+
+static int qc_readparam(struct qcam *q)
+{
+ int n1, n2;
+ int cmd;
+
+ write_lpcontrol(q, 6);
+ n1 = qc_waithand(q, 1);
+
+ write_lpcontrol(q, 0xe);
+ n2 = qc_waithand(q, 0);
+
+ cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
+ return cmd;
+}
+
/* Try to detect a QuickCam. It appears to flash the upper 4 bits of
the status register at 5-10 Hz. This is only used in the autoprobe
@@ -317,7 +282,7 @@
almost completely safe, while their method screws up my printer if
I plug it in before the camera. */
-static int qc_detect(struct qcam_device *q)
+static int qc_detect(struct qcam *q)
{
int reg, lastreg;
int count = 0;
@@ -358,41 +323,6 @@
}
}
-
-/* Reset the QuickCam. This uses the same sequence the Windows
- * QuickPic program uses. Someone with a bi-directional port should
- * check that bi-directional mode is detected right, and then
- * implement bi-directional mode in qc_readbyte(). */
-
-static void qc_reset(struct qcam_device *q)
-{
- switch (q->port_mode & QC_FORCE_MASK) {
- case QC_FORCE_UNIDIR:
- q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
- break;
-
- case QC_FORCE_BIDIR:
- q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
- break;
-
- case QC_ANY:
- write_lpcontrol(q, 0x20);
- write_lpdata(q, 0x75);
-
- if (read_lpdata(q) != 0x75)
- q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
- else
- q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
- break;
- }
-
- write_lpcontrol(q, 0xb);
- udelay(250);
- write_lpcontrol(q, 0xe);
- qc_setscanmode(q); /* in case port_mode changed */
-}
-
-
/* Decide which scan mode to use. There's no real requirement that
* the scanmode match the resolution in q->height and q-> width -- the
* camera takes the picture at the resolution specified in the
@@ -402,7 +332,7 @@
* returned. If the scan is smaller, then the rest of the image
* returned contains garbage. */
-static int qc_setscanmode(struct qcam_device *q)
+static int qc_setscanmode(struct qcam *q)
{
int old_mode = q->mode;
@@ -442,10 +372,45 @@
}
+/* Reset the QuickCam. This uses the same sequence the Windows
+ * QuickPic program uses. Someone with a bi-directional port should
+ * check that bi-directional mode is detected right, and then
+ * implement bi-directional mode in qc_readbyte(). */
+
+static void qc_reset(struct qcam *q)
+{
+ switch (q->port_mode & QC_FORCE_MASK) {
+ case QC_FORCE_UNIDIR:
+ q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
+ break;
+
+ case QC_FORCE_BIDIR:
+ q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
+ break;
+
+ case QC_ANY:
+ write_lpcontrol(q, 0x20);
+ write_lpdata(q, 0x75);
+
+ if (read_lpdata(q) != 0x75)
+ q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
+ else
+ q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
+ break;
+ }
+
+ write_lpcontrol(q, 0xb);
+ udelay(250);
+ write_lpcontrol(q, 0xe);
+ qc_setscanmode(q); /* in case port_mode changed */
+}
+
+
+
/* Reset the QuickCam and program for brightness, contrast,
* white-balance, and resolution. */
-static void qc_set(struct qcam_device *q)
+static void qc_set(struct qcam *q)
{
int val;
int val2;
@@ -499,7 +464,7 @@
the supplied buffer. It returns the number of bytes read,
or -1 on error. */
-static inline int qc_readbytes(struct qcam_device *q, char buffer[])
+static inline int qc_readbytes(struct qcam *q, char buffer[])
{
int ret = 1;
unsigned int hi, lo;
@@ -590,7 +555,7 @@
* n=2^(bit depth)-1. Ask me for more details if you don't understand
* this. */
-static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long len)
+static long qc_capture(struct qcam *q, char __user *buf, unsigned long len)
{
int i, j, k, yield;
int bytes;
@@ -674,171 +639,206 @@
* Video4linux interfacing
*/
-static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static int qcam_querycap(struct file *file, void *priv,
+ struct v4l2_capability *vcap)
{
- struct video_device *dev = video_devdata(file);
- struct qcam_device *qcam = (struct qcam_device *)dev;
+ struct qcam *qcam = video_drvdata(file);
- switch (cmd) {
- case VIDIOCGCAP:
- {
- struct video_capability *b = arg;
- strcpy(b->name, "Quickcam");
- b->type = VID_TYPE_CAPTURE|VID_TYPE_SCALES|VID_TYPE_MONOCHROME;
- b->channels = 1;
- b->audios = 0;
- b->maxwidth = 320;
- b->maxheight = 240;
- b->minwidth = 80;
- b->minheight = 60;
- return 0;
- }
- case VIDIOCGCHAN:
- {
- struct video_channel *v = arg;
- if (v->channel != 0)
- return -EINVAL;
- v->flags = 0;
- v->tuners = 0;
- /* Good question.. its composite or SVHS so.. */
- v->type = VIDEO_TYPE_CAMERA;
- strcpy(v->name, "Camera");
- return 0;
- }
- case VIDIOCSCHAN:
- {
- struct video_channel *v = arg;
- if (v->channel != 0)
- return -EINVAL;
- return 0;
- }
- case VIDIOCGTUNER:
- {
- struct video_tuner *v = arg;
- if (v->tuner)
- return -EINVAL;
- strcpy(v->name, "Format");
- v->rangelow = 0;
- v->rangehigh = 0;
- v->flags = 0;
- v->mode = VIDEO_MODE_AUTO;
- return 0;
- }
- case VIDIOCSTUNER:
- {
- struct video_tuner *v = arg;
- if (v->tuner)
- return -EINVAL;
- if (v->mode != VIDEO_MODE_AUTO)
- return -EINVAL;
- return 0;
- }
- case VIDIOCGPICT:
- {
- struct video_picture *p = arg;
- p->colour = 0x8000;
- p->hue = 0x8000;
- p->brightness = qcam->brightness << 8;
- p->contrast = qcam->contrast << 8;
- p->whiteness = qcam->whitebal << 8;
- p->depth = qcam->bpp;
- p->palette = VIDEO_PALETTE_GREY;
- return 0;
- }
- case VIDIOCSPICT:
- {
- struct video_picture *p = arg;
- if (p->palette != VIDEO_PALETTE_GREY)
- return -EINVAL;
- if (p->depth != 4 && p->depth != 6)
- return -EINVAL;
-
- /*
- * Now load the camera.
- */
-
- qcam->brightness = p->brightness >> 8;
- qcam->contrast = p->contrast >> 8;
- qcam->whitebal = p->whiteness >> 8;
- qcam->bpp = p->depth;
-
- mutex_lock(&qcam->lock);
- qc_setscanmode(qcam);
- mutex_unlock(&qcam->lock);
- qcam->status |= QC_PARAM_CHANGE;
-
- return 0;
- }
- case VIDIOCSWIN:
- {
- struct video_window *vw = arg;
- if (vw->flags)
- return -EINVAL;
- if (vw->clipcount)
- return -EINVAL;
- if (vw->height < 60 || vw->height > 240)
- return -EINVAL;
- if (vw->width < 80 || vw->width > 320)
- return -EINVAL;
-
- qcam->width = 320;
- qcam->height = 240;
- qcam->transfer_scale = 4;
-
- if (vw->width >= 160 && vw->height >= 120)
- qcam->transfer_scale = 2;
- if (vw->width >= 320 && vw->height >= 240) {
- qcam->width = 320;
- qcam->height = 240;
- qcam->transfer_scale = 1;
- }
- mutex_lock(&qcam->lock);
- qc_setscanmode(qcam);
- mutex_unlock(&qcam->lock);
-
- /* We must update the camera before we grab. We could
- just have changed the grab size */
- qcam->status |= QC_PARAM_CHANGE;
-
- /* Ok we figured out what to use from our wide choice */
- return 0;
- }
- case VIDIOCGWIN:
- {
- struct video_window *vw = arg;
-
- memset(vw, 0, sizeof(*vw));
- vw->width = qcam->width / qcam->transfer_scale;
- vw->height = qcam->height / qcam->transfer_scale;
- return 0;
- }
- case VIDIOCKEY:
- return 0;
- case VIDIOCCAPTURE:
- case VIDIOCGFBUF:
- case VIDIOCSFBUF:
- case VIDIOCGFREQ:
- case VIDIOCSFREQ:
- case VIDIOCGAUDIO:
- case VIDIOCSAUDIO:
- return -EINVAL;
- default:
- return -ENOIOCTLCMD;
- }
+ strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver));
+ strlcpy(vcap->card, "B&W Quickcam", sizeof(vcap->card));
+ strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info));
+ vcap->version = KERNEL_VERSION(0, 0, 2);
+ vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
return 0;
}
-static long qcam_ioctl(struct file *file,
- unsigned int cmd, unsigned long arg)
+static int qcam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
{
- return video_usercopy(file, cmd, arg, qcam_do_ioctl);
+ if (vin->index > 0)
+ return -EINVAL;
+ strlcpy(vin->name, "Camera", sizeof(vin->name));
+ vin->type = V4L2_INPUT_TYPE_CAMERA;
+ vin->audioset = 0;
+ vin->tuner = 0;
+ vin->std = 0;
+ vin->status = 0;
+ return 0;
+}
+
+static int qcam_g_input(struct file *file, void *fh, unsigned int *inp)
+{
+ *inp = 0;
+ return 0;
+}
+
+static int qcam_s_input(struct file *file, void *fh, unsigned int inp)
+{
+ return (inp > 0) ? -EINVAL : 0;
+}
+
+static int qcam_queryctrl(struct file *file, void *priv,
+ struct v4l2_queryctrl *qc)
+{
+ switch (qc->id) {
+ case V4L2_CID_BRIGHTNESS:
+ return v4l2_ctrl_query_fill(qc, 0, 255, 1, 180);
+ case V4L2_CID_CONTRAST:
+ return v4l2_ctrl_query_fill(qc, 0, 255, 1, 192);
+ case V4L2_CID_GAMMA:
+ return v4l2_ctrl_query_fill(qc, 0, 255, 1, 105);
+ }
+ return -EINVAL;
+}
+
+static int qcam_g_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct qcam *qcam = video_drvdata(file);
+ int ret = 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ ctrl->value = qcam->brightness;
+ break;
+ case V4L2_CID_CONTRAST:
+ ctrl->value = qcam->contrast;
+ break;
+ case V4L2_CID_GAMMA:
+ ctrl->value = qcam->whitebal;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int qcam_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct qcam *qcam = video_drvdata(file);
+ int ret = 0;
+
+ mutex_lock(&qcam->lock);
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ qcam->brightness = ctrl->value;
+ break;
+ case V4L2_CID_CONTRAST:
+ qcam->contrast = ctrl->value;
+ break;
+ case V4L2_CID_GAMMA:
+ qcam->whitebal = ctrl->value;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ if (ret == 0) {
+ qc_setscanmode(qcam);
+ qcam->status |= QC_PARAM_CHANGE;
+ }
+ mutex_unlock(&qcam->lock);
+ return ret;
+}
+
+static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+ struct qcam *qcam = video_drvdata(file);
+ struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+ pix->width = qcam->width / qcam->transfer_scale;
+ pix->height = qcam->height / qcam->transfer_scale;
+ pix->pixelformat = (qcam->bpp == 4) ? V4L2_PIX_FMT_Y4 : V4L2_PIX_FMT_Y6;
+ pix->field = V4L2_FIELD_NONE;
+ pix->bytesperline = qcam->width;
+ pix->sizeimage = qcam->width * qcam->height;
+ /* Just a guess */
+ pix->colorspace = V4L2_COLORSPACE_SRGB;
+ return 0;
+}
+
+static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+ struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+ if (pix->height <= 60 || pix->width <= 80) {
+ pix->height = 60;
+ pix->width = 80;
+ } else if (pix->height <= 120 || pix->width <= 160) {
+ pix->height = 120;
+ pix->width = 160;
+ } else {
+ pix->height = 240;
+ pix->width = 320;
+ }
+ if (pix->pixelformat != V4L2_PIX_FMT_Y4 &&
+ pix->pixelformat != V4L2_PIX_FMT_Y6)
+ pix->pixelformat = V4L2_PIX_FMT_Y4;
+ pix->field = V4L2_FIELD_NONE;
+ pix->bytesperline = pix->width;
+ pix->sizeimage = pix->width * pix->height;
+ /* Just a guess */
+ pix->colorspace = V4L2_COLORSPACE_SRGB;
+ return 0;
+}
+
+static int qcam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+ struct qcam *qcam = video_drvdata(file);
+ struct v4l2_pix_format *pix = &fmt->fmt.pix;
+ int ret = qcam_try_fmt_vid_cap(file, fh, fmt);
+
+ if (ret)
+ return ret;
+ qcam->width = 320;
+ qcam->height = 240;
+ if (pix->height == 60)
+ qcam->transfer_scale = 4;
+ else if (pix->height == 120)
+ qcam->transfer_scale = 2;
+ else
+ qcam->transfer_scale = 1;
+ if (pix->pixelformat == V4L2_PIX_FMT_Y6)
+ qcam->bpp = 6;
+ else
+ qcam->bpp = 4;
+
+ mutex_lock(&qcam->lock);
+ qc_setscanmode(qcam);
+ /* We must update the camera before we grab. We could
+ just have changed the grab size */
+ qcam->status |= QC_PARAM_CHANGE;
+ mutex_unlock(&qcam->lock);
+ return 0;
+}
+
+static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
+{
+ static struct v4l2_fmtdesc formats[] = {
+ { 0, 0, 0,
+ "4-Bit Monochrome", V4L2_PIX_FMT_Y4,
+ { 0, 0, 0, 0 }
+ },
+ { 0, 0, 0,
+ "6-Bit Monochrome", V4L2_PIX_FMT_Y6,
+ { 0, 0, 0, 0 }
+ },
+ };
+ enum v4l2_buf_type type = fmt->type;
+
+ if (fmt->index > 1)
+ return -EINVAL;
+
+ *fmt = formats[fmt->index];
+ fmt->type = type;
+ return 0;
}
static ssize_t qcam_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- struct video_device *v = video_devdata(file);
- struct qcam_device *qcam = (struct qcam_device *)v;
+ struct qcam *qcam = video_drvdata(file);
int len;
parport_claim_or_block(qcam->pdev);
@@ -858,43 +858,112 @@
return len;
}
-static int qcam_exclusive_open(struct file *file)
-{
- struct video_device *dev = video_devdata(file);
- struct qcam_device *qcam = (struct qcam_device *)dev;
-
- return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0;
-}
-
-static int qcam_exclusive_release(struct file *file)
-{
- struct video_device *dev = video_devdata(file);
- struct qcam_device *qcam = (struct qcam_device *)dev;
-
- clear_bit(0, &qcam->in_use);
- return 0;
-}
-
static const struct v4l2_file_operations qcam_fops = {
.owner = THIS_MODULE,
- .open = qcam_exclusive_open,
- .release = qcam_exclusive_release,
- .ioctl = qcam_ioctl,
+ .ioctl = video_ioctl2,
.read = qcam_read,
};
-static struct video_device qcam_template = {
- .name = "Connectix Quickcam",
- .fops = &qcam_fops,
- .release = video_device_release_empty,
+
+static const struct v4l2_ioctl_ops qcam_ioctl_ops = {
+ .vidioc_querycap = qcam_querycap,
+ .vidioc_g_input = qcam_g_input,
+ .vidioc_s_input = qcam_s_input,
+ .vidioc_enum_input = qcam_enum_input,
+ .vidioc_queryctrl = qcam_queryctrl,
+ .vidioc_g_ctrl = qcam_g_ctrl,
+ .vidioc_s_ctrl = qcam_s_ctrl,
+ .vidioc_enum_fmt_vid_cap = qcam_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = qcam_g_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = qcam_s_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = qcam_try_fmt_vid_cap,
};
-#define MAX_CAMS 4
-static struct qcam_device *qcams[MAX_CAMS];
-static unsigned int num_cams;
+/* Initialize the QuickCam driver control structure. This is where
+ * defaults are set for people who don't have a config file.*/
+
+static struct qcam *qcam_init(struct parport *port)
+{
+ struct qcam *qcam;
+ struct v4l2_device *v4l2_dev;
+
+ qcam = kzalloc(sizeof(struct qcam), GFP_KERNEL);
+ if (qcam == NULL)
+ return NULL;
+
+ v4l2_dev = &qcam->v4l2_dev;
+ strlcpy(v4l2_dev->name, "bw-qcam", sizeof(v4l2_dev->name));
+
+ if (v4l2_device_register(NULL, v4l2_dev) < 0) {
+ v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+ return NULL;
+ }
+
+ qcam->pport = port;
+ qcam->pdev = parport_register_device(port, "bw-qcam", NULL, NULL,
+ NULL, 0, NULL);
+ if (qcam->pdev == NULL) {
+ v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name);
+ kfree(qcam);
+ return NULL;
+ }
+
+ strlcpy(qcam->vdev.name, "Connectix QuickCam", sizeof(qcam->vdev.name));
+ qcam->vdev.v4l2_dev = v4l2_dev;
+ qcam->vdev.fops = &qcam_fops;
+ qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
+ qcam->vdev.release = video_device_release_empty;
+ video_set_drvdata(&qcam->vdev, qcam);
+
+ mutex_init(&qcam->lock);
+
+ qcam->port_mode = (QC_ANY | QC_NOTSET);
+ qcam->width = 320;
+ qcam->height = 240;
+ qcam->bpp = 4;
+ qcam->transfer_scale = 2;
+ qcam->contrast = 192;
+ qcam->brightness = 180;
+ qcam->whitebal = 105;
+ qcam->top = 1;
+ qcam->left = 14;
+ qcam->mode = -1;
+ qcam->status = QC_PARAM_CHANGE;
+ return qcam;
+}
+
+static int qc_calibrate(struct qcam *q)
+{
+ /*
+ * Bugfix by Hanno Mueller hmueller@kabel.de, Mai 21 96
+ * The white balance is an individual value for each
+ * quickcam.
+ */
+
+ int value;
+ int count = 0;
+
+ qc_command(q, 27); /* AutoAdjustOffset */
+ qc_command(q, 0); /* Dummy Parameter, ignored by the camera */
+
+ /* GetOffset (33) will read 255 until autocalibration */
+ /* is finished. After that, a value of 1-254 will be */
+ /* returned. */
+
+ do {
+ qc_command(q, 33);
+ value = qc_readparam(q);
+ mdelay(1);
+ schedule();
+ count++;
+ } while (value == 0xff && count < 2048);
+
+ q->whitebal = value;
+ return value;
+}
static int init_bwqcam(struct parport *port)
{
- struct qcam_device *qcam;
+ struct qcam *qcam;
if (num_cams == MAX_CAMS) {
printk(KERN_ERR "Too many Quickcams (max %d)\n", MAX_CAMS);
@@ -919,7 +988,7 @@
parport_release(qcam->pdev);
- printk(KERN_INFO "Connectix Quickcam on %s\n", qcam->pport->name);
+ v4l2_info(&qcam->v4l2_dev, "Connectix Quickcam on %s\n", qcam->pport->name);
if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
parport_unregister_device(qcam->pdev);
@@ -932,7 +1001,7 @@
return 0;
}
-static void close_bwqcam(struct qcam_device *qcam)
+static void close_bwqcam(struct qcam *qcam)
{
video_unregister_device(&qcam->vdev);
parport_unregister_device(qcam->pdev);
@@ -983,7 +1052,7 @@
{
int i;
for (i = 0; i < num_cams; i++) {
- struct qcam_device *qcam = qcams[i];
+ struct qcam *qcam = qcams[i];
if (qcam && qcam->pdev->port == port) {
qcams[i] = NULL;
close_bwqcam(qcam);
diff --git a/drivers/media/video/bw-qcam.h b/drivers/media/video/bw-qcam.h
deleted file mode 100644
index 8a60c5d..0000000
--- a/drivers/media/video/bw-qcam.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Video4Linux bw-qcam driver
- *
- * Derived from code..
- */
-
-/******************************************************************
-
-Copyright (C) 1996 by Scott Laird
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL SCOTT LAIRD 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.
-
-******************************************************************/
-
-/* One from column A... */
-#define QC_NOTSET 0
-#define QC_UNIDIR 1
-#define QC_BIDIR 2
-#define QC_SERIAL 3
-
-/* ... and one from column B */
-#define QC_ANY 0x00
-#define QC_FORCE_UNIDIR 0x10
-#define QC_FORCE_BIDIR 0x20
-#define QC_FORCE_SERIAL 0x30
-/* in the port_mode member */
-
-#define QC_MODE_MASK 0x07
-#define QC_FORCE_MASK 0x70
-
-#define MAX_HEIGHT 243
-#define MAX_WIDTH 336
-
-/* Bit fields for status flags */
-#define QC_PARAM_CHANGE 0x01 /* Camera status change has occurred */
-
-struct qcam_device {
- struct video_device vdev;
- struct pardevice *pdev;
- struct parport *pport;
- struct mutex lock;
- int width, height;
- int bpp;
- int mode;
- int contrast, brightness, whitebal;
- int port_mode;
- int transfer_scale;
- int top, left;
- int status;
- unsigned int saved_bits;
- unsigned long in_use;
-};
diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c
index 8f1dd88..6e4b196 100644
--- a/drivers/media/video/c-qcam.c
+++ b/drivers/media/video/c-qcam.c
@@ -33,15 +33,17 @@
#include <linux/mm.h>
#include <linux/parport.h>
#include <linux/sched.h>
-#include <linux/videodev.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
#include <linux/mutex.h>
#include <linux/jiffies.h>
-
+#include <linux/version.h>
+#include <linux/videodev2.h>
#include <asm/uaccess.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
-struct qcam_device {
+struct qcam {
+ struct v4l2_device v4l2_dev;
struct video_device vdev;
struct pardevice *pdev;
struct parport *pport;
@@ -51,7 +53,6 @@
int contrast, brightness, whitebal;
int top, left;
unsigned int bidirectional;
- unsigned long in_use;
struct mutex lock;
};
@@ -68,33 +69,45 @@
#define QC_DECIMATION_2 2
#define QC_DECIMATION_4 4
-#define BANNER "Colour QuickCam for Video4Linux v0.05"
+#define BANNER "Colour QuickCam for Video4Linux v0.06"
static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 };
static int probe = 2;
static int force_rgb;
static int video_nr = -1;
-static inline void qcam_set_ack(struct qcam_device *qcam, unsigned int i)
+/* FIXME: parport=auto would never have worked, surely? --RR */
+MODULE_PARM_DESC(parport, "parport=<auto|n[,n]...> for port detection method\n"
+ "probe=<0|1|2> for camera detection method\n"
+ "force_rgb=<0|1> for RGB data format (default BGR)");
+module_param_array(parport, int, NULL, 0);
+module_param(probe, int, 0);
+module_param(force_rgb, bool, 0);
+module_param(video_nr, int, 0);
+
+static struct qcam *qcams[MAX_CAMS];
+static unsigned int num_cams;
+
+static inline void qcam_set_ack(struct qcam *qcam, unsigned int i)
{
/* note: the QC specs refer to the PCAck pin by voltage, not
software level. PC ports have builtin inverters. */
parport_frob_control(qcam->pport, 8, i ? 8 : 0);
}
-static inline unsigned int qcam_ready1(struct qcam_device *qcam)
+static inline unsigned int qcam_ready1(struct qcam *qcam)
{
return (parport_read_status(qcam->pport) & 0x8) ? 1 : 0;
}
-static inline unsigned int qcam_ready2(struct qcam_device *qcam)
+static inline unsigned int qcam_ready2(struct qcam *qcam)
{
return (parport_read_data(qcam->pport) & 0x1) ? 1 : 0;
}
-static unsigned int qcam_await_ready1(struct qcam_device *qcam,
- int value)
+static unsigned int qcam_await_ready1(struct qcam *qcam, int value)
{
+ struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
unsigned long oldjiffies = jiffies;
unsigned int i;
@@ -112,14 +125,15 @@
}
/* Probably somebody pulled the plug out. Not much we can do. */
- printk(KERN_ERR "c-qcam: ready1 timeout (%d) %x %x\n", value,
+ v4l2_err(v4l2_dev, "ready1 timeout (%d) %x %x\n", value,
parport_read_status(qcam->pport),
parport_read_control(qcam->pport));
return 1;
}
-static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value)
+static unsigned int qcam_await_ready2(struct qcam *qcam, int value)
{
+ struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
unsigned long oldjiffies = jiffies;
unsigned int i;
@@ -137,14 +151,14 @@
}
/* Probably somebody pulled the plug out. Not much we can do. */
- printk(KERN_ERR "c-qcam: ready2 timeout (%d) %x %x %x\n", value,
+ v4l2_err(v4l2_dev, "ready2 timeout (%d) %x %x %x\n", value,
parport_read_status(qcam->pport),
parport_read_control(qcam->pport),
parport_read_data(qcam->pport));
return 1;
}
-static int qcam_read_data(struct qcam_device *qcam)
+static int qcam_read_data(struct qcam *qcam)
{
unsigned int idata;
@@ -159,21 +173,22 @@
return idata;
}
-static int qcam_write_data(struct qcam_device *qcam, unsigned int data)
+static int qcam_write_data(struct qcam *qcam, unsigned int data)
{
+ struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
unsigned int idata;
parport_write_data(qcam->pport, data);
idata = qcam_read_data(qcam);
if (data != idata) {
- printk(KERN_WARNING "cqcam: sent %x but received %x\n", data,
+ v4l2_warn(v4l2_dev, "sent %x but received %x\n", data,
idata);
return 1;
}
return 0;
}
-static inline int qcam_set(struct qcam_device *qcam, unsigned int cmd, unsigned int data)
+static inline int qcam_set(struct qcam *qcam, unsigned int cmd, unsigned int data)
{
if (qcam_write_data(qcam, cmd))
return -1;
@@ -182,14 +197,14 @@
return 0;
}
-static inline int qcam_get(struct qcam_device *qcam, unsigned int cmd)
+static inline int qcam_get(struct qcam *qcam, unsigned int cmd)
{
if (qcam_write_data(qcam, cmd))
return -1;
return qcam_read_data(qcam);
}
-static int qc_detect(struct qcam_device *qcam)
+static int qc_detect(struct qcam *qcam)
{
unsigned int stat, ostat, i, count = 0;
@@ -246,7 +261,7 @@
return 0;
}
-static void qc_reset(struct qcam_device *qcam)
+static void qc_reset(struct qcam *qcam)
{
parport_write_control(qcam->pport, 0xc);
parport_write_control(qcam->pport, 0x8);
@@ -258,55 +273,55 @@
/* Reset the QuickCam and program for brightness, contrast,
* white-balance, and resolution. */
-static void qc_setup(struct qcam_device *q)
+static void qc_setup(struct qcam *qcam)
{
- qc_reset(q);
+ qc_reset(qcam);
/* Set the brightness. */
- qcam_set(q, 11, q->brightness);
+ qcam_set(qcam, 11, qcam->brightness);
/* Set the height and width. These refer to the actual
CCD area *before* applying the selected decimation. */
- qcam_set(q, 17, q->ccd_height);
- qcam_set(q, 19, q->ccd_width / 2);
+ qcam_set(qcam, 17, qcam->ccd_height);
+ qcam_set(qcam, 19, qcam->ccd_width / 2);
/* Set top and left. */
- qcam_set(q, 0xd, q->top);
- qcam_set(q, 0xf, q->left);
+ qcam_set(qcam, 0xd, qcam->top);
+ qcam_set(qcam, 0xf, qcam->left);
/* Set contrast and white balance. */
- qcam_set(q, 0x19, q->contrast);
- qcam_set(q, 0x1f, q->whitebal);
+ qcam_set(qcam, 0x19, qcam->contrast);
+ qcam_set(qcam, 0x1f, qcam->whitebal);
/* Set the speed. */
- qcam_set(q, 45, 2);
+ qcam_set(qcam, 45, 2);
}
/* Read some bytes from the camera and put them in the buffer.
nbytes should be a multiple of 3, because bidirectional mode gives
us three bytes at a time. */
-static unsigned int qcam_read_bytes(struct qcam_device *q, unsigned char *buf, unsigned int nbytes)
+static unsigned int qcam_read_bytes(struct qcam *qcam, unsigned char *buf, unsigned int nbytes)
{
unsigned int bytes = 0;
- qcam_set_ack(q, 0);
- if (q->bidirectional) {
+ qcam_set_ack(qcam, 0);
+ if (qcam->bidirectional) {
/* It's a bidirectional port */
while (bytes < nbytes) {
unsigned int lo1, hi1, lo2, hi2;
unsigned char r, g, b;
- if (qcam_await_ready2(q, 1))
+ if (qcam_await_ready2(qcam, 1))
return bytes;
- lo1 = parport_read_data(q->pport) >> 1;
- hi1 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10;
- qcam_set_ack(q, 1);
- if (qcam_await_ready2(q, 0))
+ lo1 = parport_read_data(qcam->pport) >> 1;
+ hi1 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10;
+ qcam_set_ack(qcam, 1);
+ if (qcam_await_ready2(qcam, 0))
return bytes;
- lo2 = parport_read_data(q->pport) >> 1;
- hi2 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10;
- qcam_set_ack(q, 0);
+ lo2 = parport_read_data(qcam->pport) >> 1;
+ hi2 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10;
+ qcam_set_ack(qcam, 0);
r = lo1 | ((hi1 & 1) << 7);
g = ((hi1 & 0x1e) << 3) | ((hi2 & 0x1e) >> 1);
b = lo2 | ((hi2 & 1) << 7);
@@ -328,14 +343,14 @@
while (bytes < nbytes) {
unsigned int hi, lo;
- if (qcam_await_ready1(q, 1))
+ if (qcam_await_ready1(qcam, 1))
return bytes;
- hi = (parport_read_status(q->pport) & 0xf0);
- qcam_set_ack(q, 1);
- if (qcam_await_ready1(q, 0))
+ hi = (parport_read_status(qcam->pport) & 0xf0);
+ qcam_set_ack(qcam, 1);
+ if (qcam_await_ready1(qcam, 0))
return bytes;
- lo = (parport_read_status(q->pport) & 0xf0);
- qcam_set_ack(q, 0);
+ lo = (parport_read_status(qcam->pport) & 0xf0);
+ qcam_set_ack(qcam, 0);
/* flip some bits */
rgb[(i = bytes++ % 3)] = (hi | (lo >> 4)) ^ 0x88;
if (i >= 2) {
@@ -361,10 +376,11 @@
#define BUFSZ 150
-static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long len)
+static long qc_capture(struct qcam *qcam, char __user *buf, unsigned long len)
{
+ struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
unsigned lines, pixelsperline, bitsperxfer;
- unsigned int is_bi_dir = q->bidirectional;
+ unsigned int is_bi_dir = qcam->bidirectional;
size_t wantlen, outptr = 0;
char tmpbuf[BUFSZ];
@@ -373,10 +389,10 @@
/* Wait for camera to become ready */
for (;;) {
- int i = qcam_get(q, 41);
+ int i = qcam_get(qcam, 41);
if (i == -1) {
- qc_setup(q);
+ qc_setup(qcam);
return -EIO;
}
if ((i & 0x80) == 0)
@@ -384,25 +400,25 @@
schedule();
}
- if (qcam_set(q, 7, (q->mode | (is_bi_dir ? 1 : 0)) + 1))
+ if (qcam_set(qcam, 7, (qcam->mode | (is_bi_dir ? 1 : 0)) + 1))
return -EIO;
- lines = q->height;
- pixelsperline = q->width;
+ lines = qcam->height;
+ pixelsperline = qcam->width;
bitsperxfer = (is_bi_dir) ? 24 : 8;
if (is_bi_dir) {
/* Turn the port around */
- parport_data_reverse(q->pport);
+ parport_data_reverse(qcam->pport);
mdelay(3);
- qcam_set_ack(q, 0);
- if (qcam_await_ready1(q, 1)) {
- qc_setup(q);
+ qcam_set_ack(qcam, 0);
+ if (qcam_await_ready1(qcam, 1)) {
+ qc_setup(qcam);
return -EIO;
}
- qcam_set_ack(q, 1);
- if (qcam_await_ready1(q, 0)) {
- qc_setup(q);
+ qcam_set_ack(qcam, 1);
+ if (qcam_await_ready1(qcam, 0)) {
+ qc_setup(qcam);
return -EIO;
}
}
@@ -413,7 +429,7 @@
size_t t, s;
s = (wantlen > BUFSZ) ? BUFSZ : wantlen;
- t = qcam_read_bytes(q, tmpbuf, s);
+ t = qcam_read_bytes(qcam, tmpbuf, s);
if (outptr < len) {
size_t sz = len - outptr;
@@ -432,10 +448,10 @@
len = outptr;
if (wantlen) {
- printk(KERN_ERR "qcam: short read.\n");
+ v4l2_err(v4l2_dev, "short read.\n");
if (is_bi_dir)
- parport_data_forward(q->pport);
- qc_setup(q);
+ parport_data_forward(qcam->pport);
+ qc_setup(qcam);
return len;
}
@@ -443,49 +459,49 @@
int l;
do {
- l = qcam_read_bytes(q, tmpbuf, 3);
+ l = qcam_read_bytes(qcam, tmpbuf, 3);
cond_resched();
} while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e));
if (force_rgb) {
if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
- printk(KERN_ERR "qcam: bad EOF\n");
+ v4l2_err(v4l2_dev, "bad EOF\n");
} else {
if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
- printk(KERN_ERR "qcam: bad EOF\n");
+ v4l2_err(v4l2_dev, "bad EOF\n");
}
- qcam_set_ack(q, 0);
- if (qcam_await_ready1(q, 1)) {
- printk(KERN_ERR "qcam: no ack after EOF\n");
- parport_data_forward(q->pport);
- qc_setup(q);
+ qcam_set_ack(qcam, 0);
+ if (qcam_await_ready1(qcam, 1)) {
+ v4l2_err(v4l2_dev, "no ack after EOF\n");
+ parport_data_forward(qcam->pport);
+ qc_setup(qcam);
return len;
}
- parport_data_forward(q->pport);
+ parport_data_forward(qcam->pport);
mdelay(3);
- qcam_set_ack(q, 1);
- if (qcam_await_ready1(q, 0)) {
- printk(KERN_ERR "qcam: no ack to port turnaround\n");
- qc_setup(q);
+ qcam_set_ack(qcam, 1);
+ if (qcam_await_ready1(qcam, 0)) {
+ v4l2_err(v4l2_dev, "no ack to port turnaround\n");
+ qc_setup(qcam);
return len;
}
} else {
int l;
do {
- l = qcam_read_bytes(q, tmpbuf, 1);
+ l = qcam_read_bytes(qcam, tmpbuf, 1);
cond_resched();
} while (l && tmpbuf[0] == 0x7e);
- l = qcam_read_bytes(q, tmpbuf + 1, 2);
+ l = qcam_read_bytes(qcam, tmpbuf + 1, 2);
if (force_rgb) {
if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
- printk(KERN_ERR "qcam: bad EOF\n");
+ v4l2_err(v4l2_dev, "bad EOF\n");
} else {
if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
- printk(KERN_ERR "qcam: bad EOF\n");
+ v4l2_err(v4l2_dev, "bad EOF\n");
}
}
- qcam_write_data(q, 0);
+ qcam_write_data(qcam, 0);
return len;
}
@@ -493,184 +509,202 @@
* Video4linux interfacing
*/
-static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static int qcam_querycap(struct file *file, void *priv,
+ struct v4l2_capability *vcap)
{
- struct video_device *dev = video_devdata(file);
- struct qcam_device *qcam = (struct qcam_device *)dev;
+ struct qcam *qcam = video_drvdata(file);
- switch (cmd) {
- case VIDIOCGCAP:
- {
- struct video_capability *b = arg;
-
- strcpy(b->name, "Quickcam");
- b->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
- b->channels = 1;
- b->audios = 0;
- b->maxwidth = 320;
- b->maxheight = 240;
- b->minwidth = 80;
- b->minheight = 60;
- return 0;
- }
- case VIDIOCGCHAN:
- {
- struct video_channel *v = arg;
-
- if (v->channel != 0)
- return -EINVAL;
- v->flags = 0;
- v->tuners = 0;
- /* Good question.. its composite or SVHS so.. */
- v->type = VIDEO_TYPE_CAMERA;
- strcpy(v->name, "Camera");
- return 0;
- }
- case VIDIOCSCHAN:
- {
- struct video_channel *v = arg;
-
- if (v->channel != 0)
- return -EINVAL;
- return 0;
- }
- case VIDIOCGTUNER:
- {
- struct video_tuner *v = arg;
-
- if (v->tuner)
- return -EINVAL;
- memset(v, 0, sizeof(*v));
- strcpy(v->name, "Format");
- v->mode = VIDEO_MODE_AUTO;
- return 0;
- }
- case VIDIOCSTUNER:
- {
- struct video_tuner *v = arg;
-
- if (v->tuner)
- return -EINVAL;
- if (v->mode != VIDEO_MODE_AUTO)
- return -EINVAL;
- return 0;
- }
- case VIDIOCGPICT:
- {
- struct video_picture *p = arg;
-
- p->colour = 0x8000;
- p->hue = 0x8000;
- p->brightness = qcam->brightness << 8;
- p->contrast = qcam->contrast << 8;
- p->whiteness = qcam->whitebal << 8;
- p->depth = 24;
- p->palette = VIDEO_PALETTE_RGB24;
- return 0;
- }
- case VIDIOCSPICT:
- {
- struct video_picture *p = arg;
-
- /*
- * Sanity check args
- */
- if (p->depth != 24 || p->palette != VIDEO_PALETTE_RGB24)
- return -EINVAL;
-
- /*
- * Now load the camera.
- */
- qcam->brightness = p->brightness >> 8;
- qcam->contrast = p->contrast >> 8;
- qcam->whitebal = p->whiteness >> 8;
-
- mutex_lock(&qcam->lock);
- parport_claim_or_block(qcam->pdev);
- qc_setup(qcam);
- parport_release(qcam->pdev);
- mutex_unlock(&qcam->lock);
- return 0;
- }
- case VIDIOCSWIN:
- {
- struct video_window *vw = arg;
-
- if (vw->flags)
- return -EINVAL;
- if (vw->clipcount)
- return -EINVAL;
- if (vw->height < 60 || vw->height > 240)
- return -EINVAL;
- if (vw->width < 80 || vw->width > 320)
- return -EINVAL;
-
- qcam->width = 80;
- qcam->height = 60;
- qcam->mode = QC_DECIMATION_4;
-
- if (vw->width >= 160 && vw->height >= 120) {
- qcam->width = 160;
- qcam->height = 120;
- qcam->mode = QC_DECIMATION_2;
- }
- if (vw->width >= 320 && vw->height >= 240) {
- qcam->width = 320;
- qcam->height = 240;
- qcam->mode = QC_DECIMATION_1;
- }
- qcam->mode |= QC_MILLIONS;
-#if 0
- if (vw->width >= 640 && vw->height >= 480) {
- qcam->width = 640;
- qcam->height = 480;
- qcam->mode = QC_BILLIONS | QC_DECIMATION_1;
- }
-#endif
- /* Ok we figured out what to use from our
- wide choice */
- mutex_lock(&qcam->lock);
- parport_claim_or_block(qcam->pdev);
- qc_setup(qcam);
- parport_release(qcam->pdev);
- mutex_unlock(&qcam->lock);
- return 0;
- }
- case VIDIOCGWIN:
- {
- struct video_window *vw = arg;
- memset(vw, 0, sizeof(*vw));
- vw->width = qcam->width;
- vw->height = qcam->height;
- return 0;
- }
- case VIDIOCKEY:
- return 0;
- case VIDIOCCAPTURE:
- case VIDIOCGFBUF:
- case VIDIOCSFBUF:
- case VIDIOCGFREQ:
- case VIDIOCSFREQ:
- case VIDIOCGAUDIO:
- case VIDIOCSAUDIO:
- return -EINVAL;
- default:
- return -ENOIOCTLCMD;
- }
+ strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver));
+ strlcpy(vcap->card, "Color Quickcam", sizeof(vcap->card));
+ strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info));
+ vcap->version = KERNEL_VERSION(0, 0, 3);
+ vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
return 0;
}
-static long qcam_ioctl(struct file *file,
- unsigned int cmd, unsigned long arg)
+static int qcam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
{
- return video_usercopy(file, cmd, arg, qcam_do_ioctl);
+ if (vin->index > 0)
+ return -EINVAL;
+ strlcpy(vin->name, "Camera", sizeof(vin->name));
+ vin->type = V4L2_INPUT_TYPE_CAMERA;
+ vin->audioset = 0;
+ vin->tuner = 0;
+ vin->std = 0;
+ vin->status = 0;
+ return 0;
+}
+
+static int qcam_g_input(struct file *file, void *fh, unsigned int *inp)
+{
+ *inp = 0;
+ return 0;
+}
+
+static int qcam_s_input(struct file *file, void *fh, unsigned int inp)
+{
+ return (inp > 0) ? -EINVAL : 0;
+}
+
+static int qcam_queryctrl(struct file *file, void *priv,
+ struct v4l2_queryctrl *qc)
+{
+ switch (qc->id) {
+ case V4L2_CID_BRIGHTNESS:
+ return v4l2_ctrl_query_fill(qc, 0, 255, 1, 240);
+ case V4L2_CID_CONTRAST:
+ return v4l2_ctrl_query_fill(qc, 0, 255, 1, 192);
+ case V4L2_CID_GAMMA:
+ return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
+ }
+ return -EINVAL;
+}
+
+static int qcam_g_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct qcam *qcam = video_drvdata(file);
+ int ret = 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ ctrl->value = qcam->brightness;
+ break;
+ case V4L2_CID_CONTRAST:
+ ctrl->value = qcam->contrast;
+ break;
+ case V4L2_CID_GAMMA:
+ ctrl->value = qcam->whitebal;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int qcam_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct qcam *qcam = video_drvdata(file);
+ int ret = 0;
+
+ mutex_lock(&qcam->lock);
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ qcam->brightness = ctrl->value;
+ break;
+ case V4L2_CID_CONTRAST:
+ qcam->contrast = ctrl->value;
+ break;
+ case V4L2_CID_GAMMA:
+ qcam->whitebal = ctrl->value;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ if (ret == 0) {
+ parport_claim_or_block(qcam->pdev);
+ qc_setup(qcam);
+ parport_release(qcam->pdev);
+ }
+ mutex_unlock(&qcam->lock);
+ return ret;
+}
+
+static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+ struct qcam *qcam = video_drvdata(file);
+ struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+ pix->width = qcam->width;
+ pix->height = qcam->height;
+ pix->pixelformat = V4L2_PIX_FMT_RGB24;
+ pix->field = V4L2_FIELD_NONE;
+ pix->bytesperline = 3 * qcam->width;
+ pix->sizeimage = 3 * qcam->width * qcam->height;
+ /* Just a guess */
+ pix->colorspace = V4L2_COLORSPACE_SRGB;
+ return 0;
+}
+
+static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+ struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+ if (pix->height < 60 || pix->width < 80) {
+ pix->height = 60;
+ pix->width = 80;
+ } else if (pix->height < 120 || pix->width < 160) {
+ pix->height = 120;
+ pix->width = 160;
+ } else {
+ pix->height = 240;
+ pix->width = 320;
+ }
+ pix->pixelformat = V4L2_PIX_FMT_RGB24;
+ pix->field = V4L2_FIELD_NONE;
+ pix->bytesperline = 3 * pix->width;
+ pix->sizeimage = 3 * pix->width * pix->height;
+ /* Just a guess */
+ pix->colorspace = V4L2_COLORSPACE_SRGB;
+ return 0;
+}
+
+static int qcam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+ struct qcam *qcam = video_drvdata(file);
+ struct v4l2_pix_format *pix = &fmt->fmt.pix;
+ int ret = qcam_try_fmt_vid_cap(file, fh, fmt);
+
+ if (ret)
+ return ret;
+ switch (pix->height) {
+ case 60:
+ qcam->mode = QC_DECIMATION_4;
+ break;
+ case 120:
+ qcam->mode = QC_DECIMATION_2;
+ break;
+ default:
+ qcam->mode = QC_DECIMATION_1;
+ break;
+ }
+
+ mutex_lock(&qcam->lock);
+ qcam->mode |= QC_MILLIONS;
+ qcam->height = pix->height;
+ qcam->width = pix->width;
+ parport_claim_or_block(qcam->pdev);
+ qc_setup(qcam);
+ parport_release(qcam->pdev);
+ mutex_unlock(&qcam->lock);
+ return 0;
+}
+
+static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
+{
+ static struct v4l2_fmtdesc formats[] = {
+ { 0, 0, 0,
+ "RGB 8:8:8", V4L2_PIX_FMT_RGB24,
+ { 0, 0, 0, 0 }
+ },
+ };
+ enum v4l2_buf_type type = fmt->type;
+
+ if (fmt->index > 0)
+ return -EINVAL;
+
+ *fmt = formats[fmt->index];
+ fmt->type = type;
+ return 0;
}
static ssize_t qcam_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- struct video_device *v = video_devdata(file);
- struct qcam_device *qcam = (struct qcam_device *)v;
+ struct qcam *qcam = video_drvdata(file);
int len;
mutex_lock(&qcam->lock);
@@ -682,81 +716,80 @@
return len;
}
-static int qcam_exclusive_open(struct file *file)
-{
- struct video_device *dev = video_devdata(file);
- struct qcam_device *qcam = (struct qcam_device *)dev;
-
- return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0;
-}
-
-static int qcam_exclusive_release(struct file *file)
-{
- struct video_device *dev = video_devdata(file);
- struct qcam_device *qcam = (struct qcam_device *)dev;
-
- clear_bit(0, &qcam->in_use);
- return 0;
-}
-
-/* video device template */
static const struct v4l2_file_operations qcam_fops = {
.owner = THIS_MODULE,
- .open = qcam_exclusive_open,
- .release = qcam_exclusive_release,
- .ioctl = qcam_ioctl,
+ .ioctl = video_ioctl2,
.read = qcam_read,
};
-static struct video_device qcam_template = {
- .name = "Colour QuickCam",
- .fops = &qcam_fops,
- .release = video_device_release_empty,
+static const struct v4l2_ioctl_ops qcam_ioctl_ops = {
+ .vidioc_querycap = qcam_querycap,
+ .vidioc_g_input = qcam_g_input,
+ .vidioc_s_input = qcam_s_input,
+ .vidioc_enum_input = qcam_enum_input,
+ .vidioc_queryctrl = qcam_queryctrl,
+ .vidioc_g_ctrl = qcam_g_ctrl,
+ .vidioc_s_ctrl = qcam_s_ctrl,
+ .vidioc_enum_fmt_vid_cap = qcam_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = qcam_g_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = qcam_s_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = qcam_try_fmt_vid_cap,
};
/* Initialize the QuickCam driver control structure. */
-static struct qcam_device *qcam_init(struct parport *port)
+static struct qcam *qcam_init(struct parport *port)
{
- struct qcam_device *q;
+ struct qcam *qcam;
+ struct v4l2_device *v4l2_dev;
- q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL);
- if (q == NULL)
+ qcam = kzalloc(sizeof(*qcam), GFP_KERNEL);
+ if (qcam == NULL)
return NULL;
- q->pport = port;
- q->pdev = parport_register_device(port, "c-qcam", NULL, NULL,
- NULL, 0, NULL);
+ v4l2_dev = &qcam->v4l2_dev;
+ strlcpy(v4l2_dev->name, "c-qcam", sizeof(v4l2_dev->name));
- q->bidirectional = (q->pport->modes & PARPORT_MODE_TRISTATE) ? 1 : 0;
-
- if (q->pdev == NULL) {
- printk(KERN_ERR "c-qcam: couldn't register for %s.\n",
- port->name);
- kfree(q);
+ if (v4l2_device_register(NULL, v4l2_dev) < 0) {
+ v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
return NULL;
}
- memcpy(&q->vdev, &qcam_template, sizeof(qcam_template));
+ qcam->pport = port;
+ qcam->pdev = parport_register_device(port, "c-qcam", NULL, NULL,
+ NULL, 0, NULL);
- mutex_init(&q->lock);
- q->width = q->ccd_width = 320;
- q->height = q->ccd_height = 240;
- q->mode = QC_MILLIONS | QC_DECIMATION_1;
- q->contrast = 192;
- q->brightness = 240;
- q->whitebal = 128;
- q->top = 1;
- q->left = 14;
- return q;
+ qcam->bidirectional = (qcam->pport->modes & PARPORT_MODE_TRISTATE) ? 1 : 0;
+
+ if (qcam->pdev == NULL) {
+ v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name);
+ kfree(qcam);
+ return NULL;
+ }
+
+ strlcpy(qcam->vdev.name, "Colour QuickCam", sizeof(qcam->vdev.name));
+ qcam->vdev.v4l2_dev = v4l2_dev;
+ qcam->vdev.fops = &qcam_fops;
+ qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
+ qcam->vdev.release = video_device_release_empty;
+ video_set_drvdata(&qcam->vdev, qcam);
+
+ mutex_init(&qcam->lock);
+ qcam->width = qcam->ccd_width = 320;
+ qcam->height = qcam->ccd_height = 240;
+ qcam->mode = QC_MILLIONS | QC_DECIMATION_1;
+ qcam->contrast = 192;
+ qcam->brightness = 240;
+ qcam->whitebal = 128;
+ qcam->top = 1;
+ qcam->left = 14;
+ return qcam;
}
-static struct qcam_device *qcams[MAX_CAMS];
-static unsigned int num_cams;
-
static int init_cqcam(struct parport *port)
{
- struct qcam_device *qcam;
+ struct qcam *qcam;
+ struct v4l2_device *v4l2_dev;
if (parport[0] != -1) {
/* The user gave specific instructions */
@@ -777,6 +810,8 @@
if (qcam == NULL)
return -ENODEV;
+ v4l2_dev = &qcam->v4l2_dev;
+
parport_claim_or_block(qcam->pdev);
qc_reset(qcam);
@@ -793,14 +828,14 @@
parport_release(qcam->pdev);
if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
- printk(KERN_ERR "Unable to register Colour QuickCam on %s\n",
+ v4l2_err(v4l2_dev, "Unable to register Colour QuickCam on %s\n",
qcam->pport->name);
parport_unregister_device(qcam->pdev);
kfree(qcam);
return -ENODEV;
}
- printk(KERN_INFO "%s: Colour QuickCam found on %s\n",
+ v4l2_info(v4l2_dev, "%s: Colour QuickCam found on %s\n",
video_device_node_name(&qcam->vdev), qcam->pport->name);
qcams[num_cams++] = qcam;
@@ -808,7 +843,7 @@
return 0;
}
-static void close_cqcam(struct qcam_device *qcam)
+static void close_cqcam(struct qcam *qcam)
{
video_unregister_device(&qcam->vdev);
parport_unregister_device(qcam->pdev);
@@ -833,7 +868,7 @@
static int __init cqcam_init(void)
{
- printk(BANNER "\n");
+ printk(KERN_INFO BANNER "\n");
return parport_register_driver(&cqcam_driver);
}
@@ -852,14 +887,5 @@
MODULE_DESCRIPTION(BANNER);
MODULE_LICENSE("GPL");
-/* FIXME: parport=auto would never have worked, surely? --RR */
-MODULE_PARM_DESC(parport, "parport=<auto|n[,n]...> for port detection method\n"
- "probe=<0|1|2> for camera detection method\n"
- "force_rgb=<0|1> for RGB data format (default BGR)");
-module_param_array(parport, int, NULL, 0);
-module_param(probe, int, 0);
-module_param(force_rgb, bool, 0);
-module_param(video_nr, int, 0);
-
module_init(cqcam_init);
module_exit(cqcam_cleanup);
diff --git a/drivers/media/video/cx18/cx18-alsa-main.c b/drivers/media/video/cx18/cx18-alsa-main.c
index b5d7cbf..d50d69d 100644
--- a/drivers/media/video/cx18/cx18-alsa-main.c
+++ b/drivers/media/video/cx18/cx18-alsa-main.c
@@ -1,7 +1,7 @@
/*
* ALSA interface to cx18 PCM capture streams
*
- * Copyright (C) 2009 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
* Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com>
*
* Portions of this work were sponsored by ONELAN Limited.
diff --git a/drivers/media/video/cx18/cx18-alsa-mixer.c b/drivers/media/video/cx18/cx18-alsa-mixer.c
index ef21114..341bddc 100644
--- a/drivers/media/video/cx18/cx18-alsa-mixer.c
+++ b/drivers/media/video/cx18/cx18-alsa-mixer.c
@@ -2,7 +2,7 @@
* ALSA mixer controls for the
* ALSA interface to cx18 PCM capture streams
*
- * Copyright (C) 2009 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx18/cx18-alsa-mixer.h b/drivers/media/video/cx18/cx18-alsa-mixer.h
index 2d418db..ec92387 100644
--- a/drivers/media/video/cx18/cx18-alsa-mixer.h
+++ b/drivers/media/video/cx18/cx18-alsa-mixer.h
@@ -2,7 +2,7 @@
* ALSA mixer controls for the
* ALSA interface to cx18 PCM capture streams
*
- * Copyright (C) 2009 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx18/cx18-alsa-pcm.c b/drivers/media/video/cx18/cx18-alsa-pcm.c
index 2bd312d..8f55692 100644
--- a/drivers/media/video/cx18/cx18-alsa-pcm.c
+++ b/drivers/media/video/cx18/cx18-alsa-pcm.c
@@ -2,7 +2,7 @@
* ALSA PCM device for the
* ALSA interface to cx18 PCM capture streams
*
- * Copyright (C) 2009 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
* Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com>
*
* Portions of this work were sponsored by ONELAN Limited.
diff --git a/drivers/media/video/cx18/cx18-alsa-pcm.h b/drivers/media/video/cx18/cx18-alsa-pcm.h
index 325662c..d26e51f 100644
--- a/drivers/media/video/cx18/cx18-alsa-pcm.h
+++ b/drivers/media/video/cx18/cx18-alsa-pcm.h
@@ -2,7 +2,7 @@
* ALSA PCM device for the
* ALSA interface to cx18 PCM capture streams
*
- * Copyright (C) 2009 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx18/cx18-alsa.h b/drivers/media/video/cx18/cx18-alsa.h
index 88a1cde..447da37 100644
--- a/drivers/media/video/cx18/cx18-alsa.h
+++ b/drivers/media/video/cx18/cx18-alsa.h
@@ -1,7 +1,7 @@
/*
* ALSA interface to cx18 PCM capture streams
*
- * Copyright (C) 2009 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx18/cx18-av-audio.c b/drivers/media/video/cx18/cx18-av-audio.c
index 9e30983..43d09a2 100644
--- a/drivers/media/video/cx18/cx18-av-audio.c
+++ b/drivers/media/video/cx18/cx18-av-audio.c
@@ -4,7 +4,7 @@
* Derived from cx25840-audio.c
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c
index 0e5006b..a41951c 100644
--- a/drivers/media/video/cx18/cx18-av-core.c
+++ b/drivers/media/video/cx18/cx18-av-core.c
@@ -4,7 +4,7 @@
* Derived from cx25840-core.c
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -1021,86 +1021,74 @@
return -EINVAL;
}
-static int cx18_av_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
-{
- if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
- return -EINVAL;
- return cx18_av_g_sliced_fmt(sd, &fmt->fmt.sliced);
-}
-
-static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+static int cx18_av_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
{
struct cx18_av_state *state = to_cx18_av_state(sd);
struct cx18 *cx = v4l2_get_subdevdata(sd);
-
- struct v4l2_pix_format *pix;
int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
int is_50Hz = !(state->std & V4L2_STD_525_60);
- switch (fmt->type) {
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- pix = &(fmt->fmt.pix);
-
- Vsrc = (cx18_av_read(cx, 0x476) & 0x3f) << 4;
- Vsrc |= (cx18_av_read(cx, 0x475) & 0xf0) >> 4;
-
- Hsrc = (cx18_av_read(cx, 0x472) & 0x3f) << 4;
- Hsrc |= (cx18_av_read(cx, 0x471) & 0xf0) >> 4;
-
- /*
- * This adjustment reflects the excess of vactive, set in
- * cx18_av_std_setup(), above standard values:
- *
- * 480 + 1 for 60 Hz systems
- * 576 + 3 for 50 Hz systems
- */
- Vlines = pix->height + (is_50Hz ? 3 : 1);
-
- /*
- * Invalid height and width scaling requests are:
- * 1. width less than 1/16 of the source width
- * 2. width greater than the source width
- * 3. height less than 1/8 of the source height
- * 4. height greater than the source height
- */
- if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) ||
- (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
- CX18_ERR_DEV(sd, "%dx%d is not a valid size!\n",
- pix->width, pix->height);
- return -ERANGE;
- }
-
- HSC = (Hsrc * (1 << 20)) / pix->width - (1 << 20);
- VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
- VSC &= 0x1fff;
-
- if (pix->width >= 385)
- filter = 0;
- else if (pix->width > 192)
- filter = 1;
- else if (pix->width > 96)
- filter = 2;
- else
- filter = 3;
-
- CX18_DEBUG_INFO_DEV(sd,
- "decoder set size %dx%d -> scale %ux%u\n",
- pix->width, pix->height, HSC, VSC);
-
- /* HSCALE=HSC */
- cx18_av_write(cx, 0x418, HSC & 0xff);
- cx18_av_write(cx, 0x419, (HSC >> 8) & 0xff);
- cx18_av_write(cx, 0x41a, HSC >> 16);
- /* VSCALE=VSC */
- cx18_av_write(cx, 0x41c, VSC & 0xff);
- cx18_av_write(cx, 0x41d, VSC >> 8);
- /* VS_INTRLACE=1 VFILT=filter */
- cx18_av_write(cx, 0x41e, 0x8 | filter);
- break;
-
- default:
+ if (fmt->code != V4L2_MBUS_FMT_FIXED)
return -EINVAL;
+
+ fmt->field = V4L2_FIELD_INTERLACED;
+ fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+ Vsrc = (cx18_av_read(cx, 0x476) & 0x3f) << 4;
+ Vsrc |= (cx18_av_read(cx, 0x475) & 0xf0) >> 4;
+
+ Hsrc = (cx18_av_read(cx, 0x472) & 0x3f) << 4;
+ Hsrc |= (cx18_av_read(cx, 0x471) & 0xf0) >> 4;
+
+ /*
+ * This adjustment reflects the excess of vactive, set in
+ * cx18_av_std_setup(), above standard values:
+ *
+ * 480 + 1 for 60 Hz systems
+ * 576 + 3 for 50 Hz systems
+ */
+ Vlines = fmt->height + (is_50Hz ? 3 : 1);
+
+ /*
+ * Invalid height and width scaling requests are:
+ * 1. width less than 1/16 of the source width
+ * 2. width greater than the source width
+ * 3. height less than 1/8 of the source height
+ * 4. height greater than the source height
+ */
+ if ((fmt->width * 16 < Hsrc) || (Hsrc < fmt->width) ||
+ (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
+ CX18_ERR_DEV(sd, "%dx%d is not a valid size!\n",
+ fmt->width, fmt->height);
+ return -ERANGE;
}
+
+ HSC = (Hsrc * (1 << 20)) / fmt->width - (1 << 20);
+ VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
+ VSC &= 0x1fff;
+
+ if (fmt->width >= 385)
+ filter = 0;
+ else if (fmt->width > 192)
+ filter = 1;
+ else if (fmt->width > 96)
+ filter = 2;
+ else
+ filter = 3;
+
+ CX18_DEBUG_INFO_DEV(sd,
+ "decoder set size %dx%d -> scale %ux%u\n",
+ fmt->width, fmt->height, HSC, VSC);
+
+ /* HSCALE=HSC */
+ cx18_av_write(cx, 0x418, HSC & 0xff);
+ cx18_av_write(cx, 0x419, (HSC >> 8) & 0xff);
+ cx18_av_write(cx, 0x41a, HSC >> 16);
+ /* VSCALE=VSC */
+ cx18_av_write(cx, 0x41c, VSC & 0xff);
+ cx18_av_write(cx, 0x41d, VSC >> 8);
+ /* VS_INTRLACE=1 VFILT=filter */
+ cx18_av_write(cx, 0x41e, 0x8 | filter);
return 0;
}
@@ -1398,8 +1386,7 @@
static const struct v4l2_subdev_video_ops cx18_av_video_ops = {
.s_routing = cx18_av_s_video_routing,
.s_stream = cx18_av_s_stream,
- .g_fmt = cx18_av_g_fmt,
- .s_fmt = cx18_av_s_fmt,
+ .s_mbus_fmt = cx18_av_s_mbus_fmt,
};
static const struct v4l2_subdev_vbi_ops cx18_av_vbi_ops = {
diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h
index c106967..1956991 100644
--- a/drivers/media/video/cx18/cx18-av-core.h
+++ b/drivers/media/video/cx18/cx18-av-core.h
@@ -4,7 +4,7 @@
* Derived from cx25840-core.h
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
diff --git a/drivers/media/video/cx18/cx18-av-firmware.c b/drivers/media/video/cx18/cx18-av-firmware.c
index b9e8cc5..280aa4d 100644
--- a/drivers/media/video/cx18/cx18-av-firmware.c
+++ b/drivers/media/video/cx18/cx18-av-firmware.c
@@ -2,7 +2,7 @@
* cx18 ADEC firmware functions
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c
index 74e122b..6b805af 100644
--- a/drivers/media/video/cx18/cx18-cards.c
+++ b/drivers/media/video/cx18/cx18-cards.c
@@ -4,7 +4,7 @@
* Derived from ivtv-cards.c
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h
index 796e517..3e75006 100644
--- a/drivers/media/video/cx18/cx18-cards.h
+++ b/drivers/media/video/cx18/cx18-cards.h
@@ -4,7 +4,7 @@
* Derived from ivtv-cards.c
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c
index 4b4b465..67043c7 100644
--- a/drivers/media/video/cx18/cx18-controls.c
+++ b/drivers/media/video/cx18/cx18-controls.c
@@ -297,14 +297,13 @@
if (p.video_encoding != cx->params.video_encoding) {
int is_mpeg1 = p.video_encoding ==
V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
- struct v4l2_format fmt;
+ struct v4l2_mbus_framefmt fmt;
/* fix videodecoder resolution */
- fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- fmt.fmt.pix.width = cx->params.width
- / (is_mpeg1 ? 2 : 1);
- fmt.fmt.pix.height = cx->params.height;
- v4l2_subdev_call(cx->sd_av, video, s_fmt, &fmt);
+ fmt.width = cx->params.width / (is_mpeg1 ? 2 : 1);
+ fmt.height = cx->params.height;
+ fmt.code = V4L2_MBUS_FMT_FIXED;
+ v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &fmt);
}
priv.cx = cx;
priv.s = &cx->streams[id->type];
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
index c95a86b..df60f27 100644
--- a/drivers/media/video/cx18/cx18-driver.c
+++ b/drivers/media/video/cx18/cx18-driver.c
@@ -4,7 +4,7 @@
* Derived from ivtv-driver.c
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
index b9728e8..9bc51a9 100644
--- a/drivers/media/video/cx18/cx18-driver.h
+++ b/drivers/media/video/cx18/cx18-driver.h
@@ -4,7 +4,7 @@
* Derived from ivtv-driver.h
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c
index 0ae2c2e..6d19f04 100644
--- a/drivers/media/video/cx18/cx18-dvb.c
+++ b/drivers/media/video/cx18/cx18-dvb.c
@@ -2,7 +2,7 @@
* cx18 functions for DVB support
*
* Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c
index e12a150..9f23b90 100644
--- a/drivers/media/video/cx18/cx18-fileops.c
+++ b/drivers/media/video/cx18/cx18-fileops.c
@@ -4,7 +4,7 @@
* Derived from ivtv-fileops.c
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx18/cx18-firmware.c b/drivers/media/video/cx18/cx18-firmware.c
index 83cd559..1b3fb50 100644
--- a/drivers/media/video/cx18/cx18-firmware.c
+++ b/drivers/media/video/cx18/cx18-firmware.c
@@ -2,7 +2,7 @@
* cx18 firmware functions
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c
index 86a204b..5374aeb 100644
--- a/drivers/media/video/cx18/cx18-gpio.c
+++ b/drivers/media/video/cx18/cx18-gpio.c
@@ -4,7 +4,7 @@
* Derived from ivtv-gpio.c
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx18/cx18-gpio.h b/drivers/media/video/cx18/cx18-gpio.h
index f9a5ca3..4aea2ef 100644
--- a/drivers/media/video/cx18/cx18-gpio.h
+++ b/drivers/media/video/cx18/cx18-gpio.h
@@ -4,7 +4,7 @@
* Derived from ivtv-gpio.h
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c
index cfa1f28..809f7d3 100644
--- a/drivers/media/video/cx18/cx18-i2c.c
+++ b/drivers/media/video/cx18/cx18-i2c.c
@@ -4,7 +4,7 @@
* Derived from ivtv-i2c.c
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx18/cx18-io.c b/drivers/media/video/cx18/cx18-io.c
index ec5b3d7..49b9dbd 100644
--- a/drivers/media/video/cx18/cx18-io.c
+++ b/drivers/media/video/cx18/cx18-io.c
@@ -2,7 +2,7 @@
* cx18 driver PCI memory mapped IO access routines
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx18/cx18-io.h b/drivers/media/video/cx18/cx18-io.h
index 2635b3a..18974d8 100644
--- a/drivers/media/video/cx18/cx18-io.h
+++ b/drivers/media/video/cx18/cx18-io.h
@@ -2,7 +2,7 @@
* cx18 driver PCI memory mapped IO access routines
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* 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
@@ -28,7 +28,7 @@
/*
* Readback and retry of MMIO access for reliability:
* The concept was suggested by Steve Toth <stoth@linuxtv.org>.
- * The implmentation is the fault of Andy Walls <awalls@radix.net>.
+ * The implmentation is the fault of Andy Walls <awalls@md.metrocast.net>.
*
* *write* functions are implied to retry the mmio unless suffixed with _noretry
* *read* functions never retry the mmio (it never helps to do so)
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c
index 2530fc5..20eaf38 100644
--- a/drivers/media/video/cx18/cx18-ioctl.c
+++ b/drivers/media/video/cx18/cx18-ioctl.c
@@ -4,7 +4,7 @@
* Derived from ivtv-ioctl.c
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* 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
@@ -274,6 +274,7 @@
{
struct cx18_open_id *id = fh;
struct cx18 *cx = id->cx;
+ struct v4l2_mbus_framefmt mbus_fmt;
int ret;
int w, h;
@@ -293,9 +294,10 @@
if (atomic_read(&cx->ana_capturing) > 0)
return -EBUSY;
- cx->params.width = w;
- cx->params.height = h;
- v4l2_subdev_call(cx->sd_av, video, s_fmt, fmt);
+ mbus_fmt.width = cx->params.width = w;
+ mbus_fmt.height = cx->params.height = h;
+ mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
+ v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &mbus_fmt);
return cx18_g_fmt_vid_cap(file, fh, fmt);
}
diff --git a/drivers/media/video/cx18/cx18-ioctl.h b/drivers/media/video/cx18/cx18-ioctl.h
index e2ca0d1..dcb2559 100644
--- a/drivers/media/video/cx18/cx18-ioctl.h
+++ b/drivers/media/video/cx18/cx18-ioctl.h
@@ -4,7 +4,7 @@
* Derived from ivtv-ioctl.h
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx18/cx18-irq.c b/drivers/media/video/cx18/cx18-irq.c
index af2f504..80edfe9 100644
--- a/drivers/media/video/cx18/cx18-irq.c
+++ b/drivers/media/video/cx18/cx18-irq.c
@@ -2,7 +2,7 @@
* cx18 interrupt handling
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx18/cx18-irq.h b/drivers/media/video/cx18/cx18-irq.h
index 91f0b52..30e7eaf 100644
--- a/drivers/media/video/cx18/cx18-irq.h
+++ b/drivers/media/video/cx18/cx18-irq.h
@@ -2,7 +2,7 @@
* cx18 interrupt handling
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c
index 6dcce29..956aa19 100644
--- a/drivers/media/video/cx18/cx18-mailbox.c
+++ b/drivers/media/video/cx18/cx18-mailbox.c
@@ -2,7 +2,7 @@
* cx18 mailbox functions
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx18/cx18-mailbox.h b/drivers/media/video/cx18/cx18-mailbox.h
index 33a3491..077952f 100644
--- a/drivers/media/video/cx18/cx18-mailbox.h
+++ b/drivers/media/video/cx18/cx18-mailbox.h
@@ -2,7 +2,7 @@
* cx18 mailbox functions
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c
index aefc8c8..8884537 100644
--- a/drivers/media/video/cx18/cx18-queue.c
+++ b/drivers/media/video/cx18/cx18-queue.c
@@ -4,7 +4,7 @@
* Derived from ivtv-queue.c
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx18/cx18-queue.h b/drivers/media/video/cx18/cx18-queue.h
index 88a6d34..4201ddc 100644
--- a/drivers/media/video/cx18/cx18-queue.h
+++ b/drivers/media/video/cx18/cx18-queue.h
@@ -4,7 +4,7 @@
* Derived from ivtv-queue.h
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx18/cx18-scb.c b/drivers/media/video/cx18/cx18-scb.c
index 34b4d03..85cc596 100644
--- a/drivers/media/video/cx18/cx18-scb.c
+++ b/drivers/media/video/cx18/cx18-scb.c
@@ -2,7 +2,7 @@
* cx18 System Control Block initialization
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx18/cx18-scb.h b/drivers/media/video/cx18/cx18-scb.h
index 368f23d..0887765 100644
--- a/drivers/media/video/cx18/cx18-scb.h
+++ b/drivers/media/video/cx18/cx18-scb.h
@@ -2,7 +2,7 @@
* cx18 System Control Block initialization
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index f5c9126..9045f1e 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -4,7 +4,7 @@
* Derived from ivtv-streams.c
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx18/cx18-streams.h b/drivers/media/video/cx18/cx18-streams.h
index 0bff0fa..77412be 100644
--- a/drivers/media/video/cx18/cx18-streams.h
+++ b/drivers/media/video/cx18/cx18-streams.h
@@ -4,7 +4,7 @@
* Derived from ivtv-streams.h
*
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
- * Copyright (C) 2008 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c
index 2782709..e760145 100644
--- a/drivers/media/video/cx231xx/cx231xx-video.c
+++ b/drivers/media/video/cx231xx/cx231xx-video.c
@@ -993,6 +993,7 @@
struct cx231xx *dev = fh->dev;
int rc;
struct cx231xx_fmt *fmt;
+ struct v4l2_mbus_framefmt mbus_fmt;
rc = check_dev(dev);
if (rc < 0)
@@ -1026,7 +1027,9 @@
dev->format = fmt;
get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
- call_all(dev, video, s_fmt, f);
+ v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
+ call_all(dev, video, s_mbus_fmt, &mbus_fmt);
+ v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
/* Set the correct alternate setting for this resolution */
cx231xx_resolution_set(dev);
diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c
index 022b480..2bf44ef 100644
--- a/drivers/media/video/cx2341x.c
+++ b/drivers/media/video/cx2341x.c
@@ -1113,7 +1113,6 @@
void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix)
{
int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
- int temporal = p->video_temporal_filter;
/* Stream */
printk(KERN_INFO "%s: Stream: %s",
@@ -1179,14 +1178,11 @@
V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
p->video_spatial_filter);
- if (p->width != 720 || p->height != (p->is_50hz ? 576 : 480))
- temporal = 0;
-
printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
prefix,
cx2341x_menu_item(p,
V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
- temporal);
+ p->video_temporal_filter);
printk(KERN_INFO
"%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n",
prefix,
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c
index 9e14608..0a199d7 100644
--- a/drivers/media/video/cx23885/cx23885-dvb.c
+++ b/drivers/media/video/cx23885/cx23885-dvb.c
@@ -991,6 +991,8 @@
ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port,
&dev->pci->dev, adapter_nr, 0,
cx23885_dvb_fe_ioctl_override);
+ if (!ret)
+ return ret;
/* init CI & MAC */
switch (dev->board) {
diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c
index 4172cb3..d4746e0 100644
--- a/drivers/media/video/cx23885/cx23885-i2c.c
+++ b/drivers/media/video/cx23885/cx23885-i2c.c
@@ -365,7 +365,17 @@
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
- i2c_new_probed_device(&bus->i2c_adap, &info, addr_list);
+ /*
+ * We can't call i2c_new_probed_device() because it uses
+ * quick writes for probing and the IR receiver device only
+ * replies to reads.
+ */
+ if (i2c_smbus_xfer(&bus->i2c_adap, addr_list[0], 0,
+ I2C_SMBUS_READ, 0, I2C_SMBUS_QUICK,
+ NULL) >= 0) {
+ info.addr = addr_list[0];
+ i2c_new_device(&bus->i2c_adap, &info);
+ }
}
return bus->i2c_rc;
diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c
index 8d306d8..5de6ba9 100644
--- a/drivers/media/video/cx23885/cx23885-input.c
+++ b/drivers/media/video/cx23885/cx23885-input.c
@@ -5,7 +5,7 @@
*
* Most of this file is
*
- * Copyright (C) 2009 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
*
* However, the cx23885_input_{init,fini} functions contained herein are
* derived from Linux kernel files linux/media/video/.../...-input.c marked as:
diff --git a/drivers/media/video/cx23885/cx23885-input.h b/drivers/media/video/cx23885/cx23885-input.h
index 3572cb1..75ef15d 100644
--- a/drivers/media/video/cx23885/cx23885-input.h
+++ b/drivers/media/video/cx23885/cx23885-input.h
@@ -3,7 +3,7 @@
*
* Infrared remote control input device
*
- * Copyright (C) 2009 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
diff --git a/drivers/media/video/cx23885/cx23885-ioctl.c b/drivers/media/video/cx23885/cx23885-ioctl.c
index dfb4627..44812ca 100644
--- a/drivers/media/video/cx23885/cx23885-ioctl.c
+++ b/drivers/media/video/cx23885/cx23885-ioctl.c
@@ -3,7 +3,7 @@
*
* Various common ioctl() support functions
*
- * Copyright (c) 2009 Andy Walls <awalls@radix.net>
+ * Copyright (c) 2009 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx23885/cx23885-ioctl.h b/drivers/media/video/cx23885/cx23885-ioctl.h
index 80b0f49..315be0c 100644
--- a/drivers/media/video/cx23885/cx23885-ioctl.h
+++ b/drivers/media/video/cx23885/cx23885-ioctl.h
@@ -3,7 +3,7 @@
*
* Various common ioctl() support functions
*
- * Copyright (c) 2009 Andy Walls <awalls@radix.net>
+ * Copyright (c) 2009 Andy Walls <awalls@md.metrocast.net>
*
* 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
diff --git a/drivers/media/video/cx23885/cx23885-ir.c b/drivers/media/video/cx23885/cx23885-ir.c
index 6ae982c..9a677eb 100644
--- a/drivers/media/video/cx23885/cx23885-ir.c
+++ b/drivers/media/video/cx23885/cx23885-ir.c
@@ -3,7 +3,7 @@
*
* Infrared device support routines - non-input, non-vl42_subdev routines
*
- * Copyright (C) 2009 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
diff --git a/drivers/media/video/cx23885/cx23885-ir.h b/drivers/media/video/cx23885/cx23885-ir.h
index 9b8a6d5..0c9d8bd 100644
--- a/drivers/media/video/cx23885/cx23885-ir.h
+++ b/drivers/media/video/cx23885/cx23885-ir.h
@@ -3,7 +3,7 @@
*
* Infrared device support routines - non-input, non-vl42_subdev routines
*
- * Copyright (C) 2009 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c
index 543b854..4e44dcd 100644
--- a/drivers/media/video/cx23885/cx23885-video.c
+++ b/drivers/media/video/cx23885/cx23885-video.c
@@ -976,6 +976,7 @@
{
struct cx23885_fh *fh = priv;
struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+ struct v4l2_mbus_framefmt mbus_fmt;
int err;
dprintk(2, "%s()\n", __func__);
@@ -989,7 +990,9 @@
fh->vidq.field = f->fmt.pix.field;
dprintk(2, "%s() width=%d height=%d field=%d\n", __func__,
fh->width, fh->height, fh->vidq.field);
- call_all(dev, video, s_fmt, f);
+ v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
+ call_all(dev, video, s_mbus_fmt, &mbus_fmt);
+ v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
return 0;
}
diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/video/cx23885/cx23888-ir.c
index ad728d7..f63d378 100644
--- a/drivers/media/video/cx23885/cx23888-ir.c
+++ b/drivers/media/video/cx23885/cx23888-ir.c
@@ -3,7 +3,7 @@
*
* CX23888 Integrated Consumer Infrared Controller
*
- * Copyright (C) 2009 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
diff --git a/drivers/media/video/cx23885/cx23888-ir.h b/drivers/media/video/cx23885/cx23888-ir.h
index 3d446f9..d2de41c 100644
--- a/drivers/media/video/cx23885/cx23888-ir.h
+++ b/drivers/media/video/cx23885/cx23888-ir.h
@@ -3,7 +3,7 @@
*
* CX23888 Integrated Consumer Infrared Controller
*
- * Copyright (C) 2009 Andy Walls <awalls@radix.net>
+ * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index 8b6fb35..bb4872b 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -1014,75 +1014,59 @@
/* ----------------------------------------------------------------------- */
-static int cx25840_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
-{
- switch (fmt->type) {
- case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
- return cx25840_g_sliced_fmt(sd, &fmt->fmt.sliced);
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static int cx25840_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+static int cx25840_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
{
struct cx25840_state *state = to_state(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
- struct v4l2_pix_format *pix;
int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
int is_50Hz = !(state->std & V4L2_STD_525_60);
- switch (fmt->type) {
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- pix = &(fmt->fmt.pix);
-
- Vsrc = (cx25840_read(client, 0x476) & 0x3f) << 4;
- Vsrc |= (cx25840_read(client, 0x475) & 0xf0) >> 4;
-
- Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4;
- Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4;
-
- Vlines = pix->height + (is_50Hz ? 4 : 7);
-
- if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) ||
- (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
- v4l_err(client, "%dx%d is not a valid size!\n",
- pix->width, pix->height);
- return -ERANGE;
- }
-
- HSC = (Hsrc * (1 << 20)) / pix->width - (1 << 20);
- VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
- VSC &= 0x1fff;
-
- if (pix->width >= 385)
- filter = 0;
- else if (pix->width > 192)
- filter = 1;
- else if (pix->width > 96)
- filter = 2;
- else
- filter = 3;
-
- v4l_dbg(1, cx25840_debug, client, "decoder set size %dx%d -> scale %ux%u\n",
- pix->width, pix->height, HSC, VSC);
-
- /* HSCALE=HSC */
- cx25840_write(client, 0x418, HSC & 0xff);
- cx25840_write(client, 0x419, (HSC >> 8) & 0xff);
- cx25840_write(client, 0x41a, HSC >> 16);
- /* VSCALE=VSC */
- cx25840_write(client, 0x41c, VSC & 0xff);
- cx25840_write(client, 0x41d, VSC >> 8);
- /* VS_INTRLACE=1 VFILT=filter */
- cx25840_write(client, 0x41e, 0x8 | filter);
- break;
-
- default:
+ if (fmt->code != V4L2_MBUS_FMT_FIXED)
return -EINVAL;
+
+ fmt->field = V4L2_FIELD_INTERLACED;
+ fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+ Vsrc = (cx25840_read(client, 0x476) & 0x3f) << 4;
+ Vsrc |= (cx25840_read(client, 0x475) & 0xf0) >> 4;
+
+ Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4;
+ Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4;
+
+ Vlines = fmt->height + (is_50Hz ? 4 : 7);
+
+ if ((fmt->width * 16 < Hsrc) || (Hsrc < fmt->width) ||
+ (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
+ v4l_err(client, "%dx%d is not a valid size!\n",
+ fmt->width, fmt->height);
+ return -ERANGE;
}
+ HSC = (Hsrc * (1 << 20)) / fmt->width - (1 << 20);
+ VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
+ VSC &= 0x1fff;
+
+ if (fmt->width >= 385)
+ filter = 0;
+ else if (fmt->width > 192)
+ filter = 1;
+ else if (fmt->width > 96)
+ filter = 2;
+ else
+ filter = 3;
+
+ v4l_dbg(1, cx25840_debug, client, "decoder set size %dx%d -> scale %ux%u\n",
+ fmt->width, fmt->height, HSC, VSC);
+
+ /* HSCALE=HSC */
+ cx25840_write(client, 0x418, HSC & 0xff);
+ cx25840_write(client, 0x419, (HSC >> 8) & 0xff);
+ cx25840_write(client, 0x41a, HSC >> 16);
+ /* VSCALE=VSC */
+ cx25840_write(client, 0x41c, VSC & 0xff);
+ cx25840_write(client, 0x41d, VSC >> 8);
+ /* VS_INTRLACE=1 VFILT=filter */
+ cx25840_write(client, 0x41e, 0x8 | filter);
return 0;
}
@@ -1627,8 +1611,7 @@
static const struct v4l2_subdev_video_ops cx25840_video_ops = {
.s_routing = cx25840_s_video_routing,
- .g_fmt = cx25840_g_fmt,
- .s_fmt = cx25840_s_fmt,
+ .s_mbus_fmt = cx25840_s_mbus_fmt,
.s_stream = cx25840_s_stream,
};
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index ee1ca39..fb39f11 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -188,10 +188,24 @@
0x18, 0x6b, 0x71,
I2C_CLIENT_END
};
+ const unsigned short *addrp;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
- i2c_new_probed_device(&core->i2c_adap, &info, addr_list);
+ /*
+ * We can't call i2c_new_probed_device() because it uses
+ * quick writes for probing and at least some R receiver
+ * devices only reply to reads.
+ */
+ for (addrp = addr_list; *addrp != I2C_CLIENT_END; addrp++) {
+ if (i2c_smbus_xfer(&core->i2c_adap, *addrp, 0,
+ I2C_SMBUS_READ, 0,
+ I2C_SMBUS_QUICK, NULL) >= 0) {
+ info.addr = *addrp;
+ i2c_new_device(&core->i2c_adap, &info);
+ break;
+ }
+ }
}
return core->i2c_rc;
}
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index 331e1ca..44c63cbd 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -1186,8 +1186,7 @@
mutex_lock(&em28xx_devlist_mutex);
list_add_tail(&ops->next, &em28xx_extension_devlist);
list_for_each_entry(dev, &em28xx_devlist, devlist) {
- if (dev)
- ops->init(dev);
+ ops->init(dev);
}
printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name);
mutex_unlock(&em28xx_devlist_mutex);
@@ -1201,10 +1200,8 @@
mutex_lock(&em28xx_devlist_mutex);
list_for_each_entry(dev, &em28xx_devlist, devlist) {
- if (dev)
- ops->fini(dev);
+ ops->fini(dev);
}
-
printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name);
list_del(&ops->next);
mutex_unlock(&em28xx_devlist_mutex);
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c
index 785eeb4..95354a3 100644
--- a/drivers/media/video/gspca/sonixb.c
+++ b/drivers/media/video/gspca/sonixb.c
@@ -1453,9 +1453,7 @@
{USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
{USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},
{USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)},
-#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
{USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)},
-#endif
{USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)},
#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
{USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)},
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c
index bb923ef..176c5b3 100644
--- a/drivers/media/video/gspca/sonixj.c
+++ b/drivers/media/video/gspca/sonixj.c
@@ -3022,16 +3022,18 @@
/* {USB_DEVICE(0x0c45, 0x60c2), BS(SN9C105, P1030xC)}, */
/* {USB_DEVICE(0x0c45, 0x60c8), BS(SN9C105, OM6802)}, */
/* {USB_DEVICE(0x0c45, 0x60cc), BS(SN9C105, HV7131GP)}, */
+ {USB_DEVICE(0x0c45, 0x60ce), BS(SN9C105, SP80708)},
{USB_DEVICE(0x0c45, 0x60ec), BS(SN9C105, MO4000)},
/* {USB_DEVICE(0x0c45, 0x60ef), BS(SN9C105, ICM105C)}, */
/* {USB_DEVICE(0x0c45, 0x60fa), BS(SN9C105, OV7648)}, */
+/* {USB_DEVICE(0x0c45, 0x60f2), BS(SN9C105, OV7660)}, */
{USB_DEVICE(0x0c45, 0x60fb), BS(SN9C105, OV7660)},
#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
{USB_DEVICE(0x0c45, 0x60fc), BS(SN9C105, HV7131R)},
{USB_DEVICE(0x0c45, 0x60fe), BS(SN9C105, OV7630)},
#endif
{USB_DEVICE(0x0c45, 0x6100), BS(SN9C120, MI0360)}, /*sn9c128*/
-/* {USB_DEVICE(0x0c45, 0x6102), BS(SN9C120, P1030xC)}, */
+/* {USB_DEVICE(0x0c45, 0x6102), BS(SN9C120, PO2030N)}, * / GC0305*/
/* {USB_DEVICE(0x0c45, 0x6108), BS(SN9C120, OM6802)}, */
{USB_DEVICE(0x0c45, 0x610a), BS(SN9C120, OV7648)}, /*sn9c128*/
{USB_DEVICE(0x0c45, 0x610b), BS(SN9C120, OV7660)}, /*sn9c128*/
@@ -3058,6 +3060,7 @@
{USB_DEVICE(0x0c45, 0x613c), BS(SN9C120, HV7131R)},
{USB_DEVICE(0x0c45, 0x613e), BS(SN9C120, OV7630)},
{USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)}, /*sn9c120b*/
+ /* or GC0305 / GC0307 */
{USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)}, /*sn9c120b*/
{USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)}, /*sn9c120b*/
{USB_DEVICE(0x0c45, 0x614a), BS(SN9C120, ADCM1700)}, /*sn9c120b*/
diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c
index 7cfccfd..c338f3f 100644
--- a/drivers/media/video/hdpvr/hdpvr-video.c
+++ b/drivers/media/video/hdpvr/hdpvr-video.c
@@ -366,7 +366,7 @@
dev = (struct hdpvr_device *)video_get_drvdata(video_devdata(file));
if (!dev) {
- v4l2_err(&dev->v4l2_dev, "open failing with with ENODEV\n");
+ pr_err("open failing with with ENODEV\n");
retval = -ENODEV;
goto err;
}
diff --git a/drivers/media/video/ivtv/ivtv-controls.c b/drivers/media/video/ivtv/ivtv-controls.c
index b59475bf..b588e30 100644
--- a/drivers/media/video/ivtv/ivtv-controls.c
+++ b/drivers/media/video/ivtv/ivtv-controls.c
@@ -267,13 +267,13 @@
if (p.video_encoding != itv->params.video_encoding) {
int is_mpeg1 = p.video_encoding ==
V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
- struct v4l2_format fmt;
+ struct v4l2_mbus_framefmt fmt;
/* fix videodecoder resolution */
- fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- fmt.fmt.pix.width = itv->params.width / (is_mpeg1 ? 2 : 1);
- fmt.fmt.pix.height = itv->params.height;
- v4l2_subdev_call(itv->sd_video, video, s_fmt, &fmt);
+ fmt.width = itv->params.width / (is_mpeg1 ? 2 : 1);
+ fmt.height = itv->params.height;
+ fmt.code = V4L2_MBUS_FMT_FIXED;
+ v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &fmt);
}
err = cx2341x_update(itv, ivtv_api_func, &itv->params, &p);
if (!err && itv->params.stream_vbi_fmt != p.stream_vbi_fmt)
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
index abf4109..3c2cc27 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.c
+++ b/drivers/media/video/ivtv/ivtv-fileops.c
@@ -823,6 +823,12 @@
IVTV_DEBUG_FILE("close() of %s\n", s->name);
+ if (id->type == IVTV_DEC_STREAM_TYPE_YUV &&
+ test_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags)) {
+ /* Restore registers we've changed & clean up any mess */
+ ivtv_yuv_close(itv);
+ }
+
/* Stop decoding */
if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
IVTV_DEBUG_INFO("close stopping decode\n");
@@ -832,10 +838,7 @@
}
clear_bit(IVTV_F_S_APPL_IO, &s->s_flags);
clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
- if (id->type == IVTV_DEC_STREAM_TYPE_YUV && test_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags)) {
- /* Restore registers we've changed & clean up any mess we've made */
- ivtv_yuv_close(itv);
- }
+
if (itv->output_mode == OUT_UDMA_YUV && id->yuv_frames)
itv->output_mode = OUT_NONE;
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index fa9f0d9..11ac2fa 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -569,6 +569,7 @@
struct ivtv_open_id *id = fh;
struct ivtv *itv = id->itv;
struct cx2341x_mpeg_params *p = &itv->params;
+ struct v4l2_mbus_framefmt mbus_fmt;
int ret = ivtv_try_fmt_vid_cap(file, fh, fmt);
int w = fmt->fmt.pix.width;
int h = fmt->fmt.pix.height;
@@ -586,7 +587,10 @@
p->height = h;
if (p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
fmt->fmt.pix.width /= 2;
- v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt);
+ mbus_fmt.width = fmt->fmt.pix.width;
+ mbus_fmt.height = h;
+ mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
+ v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &mbus_fmt);
return ivtv_g_fmt_vid_cap(file, fh, fmt);
}
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
index de4288c..9ecacab 100644
--- a/drivers/media/video/ivtv/ivtv-streams.c
+++ b/drivers/media/video/ivtv/ivtv-streams.c
@@ -618,12 +618,17 @@
struct ivtv *itv = s->itv;
struct cx2341x_mpeg_params *p = &itv->params;
int datatype;
+ u16 width;
+ u16 height;
if (s->vdev == NULL)
return -EINVAL;
IVTV_DEBUG_INFO("Setting some initial decoder settings\n");
+ width = p->width;
+ height = p->height;
+
/* set audio mode to left/stereo for dual/stereo mode. */
ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
@@ -646,7 +651,14 @@
2 = yuv_from_host */
switch (s->type) {
case IVTV_DEC_STREAM_TYPE_YUV:
- datatype = itv->output_mode == OUT_PASSTHROUGH ? 1 : 2;
+ if (itv->output_mode == OUT_PASSTHROUGH) {
+ datatype = 1;
+ } else {
+ /* Fake size to avoid switching video standard */
+ datatype = 2;
+ width = 720;
+ height = itv->is_out_50hz ? 576 : 480;
+ }
IVTV_DEBUG_INFO("Setup DEC YUV Stream data[0] = %d\n", datatype);
break;
case IVTV_DEC_STREAM_TYPE_MPG:
@@ -655,9 +667,13 @@
break;
}
if (ivtv_vapi(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, datatype,
- p->width, p->height, p->audio_properties)) {
+ width, height, p->audio_properties)) {
IVTV_DEBUG_WARN("Couldn't initialize decoder source\n");
}
+
+ /* Decoder sometimes dies here, so wait a moment */
+ ivtv_msleep_timeout(10, 0);
+
return 0;
}
@@ -697,6 +713,9 @@
/* start playback */
ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, gop_offset, 0);
+ /* Let things settle before we actually start */
+ ivtv_msleep_timeout(10, 0);
+
/* Clear the following Interrupt mask bits for decoding */
ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_DECODE);
IVTV_DEBUG_IRQ("IRQ Mask is now: 0x%08x\n", itv->irqmask);
diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c
index 49e1a28..9ff3425 100644
--- a/drivers/media/video/ivtv/ivtvfb.c
+++ b/drivers/media/video/ivtv/ivtvfb.c
@@ -1066,7 +1066,11 @@
}
mutex_unlock(&itv->serialize_lock);
- ivtvfb_get_framebuffer(itv, &oi->video_rbase, &oi->video_buffer_size);
+ if (ivtvfb_get_framebuffer(itv, &oi->video_rbase,
+ &oi->video_buffer_size) < 0) {
+ IVTVFB_ERR("Firmware failed to respond\n");
+ return -EIO;
+ }
/* The osd buffer size depends on the number of video buffers allocated
on the PVR350 itself. For now we'll hardcode the smallest osd buffer
@@ -1158,8 +1162,11 @@
}
/* Find & setup the OSD buffer */
- if ((rc = ivtvfb_init_io(itv)))
+ rc = ivtvfb_init_io(itv);
+ if (rc) {
+ ivtvfb_release_buffers(itv);
return rc;
+ }
/* Set the startup video mode information */
if ((rc = ivtvfb_init_vidmode(itv))) {
@@ -1210,6 +1217,7 @@
{
struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev);
+ struct osd_info *oi = itv->osd_info;
if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) {
@@ -1218,7 +1226,7 @@
return 0;
}
IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance);
- ivtvfb_blank(FB_BLANK_POWERDOWN, &itv->osd_info->ivtvfb_info);
+ ivtvfb_blank(FB_BLANK_VSYNC_SUSPEND, &oi->ivtvfb_info);
ivtvfb_release_buffers(itv);
itv->osd_video_pbase = 0;
}
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
index b62c0bd..79f096d 100644
--- a/drivers/media/video/mt9m001.c
+++ b/drivers/media/video/mt9m001.c
@@ -701,13 +701,13 @@
#endif
};
-static int mt9m001_enum_fmt(struct v4l2_subdev *sd, int index,
+static int mt9m001_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
enum v4l2_mbus_pixelcode *code)
{
struct i2c_client *client = sd->priv;
struct mt9m001 *mt9m001 = to_mt9m001(client);
- if ((unsigned int)index >= mt9m001->num_fmts)
+ if (index >= mt9m001->num_fmts)
return -EINVAL;
*code = mt9m001->fmts[index].code;
@@ -785,7 +785,6 @@
ret = mt9m001_video_probe(icd, client);
if (ret) {
icd->ops = NULL;
- i2c_set_clientdata(client, NULL);
kfree(mt9m001);
}
@@ -799,7 +798,6 @@
icd->ops = NULL;
mt9m001_video_remove(icd);
- i2c_set_clientdata(client, NULL);
client->driver = NULL;
kfree(mt9m001);
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
index d35f536..fbd0fc7 100644
--- a/drivers/media/video/mt9m111.c
+++ b/drivers/media/video/mt9m111.c
@@ -999,10 +999,10 @@
#endif
};
-static int mt9m111_enum_fmt(struct v4l2_subdev *sd, int index,
+static int mt9m111_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
enum v4l2_mbus_pixelcode *code)
{
- if ((unsigned int)index >= ARRAY_SIZE(mt9m111_colour_fmts))
+ if (index >= ARRAY_SIZE(mt9m111_colour_fmts))
return -EINVAL;
*code = mt9m111_colour_fmts[index].code;
@@ -1068,7 +1068,6 @@
ret = mt9m111_video_probe(icd, client);
if (ret) {
icd->ops = NULL;
- i2c_set_clientdata(client, NULL);
kfree(mt9m111);
}
@@ -1081,7 +1080,6 @@
struct soc_camera_device *icd = client->dev.platform_data;
icd->ops = NULL;
- i2c_set_clientdata(client, NULL);
client->driver = NULL;
kfree(mt9m111);
diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c
index 78b4e09..a9a28b2 100644
--- a/drivers/media/video/mt9t031.c
+++ b/drivers/media/video/mt9t031.c
@@ -798,7 +798,7 @@
#endif
};
-static int mt9t031_enum_fmt(struct v4l2_subdev *sd, int index,
+static int mt9t031_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
enum v4l2_mbus_pixelcode *code)
{
if (index)
@@ -883,7 +883,6 @@
if (ret) {
if (icd)
icd->ops = NULL;
- i2c_set_clientdata(client, NULL);
kfree(mt9t031);
}
@@ -897,7 +896,6 @@
if (icd)
icd->ops = NULL;
- i2c_set_clientdata(client, NULL);
client->driver = NULL;
kfree(mt9t031);
diff --git a/drivers/media/video/mt9t112.c b/drivers/media/video/mt9t112.c
index 7438f8d..e4bf1db 100644
--- a/drivers/media/video/mt9t112.c
+++ b/drivers/media/video/mt9t112.c
@@ -1017,10 +1017,10 @@
return 0;
}
-static int mt9t112_enum_fmt(struct v4l2_subdev *sd, int index,
+static int mt9t112_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
enum v4l2_mbus_pixelcode *code)
{
- if ((unsigned int)index >= ARRAY_SIZE(mt9t112_cfmts))
+ if (index >= ARRAY_SIZE(mt9t112_cfmts))
return -EINVAL;
*code = mt9t112_cfmts[index].code;
@@ -1119,7 +1119,6 @@
ret = mt9t112_camera_probe(icd, client);
if (ret) {
icd->ops = NULL;
- i2c_set_clientdata(client, NULL);
kfree(priv);
}
@@ -1132,7 +1131,6 @@
struct soc_camera_device *icd = client->dev.platform_data;
icd->ops = NULL;
- i2c_set_clientdata(client, NULL);
kfree(priv);
return 0;
}
diff --git a/drivers/media/video/mt9v011.c b/drivers/media/video/mt9v011.c
index 72e55be..f5e778d 100644
--- a/drivers/media/video/mt9v011.c
+++ b/drivers/media/video/mt9v011.c
@@ -392,27 +392,25 @@
return 0;
}
-static int mt9v011_enum_fmt(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt)
+static int mt9v011_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
+ enum v4l2_mbus_pixelcode *code)
{
- if (fmt->index > 0)
+ if (index > 0)
return -EINVAL;
- fmt->flags = 0;
- strcpy(fmt->description, "8 bpp Bayer GRGR..BGBG");
- fmt->pixelformat = V4L2_PIX_FMT_SGRBG8;
-
+ *code = V4L2_MBUS_FMT_SGRBG8_1X8;
return 0;
}
-static int mt9v011_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+static int mt9v011_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
{
- struct v4l2_pix_format *pix = &fmt->fmt.pix;
-
- if (pix->pixelformat != V4L2_PIX_FMT_SGRBG8)
+ if (fmt->code != V4L2_MBUS_FMT_SGRBG8_1X8)
return -EINVAL;
- v4l_bound_align_image(&pix->width, 48, 639, 1,
- &pix->height, 32, 480, 1, 0);
+ v4l_bound_align_image(&fmt->width, 48, 639, 1,
+ &fmt->height, 32, 480, 1, 0);
+ fmt->field = V4L2_FIELD_NONE;
+ fmt->colorspace = V4L2_COLORSPACE_SRGB;
return 0;
}
@@ -455,18 +453,17 @@
return 0;
}
-static int mt9v011_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+static int mt9v011_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
{
- struct v4l2_pix_format *pix = &fmt->fmt.pix;
struct mt9v011 *core = to_mt9v011(sd);
int rc;
- rc = mt9v011_try_fmt(sd, fmt);
+ rc = mt9v011_try_mbus_fmt(sd, fmt);
if (rc < 0)
return -EINVAL;
- core->width = pix->width;
- core->height = pix->height;
+ core->width = fmt->width;
+ core->height = fmt->height;
set_res(sd);
@@ -549,9 +546,9 @@
};
static const struct v4l2_subdev_video_ops mt9v011_video_ops = {
- .enum_fmt = mt9v011_enum_fmt,
- .try_fmt = mt9v011_try_fmt,
- .s_fmt = mt9v011_s_fmt,
+ .enum_mbus_fmt = mt9v011_enum_mbus_fmt,
+ .try_mbus_fmt = mt9v011_try_mbus_fmt,
+ .s_mbus_fmt = mt9v011_s_mbus_fmt,
.g_parm = mt9v011_g_parm,
.s_parm = mt9v011_s_parm,
};
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
index e5bae4c..e7cd23c 100644
--- a/drivers/media/video/mt9v022.c
+++ b/drivers/media/video/mt9v022.c
@@ -838,13 +838,13 @@
#endif
};
-static int mt9v022_enum_fmt(struct v4l2_subdev *sd, int index,
+static int mt9v022_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
enum v4l2_mbus_pixelcode *code)
{
struct i2c_client *client = sd->priv;
struct mt9v022 *mt9v022 = to_mt9v022(client);
- if ((unsigned int)index >= mt9v022->num_fmts)
+ if (index >= mt9v022->num_fmts)
return -EINVAL;
*code = mt9v022->fmts[index].code;
@@ -920,7 +920,6 @@
ret = mt9v022_video_probe(icd, client);
if (ret) {
icd->ops = NULL;
- i2c_set_clientdata(client, NULL);
kfree(mt9v022);
}
@@ -934,7 +933,6 @@
icd->ops = NULL;
mt9v022_video_remove(icd);
- i2c_set_clientdata(client, NULL);
client->driver = NULL;
kfree(mt9v022);
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c
index d477e30..a9be14c 100644
--- a/drivers/media/video/mx3_camera.c
+++ b/drivers/media/video/mx3_camera.c
@@ -672,7 +672,7 @@
fmt->packing == SOC_MBUS_PACKING_EXTEND16);
}
-static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx,
+static int mx3_camera_get_formats(struct soc_camera_device *icd, unsigned int idx,
struct soc_camera_format_xlate *xlate)
{
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
@@ -689,7 +689,7 @@
fmt = soc_mbus_get_fmtdesc(code);
if (!fmt) {
dev_err(icd->dev.parent,
- "Invalid format code #%d: %d\n", idx, code);
+ "Invalid format code #%u: %d\n", idx, code);
return 0;
}
diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c
index 4c0ab49..e7db0554 100644
--- a/drivers/media/video/omap/omap_vout.c
+++ b/drivers/media/video/omap/omap_vout.c
@@ -2371,12 +2371,11 @@
for (k = 0; k < pdev->num_resources; k++) {
- vout = kmalloc(sizeof(struct omap_vout_device), GFP_KERNEL);
+ vout = kzalloc(sizeof(struct omap_vout_device), GFP_KERNEL);
if (!vout) {
dev_err(&pdev->dev, ": could not allocate memory\n");
return -ENOMEM;
}
- memset(vout, 0, sizeof(struct omap_vout_device));
vout->vid = k;
vid_dev->vouts[k] = vout;
diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c
index 7f8ece3..34034a7 100644
--- a/drivers/media/video/ov772x.c
+++ b/drivers/media/video/ov772x.c
@@ -1092,10 +1092,10 @@
#endif
};
-static int ov772x_enum_fmt(struct v4l2_subdev *sd, int index,
+static int ov772x_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
enum v4l2_mbus_pixelcode *code)
{
- if ((unsigned int)index >= ARRAY_SIZE(ov772x_cfmts))
+ if (index >= ARRAY_SIZE(ov772x_cfmts))
return -EINVAL;
*code = ov772x_cfmts[index].code;
@@ -1159,7 +1159,6 @@
ret = ov772x_video_probe(icd, client);
if (ret) {
icd->ops = NULL;
- i2c_set_clientdata(client, NULL);
kfree(priv);
}
@@ -1172,7 +1171,6 @@
struct soc_camera_device *icd = client->dev.platform_data;
icd->ops = NULL;
- i2c_set_clientdata(client, NULL);
kfree(priv);
return 0;
}
diff --git a/drivers/media/video/ov9640.c b/drivers/media/video/ov9640.c
index 36599a6..7ce9e05 100644
--- a/drivers/media/video/ov9640.c
+++ b/drivers/media/video/ov9640.c
@@ -614,10 +614,10 @@
return 0;
}
-static int ov9640_enum_fmt(struct v4l2_subdev *sd, int index,
+static int ov9640_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
enum v4l2_mbus_pixelcode *code)
{
- if ((unsigned int)index >= ARRAY_SIZE(ov9640_codes))
+ if (index >= ARRAY_SIZE(ov9640_codes))
return -EINVAL;
*code = ov9640_codes[index];
@@ -783,7 +783,6 @@
if (ret) {
icd->ops = NULL;
- i2c_set_clientdata(client, NULL);
kfree(priv);
}
@@ -794,7 +793,6 @@
{
struct ov9640_priv *priv = i2c_get_clientdata(client);
- i2c_set_clientdata(client, NULL);
kfree(priv);
return 0;
}
diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
index 6bc16c1..3092abf 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
@@ -117,6 +117,7 @@
static const struct pvr2_device_client_desc pvr2_cli_gotview_2[] = {
{ .module_id = PVR2_CLIENT_ID_CX25840 },
{ .module_id = PVR2_CLIENT_ID_TUNER },
+ { .module_id = PVR2_CLIENT_ID_DEMOD },
};
static const struct pvr2_device_desc pvr2_device_gotview_2 = {
diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h
index e5b9594..273c8d4 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h
@@ -177,6 +177,11 @@
unsigned int flag_has_composite:1; /* Has composite input */
unsigned int flag_has_svideo:1; /* Has s-video input */
unsigned int flag_fx2_16kb:1; /* 16KB FX2 firmware OK here */
+
+ /* If this driver is considered experimental, i.e. not all aspects
+ are working correctly and/or it is untested, mark that fact
+ with this flag. */
+ unsigned int flag_is_experimental:1;
};
extern struct usb_device_id pvr2_device_table[];
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index 301ef19..70ea578 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -2459,6 +2459,19 @@
hdw,hdw_desc->description);
pvr2_trace(PVR2_TRACE_INFO, "Hardware description: %s",
hdw_desc->description);
+ if (hdw_desc->flag_is_experimental) {
+ pvr2_trace(PVR2_TRACE_INFO, "**********");
+ pvr2_trace(PVR2_TRACE_INFO,
+ "WARNING: Support for this device (%s) is"
+ " experimental.", hdw_desc->description);
+ pvr2_trace(PVR2_TRACE_INFO,
+ "Important functionality might not be"
+ " entirely working.");
+ pvr2_trace(PVR2_TRACE_INFO,
+ "Please consider contacting the driver author to"
+ " help with further stabilization of the driver.");
+ pvr2_trace(PVR2_TRACE_INFO, "**********");
+ }
if (!hdw) goto fail;
init_timer(&hdw->quiescent_timer);
@@ -3056,14 +3069,14 @@
}
if (hdw->res_hor_dirty || hdw->res_ver_dirty || hdw->force_dirty) {
- struct v4l2_format fmt;
+ struct v4l2_mbus_framefmt fmt;
memset(&fmt, 0, sizeof(fmt));
- fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- fmt.fmt.pix.width = hdw->res_hor_val;
- fmt.fmt.pix.height = hdw->res_ver_val;
+ fmt.width = hdw->res_hor_val;
+ fmt.height = hdw->res_ver_val;
+ fmt.code = V4L2_MBUS_FMT_FIXED;
pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_size(%dx%d)",
- fmt.fmt.pix.width, fmt.fmt.pix.height);
- v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_fmt, &fmt);
+ fmt.width, fmt.height);
+ v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_mbus_fmt, &fmt);
}
if (hdw->srate_dirty || hdw->force_dirty) {
@@ -4084,12 +4097,20 @@
void pvr2_hdw_cpureset_assert(struct pvr2_hdw *hdw,int val)
{
- char da[1];
+ char *da;
unsigned int pipe;
int ret;
if (!hdw->usb_dev) return;
+ da = kmalloc(16, GFP_KERNEL);
+
+ if (da == NULL) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "Unable to allocate memory to control CPU reset");
+ return;
+ }
+
pvr2_trace(PVR2_TRACE_INIT,"cpureset_assert(%d)",val);
da[0] = val ? 0x01 : 0x00;
@@ -4103,6 +4124,8 @@
"cpureset_assert(%d) error=%d",val,ret);
pvr2_hdw_render_useless(hdw);
}
+
+ kfree(da);
}
diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c
index eeacd0f..2254194 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-main.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-main.c
@@ -153,12 +153,12 @@
usb_deregister(&pvr_driver);
+ pvr2_context_global_done();
+
#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
pvr2_sysfs_class_destroy(class_ptr);
#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
- pvr2_context_global_done();
-
pvr2_trace(PVR2_TRACE_INIT,"pvr_exit complete");
}
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
index 71f5056..3d7e5aa 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
@@ -74,7 +74,7 @@
int ctl_id;
struct pvr2_sysfs *chptr;
struct pvr2_sysfs_ctl_item *item_next;
- struct attribute *attr_gen[7];
+ struct attribute *attr_gen[8];
struct attribute_group grp;
int created_ok;
char name[80];
@@ -511,6 +511,7 @@
static void class_dev_destroy(struct pvr2_sysfs *sfp)
{
+ struct device *dev;
if (!sfp->class_dev) return;
#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
pvr2_sysfs_tear_down_debugifc(sfp);
@@ -542,6 +543,9 @@
}
pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev);
dev_set_drvdata(sfp->class_dev, NULL);
+ dev = sfp->class_dev->parent;
+ sfp->class_dev->parent = NULL;
+ put_device(dev);
device_unregister(sfp->class_dev);
sfp->class_dev = NULL;
}
@@ -631,10 +635,11 @@
pvr2_sysfs_trace("Creating class_dev id=%p",class_dev);
class_dev->class = &class_ptr->class;
+
dev_set_name(class_dev, "%s",
pvr2_hdw_get_device_identifier(sfp->channel.hdw));
- class_dev->parent = &usb_dev->dev;
+ class_dev->parent = get_device(&usb_dev->dev);
sfp->class_dev = class_dev;
dev_set_drvdata(class_dev, sfp);
@@ -775,7 +780,8 @@
struct pvr2_sysfs_class *clp;
clp = kzalloc(sizeof(*clp),GFP_KERNEL);
if (!clp) return clp;
- pvr2_sysfs_trace("Creating pvr2_sysfs_class id=%p",clp);
+ pvr2_sysfs_trace("Creating and registering pvr2_sysfs_class id=%p",
+ clp);
clp->class.name = "pvrusb2";
clp->class.class_release = pvr2_sysfs_class_release;
clp->class.dev_release = pvr2_sysfs_release;
@@ -791,6 +797,7 @@
void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class *clp)
{
+ pvr2_sysfs_trace("Unregistering pvr2_sysfs_class id=%p", clp);
class_unregister(&clp->class);
}
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index 5ffa0d2..aaafa03 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -883,6 +883,17 @@
{
struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
enum pvr2_config cfg = dip->config;
+ char msg[80];
+ unsigned int mcnt;
+
+ /* Construct the unregistration message *before* we actually
+ perform the unregistration step. By doing it this way we don't
+ have to worry about potentially touching deleted resources. */
+ mcnt = scnprintf(msg, sizeof(msg) - 1,
+ "pvrusb2: unregistered device %s [%s]",
+ video_device_node_name(&dip->devbase),
+ pvr2_config_get_name(cfg));
+ msg[mcnt] = 0;
pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
@@ -894,9 +905,7 @@
are gone. */
video_unregister_device(&dip->devbase);
- printk(KERN_INFO "pvrusb2: unregistered device %s [%s]\n",
- video_device_node_name(&dip->devbase),
- pvr2_config_get_name(cfg));
+ printk(KERN_INFO "%s\n", msg);
}
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index 7fe70e7..fb242f6 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -1247,7 +1247,7 @@
fmt->packing == SOC_MBUS_PACKING_EXTEND16);
}
-static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx,
+static int pxa_camera_get_formats(struct soc_camera_device *icd, unsigned int idx,
struct soc_camera_format_xlate *xlate)
{
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
@@ -1264,7 +1264,7 @@
fmt = soc_mbus_get_fmtdesc(code);
if (!fmt) {
- dev_err(dev, "Invalid format code #%d: %d\n", idx, code);
+ dev_err(dev, "Invalid format code #%u: %d\n", idx, code);
return 0;
}
diff --git a/drivers/media/video/rj54n1cb0c.c b/drivers/media/video/rj54n1cb0c.c
index bbd9c11..47fd207 100644
--- a/drivers/media/video/rj54n1cb0c.c
+++ b/drivers/media/video/rj54n1cb0c.c
@@ -481,10 +481,10 @@
return 0;
}
-static int rj54n1_enum_fmt(struct v4l2_subdev *sd, int index,
+static int rj54n1_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
enum v4l2_mbus_pixelcode *code)
{
- if ((unsigned int)index >= ARRAY_SIZE(rj54n1_colour_fmts))
+ if (index >= ARRAY_SIZE(rj54n1_colour_fmts))
return -EINVAL;
*code = rj54n1_colour_fmts[index].code;
@@ -1444,7 +1444,6 @@
ret = rj54n1_video_probe(icd, client, rj54n1_priv);
if (ret < 0) {
icd->ops = NULL;
- i2c_set_clientdata(client, NULL);
kfree(rj54n1);
return ret;
}
@@ -1461,7 +1460,6 @@
icd->ops = NULL;
if (icl->free_bus)
icl->free_bus(icl);
- i2c_set_clientdata(client, NULL);
client->driver = NULL;
kfree(rj54n1);
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index 53b6fcd..76da743 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -1117,13 +1117,6 @@
return 0;
}
-static int saa711x_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
-{
- if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
- return -EINVAL;
- return saa711x_g_sliced_fmt(sd, &fmt->fmt.sliced);
-}
-
static int saa711x_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
{
saa711x_set_lcr(sd, NULL);
@@ -1136,12 +1129,13 @@
return 0;
}
-static int saa711x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+static int saa711x_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
{
- if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ if (fmt->code != V4L2_MBUS_FMT_FIXED)
return -EINVAL;
-
- return saa711x_set_size(sd, fmt->fmt.pix.width, fmt->fmt.pix.height);
+ fmt->field = V4L2_FIELD_INTERLACED;
+ fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+ return saa711x_set_size(sd, fmt->width, fmt->height);
}
/* Decode the sliced VBI data stream as created by the saa7115.
@@ -1556,8 +1550,7 @@
static const struct v4l2_subdev_video_ops saa711x_video_ops = {
.s_routing = saa711x_s_routing,
.s_crystal_freq = saa711x_s_crystal_freq,
- .g_fmt = saa711x_g_fmt,
- .s_fmt = saa711x_s_fmt,
+ .s_mbus_fmt = saa711x_s_mbus_fmt,
.s_stream = saa711x_s_stream,
.querystd = saa711x_querystd,
.g_input_status = saa711x_g_input_status,
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c
index 87986ad..79fffcf 100644
--- a/drivers/media/video/saa7127.c
+++ b/drivers/media/video/saa7127.c
@@ -645,13 +645,6 @@
return 0;
}
-static int saa7127_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
-{
- if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
- return -EINVAL;
- return saa7127_g_sliced_fmt(sd, &fmt->fmt.sliced);
-}
-
static int saa7127_s_vbi_data(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
{
switch (data->id) {
@@ -731,7 +724,6 @@
};
static const struct v4l2_subdev_video_ops saa7127_video_ops = {
- .g_fmt = saa7127_g_fmt,
.s_std_output = saa7127_s_std_output,
.s_routing = saa7127_s_routing,
.s_stream = saa7127_s_stream,
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
index 1eabff6..40fd31c 100644
--- a/drivers/media/video/saa7134/saa6752hs.c
+++ b/drivers/media/video/saa7134/saa6752hs.c
@@ -846,24 +846,28 @@
return 0;
}
-static int saa6752hs_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int saa6752hs_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
{
struct saa6752hs_state *h = to_state(sd);
if (h->video_format == SAA6752HS_VF_UNKNOWN)
h->video_format = SAA6752HS_VF_D1;
- f->fmt.pix.width =
- v4l2_format_table[h->video_format].fmt.pix.width;
- f->fmt.pix.height =
- v4l2_format_table[h->video_format].fmt.pix.height;
+ f->width = v4l2_format_table[h->video_format].fmt.pix.width;
+ f->height = v4l2_format_table[h->video_format].fmt.pix.height;
+ f->code = V4L2_MBUS_FMT_FIXED;
+ f->field = V4L2_FIELD_INTERLACED;
+ f->colorspace = V4L2_COLORSPACE_SMPTE170M;
return 0;
}
-static int saa6752hs_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int saa6752hs_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
{
struct saa6752hs_state *h = to_state(sd);
int dist_352, dist_480, dist_720;
+ if (f->code != V4L2_MBUS_FMT_FIXED)
+ return -EINVAL;
+
/*
FIXME: translate and round width/height into EMPRESS
subsample type:
@@ -876,28 +880,30 @@
D1 | 720x576 | 720x480
*/
- dist_352 = abs(f->fmt.pix.width - 352);
- dist_480 = abs(f->fmt.pix.width - 480);
- dist_720 = abs(f->fmt.pix.width - 720);
+ dist_352 = abs(f->width - 352);
+ dist_480 = abs(f->width - 480);
+ dist_720 = abs(f->width - 720);
if (dist_720 < dist_480) {
- f->fmt.pix.width = 720;
- f->fmt.pix.height = 576;
+ f->width = 720;
+ f->height = 576;
h->video_format = SAA6752HS_VF_D1;
} else if (dist_480 < dist_352) {
- f->fmt.pix.width = 480;
- f->fmt.pix.height = 576;
+ f->width = 480;
+ f->height = 576;
h->video_format = SAA6752HS_VF_2_3_D1;
} else {
- f->fmt.pix.width = 352;
- if (abs(f->fmt.pix.height - 576) <
- abs(f->fmt.pix.height - 288)) {
- f->fmt.pix.height = 576;
+ f->width = 352;
+ if (abs(f->height - 576) <
+ abs(f->height - 288)) {
+ f->height = 576;
h->video_format = SAA6752HS_VF_1_2_D1;
} else {
- f->fmt.pix.height = 288;
+ f->height = 288;
h->video_format = SAA6752HS_VF_SIF;
}
}
+ f->field = V4L2_FIELD_INTERLACED;
+ f->colorspace = V4L2_COLORSPACE_SMPTE170M;
return 0;
}
@@ -932,8 +938,8 @@
};
static const struct v4l2_subdev_video_ops saa6752hs_video_ops = {
- .s_fmt = saa6752hs_s_fmt,
- .g_fmt = saa6752hs_g_fmt,
+ .s_mbus_fmt = saa6752hs_s_mbus_fmt,
+ .g_mbus_fmt = saa6752hs_g_mbus_fmt,
};
static const struct v4l2_subdev_ops saa6752hs_ops = {
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index 72700d4e..07f6bb8 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -3897,6 +3897,40 @@
.gpio = 0x01,
},
},
+ [SAA7134_BOARD_AVERMEDIA_M733A] = {
+ .name = "Avermedia PCI M733A",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tuner_config = 0,
+ .gpiomask = 0x020200000,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ }, {
+ .name = name_comp1,
+ .vmux = 3,
+ .amux = LINE1,
+ }, {
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ } },
+ .radio = {
+ .name = name_radio,
+ .amux = TV,
+ .gpio = 0x00200000,
+ },
+ .mute = {
+ .name = name_mute,
+ .amux = TV,
+ .gpio = 0x01,
+ },
+ },
[SAA7134_BOARD_BEHOLD_401] = {
/* Beholder Intl. Ltd. 2008 */
/*Dmitry Belimov <d.belimov@gmail.com> */
@@ -5822,6 +5856,18 @@
.driver_data = SAA7134_BOARD_AVERMEDIA_M135A,
}, {
.vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x1461, /* Avermedia Technologies Inc */
+ .subdevice = 0x4155,
+ .driver_data = SAA7134_BOARD_AVERMEDIA_M733A,
+ }, {
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x1461, /* Avermedia Technologies Inc */
+ .subdevice = 0x4255,
+ .driver_data = SAA7134_BOARD_AVERMEDIA_M733A,
+ }, {
+ .vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7130,
.subvendor = PCI_VENDOR_ID_PHILIPS,
.subdevice = 0x2004,
@@ -6786,6 +6832,7 @@
switch (dev->board) {
case SAA7134_BOARD_HAUPPAUGE_HVR1150:
case SAA7134_BOARD_HAUPPAUGE_HVR1120:
+ case SAA7134_BOARD_AVERMEDIA_M733A:
/* tda8290 + tda18271 */
ret = saa7134_tda8290_18271_callback(dev, command, arg);
break;
@@ -7087,6 +7134,14 @@
saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x0000C000, 0x0000C000);
saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0000C000, 0x0000C000);
break;
+ case SAA7134_BOARD_AVERMEDIA_M733A:
+ saa7134_set_gpio(dev, 1, 1);
+ msleep(10);
+ saa7134_set_gpio(dev, 1, 0);
+ msleep(10);
+ saa7134_set_gpio(dev, 1, 1);
+ dev->has_remote = SAA7134_REMOTE_GPIO;
+ break;
}
return 0;
}
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index ea877a5..e763f9f 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -223,9 +223,11 @@
struct v4l2_format *f)
{
struct saa7134_dev *dev = file->private_data;
+ struct v4l2_mbus_framefmt mbus_fmt;
- saa_call_all(dev, video, g_fmt, f);
+ saa_call_all(dev, video, g_mbus_fmt, &mbus_fmt);
+ v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
@@ -236,8 +238,11 @@
struct v4l2_format *f)
{
struct saa7134_dev *dev = file->private_data;
+ struct v4l2_mbus_framefmt mbus_fmt;
- saa_call_all(dev, video, s_fmt, f);
+ v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
+ saa_call_all(dev, video, s_mbus_fmt, &mbus_fmt);
+ v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index e5565e2..0b336ca 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -141,8 +141,8 @@
struct saa7134_dev *dev = ir->c->adapter->algo_data;
if (dev == NULL) {
- dprintk("get_key_flydvb_trio: "
- "gir->c->adapter->algo_data is NULL!\n");
+ i2cdprintk("get_key_flydvb_trio: "
+ "ir->c->adapter->algo_data is NULL!\n");
return -EIO;
}
@@ -195,8 +195,8 @@
/* <dev> is needed to access GPIO. Used by the saa_readl macro. */
struct saa7134_dev *dev = ir->c->adapter->algo_data;
if (dev == NULL) {
- dprintk("get_key_msi_tvanywhere_plus: "
- "gir->c->adapter->algo_data is NULL!\n");
+ i2cdprintk("get_key_msi_tvanywhere_plus: "
+ "ir->c->adapter->algo_data is NULL!\n");
return -EIO;
}
@@ -657,12 +657,19 @@
saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4);
break;
case SAA7134_BOARD_AVERMEDIA_M135A:
- ir_codes = RC_MAP_AVERMEDIA_M135A_RM_JX;
+ ir_codes = RC_MAP_AVERMEDIA_M135A;
mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */
mask_keyup = 0x0040000;
mask_keycode = 0xffff;
raw_decode = 1;
break;
+ case SAA7134_BOARD_AVERMEDIA_M733A:
+ ir_codes = RC_MAP_AVERMEDIA_M733A_RM_K6;
+ mask_keydown = 0x0040000;
+ mask_keyup = 0x0040000;
+ mask_keycode = 0xffff;
+ raw_decode = 1;
+ break;
case SAA7134_BOARD_AVERMEDIA_777:
case SAA7134_BOARD_AVERMEDIA_A16AR:
ir_codes = RC_MAP_AVERMEDIA;
@@ -815,7 +822,6 @@
mask_keyup = 0x020000;
polling = 50; /* ms */
break;
- break;
}
if (NULL == ir_codes) {
printk("%s: Oops: IR config error [card=%d]\n",
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index 3962534..756a1ca 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -303,6 +303,7 @@
#define SAA7134_BOARD_HAWELL_HW_404M7 177
#define SAA7134_BOARD_BEHOLD_H7 178
#define SAA7134_BOARD_BEHOLD_A7 179
+#define SAA7134_BOARD_AVERMEDIA_M733A 180
#define SAA7134_MAXBOARDS 32
#define SAA7134_INPUT_MAX 8
diff --git a/drivers/media/video/saa717x.c b/drivers/media/video/saa717x.c
index d521c64..78d6995 100644
--- a/drivers/media/video/saa717x.c
+++ b/drivers/media/video/saa717x.c
@@ -1199,28 +1199,32 @@
}
#endif
-static int saa717x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+static int saa717x_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
{
- struct v4l2_pix_format *pix;
int prescale, h_scale, v_scale;
- pix = &fmt->fmt.pix;
v4l2_dbg(1, debug, sd, "decoder set size\n");
+ if (fmt->code != V4L2_MBUS_FMT_FIXED)
+ return -EINVAL;
+
/* FIXME need better bounds checking here */
- if (pix->width < 1 || pix->width > 1440)
+ if (fmt->width < 1 || fmt->width > 1440)
return -EINVAL;
- if (pix->height < 1 || pix->height > 960)
+ if (fmt->height < 1 || fmt->height > 960)
return -EINVAL;
+ fmt->field = V4L2_FIELD_INTERLACED;
+ fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+
/* scaling setting */
/* NTSC and interlace only */
- prescale = SAA717X_NTSC_WIDTH / pix->width;
+ prescale = SAA717X_NTSC_WIDTH / fmt->width;
if (prescale == 0)
prescale = 1;
- h_scale = 1024 * SAA717X_NTSC_WIDTH / prescale / pix->width;
+ h_scale = 1024 * SAA717X_NTSC_WIDTH / prescale / fmt->width;
/* interlace */
- v_scale = 512 * 2 * SAA717X_NTSC_HEIGHT / pix->height;
+ v_scale = 512 * 2 * SAA717X_NTSC_HEIGHT / fmt->height;
/* Horizontal prescaling etc */
set_h_prescale(sd, 0, prescale);
@@ -1241,19 +1245,19 @@
/* set video output size */
/* video number of pixels at output */
/* TASK A */
- saa717x_write(sd, 0x5C, (u8)(pix->width & 0xFF));
- saa717x_write(sd, 0x5D, (u8)((pix->width >> 8) & 0xFF));
+ saa717x_write(sd, 0x5C, (u8)(fmt->width & 0xFF));
+ saa717x_write(sd, 0x5D, (u8)((fmt->width >> 8) & 0xFF));
/* TASK B */
- saa717x_write(sd, 0x9C, (u8)(pix->width & 0xFF));
- saa717x_write(sd, 0x9D, (u8)((pix->width >> 8) & 0xFF));
+ saa717x_write(sd, 0x9C, (u8)(fmt->width & 0xFF));
+ saa717x_write(sd, 0x9D, (u8)((fmt->width >> 8) & 0xFF));
/* video number of lines at output */
/* TASK A */
- saa717x_write(sd, 0x5E, (u8)(pix->height & 0xFF));
- saa717x_write(sd, 0x5F, (u8)((pix->height >> 8) & 0xFF));
+ saa717x_write(sd, 0x5E, (u8)(fmt->height & 0xFF));
+ saa717x_write(sd, 0x5F, (u8)((fmt->height >> 8) & 0xFF));
/* TASK B */
- saa717x_write(sd, 0x9E, (u8)(pix->height & 0xFF));
- saa717x_write(sd, 0x9F, (u8)((pix->height >> 8) & 0xFF));
+ saa717x_write(sd, 0x9E, (u8)(fmt->height & 0xFF));
+ saa717x_write(sd, 0x9F, (u8)((fmt->height >> 8) & 0xFF));
return 0;
}
@@ -1403,7 +1407,7 @@
static const struct v4l2_subdev_video_ops saa717x_video_ops = {
.s_routing = saa717x_s_video_routing,
- .s_fmt = saa717x_s_fmt,
+ .s_mbus_fmt = saa717x_s_mbus_fmt,
.s_stream = saa717x_s_stream,
};
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index 4ac3b48..961bfa2 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -878,7 +878,7 @@
static int client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect);
-static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx,
+static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int idx,
struct soc_camera_format_xlate *xlate)
{
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
@@ -897,7 +897,7 @@
fmt = soc_mbus_get_fmtdesc(code);
if (!fmt) {
dev_err(icd->dev.parent,
- "Invalid format code #%d: %d\n", idx, code);
+ "Invalid format code #%u: %d\n", idx, code);
return -EINVAL;
}
diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h
index 522ba3f..b6643ca 100644
--- a/drivers/media/video/sn9c102/sn9c102_devtable.h
+++ b/drivers/media/video/sn9c102/sn9c102_devtable.h
@@ -62,8 +62,8 @@
#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
{ SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), },
/* { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, HV7131R */
-#endif
{ SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), },
+#endif
{ SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), },
/* SN9C103 */
{ SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), },
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index db1ca0e..475757b 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -200,7 +200,8 @@
{
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
- int i, fmts = 0, raw_fmts = 0, ret;
+ unsigned int i, fmts = 0, raw_fmts = 0;
+ int ret;
enum v4l2_mbus_pixelcode code;
while (!v4l2_subdev_call(sd, video, enum_mbus_fmt, raw_fmts, &code))
diff --git a/drivers/media/video/soc_camera_platform.c b/drivers/media/video/soc_camera_platform.c
index 10b003a..248c986 100644
--- a/drivers/media/video/soc_camera_platform.c
+++ b/drivers/media/video/soc_camera_platform.c
@@ -71,7 +71,7 @@
static struct v4l2_subdev_core_ops platform_subdev_core_ops;
-static int soc_camera_platform_enum_fmt(struct v4l2_subdev *sd, int index,
+static int soc_camera_platform_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
enum v4l2_mbus_pixelcode *code)
{
struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd);
diff --git a/drivers/media/video/tcm825x.c b/drivers/media/video/tcm825x.c
index b90e9da..54681a5 100644
--- a/drivers/media/video/tcm825x.c
+++ b/drivers/media/video/tcm825x.c
@@ -850,7 +850,6 @@
const struct i2c_device_id *did)
{
struct tcm825x_sensor *sensor = &tcm825x;
- int rval;
if (i2c_get_clientdata(client))
return -EBUSY;
@@ -871,11 +870,7 @@
sensor->pix.height = tcm825x_sizes[QVGA].height;
sensor->pix.pixelformat = V4L2_PIX_FMT_RGB565;
- rval = v4l2_int_device_register(sensor->v4l2_int_device);
- if (rval)
- i2c_set_clientdata(client, NULL);
-
- return rval;
+ return v4l2_int_device_register(sensor->v4l2_int_device);
}
static int tcm825x_remove(struct i2c_client *client)
@@ -886,7 +881,6 @@
return -ENODEV; /* our client isn't attached */
v4l2_int_device_unregister(sensor->v4l2_int_device);
- i2c_set_clientdata(client, NULL);
return 0;
}
diff --git a/drivers/media/video/tvp514x.c b/drivers/media/video/tvp514x.c
index e826114..71c73fa 100644
--- a/drivers/media/video/tvp514x.c
+++ b/drivers/media/video/tvp514x.c
@@ -88,9 +88,6 @@
* @pdata: Board specific
* @ver: Chip version
* @streaming: TVP5146/47 decoder streaming - enabled or disabled.
- * @pix: Current pixel format
- * @num_fmts: Number of formats
- * @fmt_list: Format list
* @current_std: Current standard
* @num_stds: Number of standards
* @std_list: Standards list
@@ -105,13 +102,9 @@
int ver;
int streaming;
- struct v4l2_pix_format pix;
- int num_fmts;
- const struct v4l2_fmtdesc *fmt_list;
-
enum tvp514x_std current_std;
int num_stds;
- struct tvp514x_std_info *std_list;
+ const struct tvp514x_std_info *std_list;
/* Input and Output Routing parameters */
u32 input;
u32 output;
@@ -203,27 +196,12 @@
};
/**
- * List of image formats supported by TVP5146/47 decoder
- * Currently we are using 8 bit mode only, but can be
- * extended to 10/20 bit mode.
- */
-static const struct v4l2_fmtdesc tvp514x_fmt_list[] = {
- {
- .index = 0,
- .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
- .flags = 0,
- .description = "8-bit UYVY 4:2:2 Format",
- .pixelformat = V4L2_PIX_FMT_UYVY,
- },
-};
-
-/**
* Supported standards -
*
* Currently supports two standards only, need to add support for rest of the
* modes, like SECAM, etc...
*/
-static struct tvp514x_std_info tvp514x_std_list[] = {
+static const struct tvp514x_std_info tvp514x_std_list[] = {
/* Standard: STD_NTSC_MJ */
[STD_NTSC_MJ] = {
.width = NTSC_NUM_ACTIVE_PIXELS,
@@ -366,13 +344,13 @@
}
/**
- * tvp514x_get_current_std() : Get the current standard detected by TVP5146/47
+ * tvp514x_query_current_std() : Query the current standard detected by TVP5146/47
* @sd: ptr to v4l2_subdev struct
*
- * Get current standard detected by TVP5146/47, STD_INVALID if there is no
+ * Returns the current standard detected by TVP5146/47, STD_INVALID if there is no
* standard detected.
*/
-static enum tvp514x_std tvp514x_get_current_std(struct v4l2_subdev *sd)
+static enum tvp514x_std tvp514x_query_current_std(struct v4l2_subdev *sd)
{
u8 std, std_status;
@@ -518,7 +496,7 @@
* @std_id: standard V4L2 std_id ioctl enum
*
* Returns the current standard detected by TVP5146/47. If no active input is
- * detected, returns -EINVAL
+ * detected then *std_id is set to 0 and the function returns 0.
*/
static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
{
@@ -530,10 +508,12 @@
if (std_id == NULL)
return -EINVAL;
- /* get the current standard */
- current_std = tvp514x_get_current_std(sd);
+ *std_id = V4L2_STD_UNKNOWN;
+
+ /* query the current standard */
+ current_std = tvp514x_query_current_std(sd);
if (current_std == STD_INVALID)
- return -EINVAL;
+ return 0;
input_sel = decoder->input;
@@ -575,12 +555,11 @@
/* check whether signal is locked */
sync_lock_status = tvp514x_read_reg(sd, REG_STATUS1);
if (lock_mask != (sync_lock_status & lock_mask))
- return -EINVAL; /* No input detected */
+ return 0; /* No input detected */
- decoder->current_std = current_std;
*std_id = decoder->std_list[current_std].standard.id;
- v4l2_dbg(1, debug, sd, "Current STD: %s",
+ v4l2_dbg(1, debug, sd, "Current STD: %s\n",
decoder->std_list[current_std].standard.name);
return 0;
}
@@ -614,7 +593,7 @@
decoder->tvp514x_regs[REG_VIDEO_STD].val =
decoder->std_list[i].video_std;
- v4l2_dbg(1, debug, sd, "Standard set to: %s",
+ v4l2_dbg(1, debug, sd, "Standard set to: %s\n",
decoder->std_list[i].standard.name);
return 0;
}
@@ -637,7 +616,6 @@
int err;
enum tvp514x_input input_sel;
enum tvp514x_output output_sel;
- enum tvp514x_std current_std = STD_INVALID;
u8 sync_lock_status, lock_mask;
int try_count = LOCK_RETRY_COUNT;
@@ -721,11 +699,6 @@
/* Allow decoder to sync up with new input */
msleep(LOCK_RETRY_DELAY);
- /* get the current standard for future reference */
- current_std = tvp514x_get_current_std(sd);
- if (current_std == STD_INVALID)
- continue;
-
sync_lock_status = tvp514x_read_reg(sd,
REG_STATUS1);
if (lock_mask == (sync_lock_status & lock_mask))
@@ -733,15 +706,13 @@
break;
}
- if ((current_std == STD_INVALID) || (try_count < 0))
+ if (try_count < 0)
return -EINVAL;
- decoder->current_std = current_std;
decoder->input = input;
decoder->output = output;
- v4l2_dbg(1, debug, sd, "Input set to: %d, std : %d",
- input_sel, current_std);
+ v4l2_dbg(1, debug, sd, "Input set to: %d\n", input_sel);
return 0;
}
@@ -794,7 +765,7 @@
return err;
}
- v4l2_dbg(1, debug, sd, "Query Control:%s: Min - %d, Max - %d, Def - %d",
+ v4l2_dbg(1, debug, sd, "Query Control:%s: Min - %d, Max - %d, Def - %d\n",
qctrl->name, qctrl->minimum, qctrl->maximum,
qctrl->default_value);
@@ -851,7 +822,7 @@
return -EINVAL;
}
- v4l2_dbg(1, debug, sd, "Get Control: ID - %d - %d",
+ v4l2_dbg(1, debug, sd, "Get Control: ID - %d - %d\n",
ctrl->id, ctrl->value);
return 0;
}
@@ -951,7 +922,7 @@
return err;
}
- v4l2_dbg(1, debug, sd, "Set Control: ID - %d - %d",
+ v4l2_dbg(1, debug, sd, "Set Control: ID - %d - %d\n",
ctrl->id, ctrl->value);
return err;
@@ -967,44 +938,33 @@
static int
tvp514x_enum_fmt_cap(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt)
{
- struct tvp514x_decoder *decoder = to_decoder(sd);
- int index;
-
- if (fmt == NULL)
- return -EINVAL;
-
- index = fmt->index;
- if ((index >= decoder->num_fmts) || (index < 0))
- /* Index out of bound */
+ if (fmt == NULL || fmt->index)
return -EINVAL;
if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
/* only capture is supported */
return -EINVAL;
- memcpy(fmt, &decoder->fmt_list[index],
- sizeof(struct v4l2_fmtdesc));
-
- v4l2_dbg(1, debug, sd, "Current FMT: index - %d (%s)",
- decoder->fmt_list[index].index,
- decoder->fmt_list[index].description);
+ /* only one format */
+ fmt->flags = 0;
+ strlcpy(fmt->description, "8-bit UYVY 4:2:2 Format",
+ sizeof(fmt->description));
+ fmt->pixelformat = V4L2_PIX_FMT_UYVY;
return 0;
}
/**
- * tvp514x_try_fmt_cap() - V4L2 decoder interface handler for try_fmt
+ * tvp514x_fmt_cap() - V4L2 decoder interface handler for try/s/g_fmt
* @sd: pointer to standard V4L2 sub-device structure
* @f: pointer to standard V4L2 VIDIOC_TRY_FMT ioctl structure
*
- * Implement the VIDIOC_TRY_FMT ioctl for the CAPTURE buffer type. This
- * ioctl is used to negotiate the image capture size and pixel format
- * without actually making it take effect.
+ * Implement the VIDIOC_TRY/S/G_FMT ioctl for the CAPTURE buffer type. This
+ * ioctl is used to negotiate the image capture size and pixel format.
*/
static int
-tvp514x_try_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f)
+tvp514x_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f)
{
struct tvp514x_decoder *decoder = to_decoder(sd);
- int ifmt;
struct v4l2_pix_format *pix;
enum tvp514x_std current_std;
@@ -1012,106 +972,30 @@
return -EINVAL;
if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- /* only capture is supported */
- f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ return -EINVAL;
pix = &f->fmt.pix;
/* Calculate height and width based on current standard */
- current_std = tvp514x_get_current_std(sd);
- if (current_std == STD_INVALID)
- return -EINVAL;
+ current_std = decoder->current_std;
- decoder->current_std = current_std;
+ pix->pixelformat = V4L2_PIX_FMT_UYVY;
pix->width = decoder->std_list[current_std].width;
pix->height = decoder->std_list[current_std].height;
-
- for (ifmt = 0; ifmt < decoder->num_fmts; ifmt++) {
- if (pix->pixelformat ==
- decoder->fmt_list[ifmt].pixelformat)
- break;
- }
- if (ifmt == decoder->num_fmts)
- /* None of the format matched, select default */
- ifmt = 0;
- pix->pixelformat = decoder->fmt_list[ifmt].pixelformat;
-
pix->field = V4L2_FIELD_INTERLACED;
pix->bytesperline = pix->width * 2;
pix->sizeimage = pix->bytesperline * pix->height;
pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
pix->priv = 0;
- v4l2_dbg(1, debug, sd, "Try FMT: pixelformat - %s, bytesperline - %d"
- "Width - %d, Height - %d",
- decoder->fmt_list[ifmt].description, pix->bytesperline,
+ v4l2_dbg(1, debug, sd, "FMT: bytesperline - %d"
+ "Width - %d, Height - %d\n",
+ pix->bytesperline,
pix->width, pix->height);
return 0;
}
/**
- * tvp514x_s_fmt_cap() - V4L2 decoder interface handler for s_fmt
- * @sd: pointer to standard V4L2 sub-device structure
- * @f: pointer to standard V4L2 VIDIOC_S_FMT ioctl structure
- *
- * If the requested format is supported, configures the HW to use that
- * format, returns error code if format not supported or HW can't be
- * correctly configured.
- */
-static int
-tvp514x_s_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f)
-{
- struct tvp514x_decoder *decoder = to_decoder(sd);
- struct v4l2_pix_format *pix;
- int rval;
-
- if (f == NULL)
- return -EINVAL;
-
- if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- /* only capture is supported */
- return -EINVAL;
-
- pix = &f->fmt.pix;
- rval = tvp514x_try_fmt_cap(sd, f);
- if (rval)
- return rval;
-
- decoder->pix = *pix;
-
- return rval;
-}
-
-/**
- * tvp514x_g_fmt_cap() - V4L2 decoder interface handler for tvp514x_g_fmt_cap
- * @sd: pointer to standard V4L2 sub-device structure
- * @f: pointer to standard V4L2 v4l2_format structure
- *
- * Returns the decoder's current pixel format in the v4l2_format
- * parameter.
- */
-static int
-tvp514x_g_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f)
-{
- struct tvp514x_decoder *decoder = to_decoder(sd);
-
- if (f == NULL)
- return -EINVAL;
-
- if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- /* only capture is supported */
- return -EINVAL;
-
- f->fmt.pix = decoder->pix;
-
- v4l2_dbg(1, debug, sd, "Current FMT: bytesperline - %d"
- "Width - %d, Height - %d",
- decoder->pix.bytesperline,
- decoder->pix.width, decoder->pix.height);
- return 0;
-}
-
-/**
* tvp514x_g_parm() - V4L2 decoder interface handler for g_parm
* @sd: pointer to standard V4L2 sub-device structure
* @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
@@ -1132,15 +1016,8 @@
/* only capture is supported */
return -EINVAL;
- memset(a, 0, sizeof(*a));
- a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
/* get the current standard */
- current_std = tvp514x_get_current_std(sd);
- if (current_std == STD_INVALID)
- return -EINVAL;
-
- decoder->current_std = current_std;
+ current_std = decoder->current_std;
cparm = &a->parm.capture;
cparm->capability = V4L2_CAP_TIMEPERFRAME;
@@ -1175,11 +1052,7 @@
timeperframe = &a->parm.capture.timeperframe;
/* get the current standard */
- current_std = tvp514x_get_current_std(sd);
- if (current_std == STD_INVALID)
- return -EINVAL;
-
- decoder->current_std = current_std;
+ current_std = decoder->current_std;
*timeperframe =
decoder->std_list[current_std].standard.frameperiod;
@@ -1259,9 +1132,9 @@
.s_routing = tvp514x_s_routing,
.querystd = tvp514x_querystd,
.enum_fmt = tvp514x_enum_fmt_cap,
- .g_fmt = tvp514x_g_fmt_cap,
- .try_fmt = tvp514x_try_fmt_cap,
- .s_fmt = tvp514x_s_fmt_cap,
+ .g_fmt = tvp514x_fmt_cap,
+ .try_fmt = tvp514x_fmt_cap,
+ .s_fmt = tvp514x_fmt_cap,
.g_parm = tvp514x_g_parm,
.s_parm = tvp514x_s_parm,
.s_stream = tvp514x_s_stream,
@@ -1274,22 +1147,6 @@
static struct tvp514x_decoder tvp514x_dev = {
.streaming = 0,
-
- .fmt_list = tvp514x_fmt_list,
- .num_fmts = ARRAY_SIZE(tvp514x_fmt_list),
-
- .pix = {
- /* Default to NTSC 8-bit YUV 422 */
- .width = NTSC_NUM_ACTIVE_PIXELS,
- .height = NTSC_NUM_ACTIVE_LINES,
- .pixelformat = V4L2_PIX_FMT_UYVY,
- .field = V4L2_FIELD_INTERLACED,
- .bytesperline = NTSC_NUM_ACTIVE_PIXELS * 2,
- .sizeimage =
- NTSC_NUM_ACTIVE_PIXELS * 2 * NTSC_NUM_ACTIVE_LINES,
- .colorspace = V4L2_COLORSPACE_SMPTE170M,
- },
-
.current_std = STD_NTSC_MJ,
.std_list = tvp514x_std_list,
.num_stds = ARRAY_SIZE(tvp514x_std_list),
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c
index 47f0582..1654f65 100644
--- a/drivers/media/video/tvp5150.c
+++ b/drivers/media/video/tvp5150.c
@@ -934,17 +934,6 @@
return 0;
}
-static int tvp5150_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
-{
- switch (fmt->type) {
- case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
- return tvp5150_s_sliced_fmt(sd, &fmt->fmt.sliced);
-
- default:
- return -EINVAL;
- }
-}
-
static int tvp5150_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
{
int i, mask = 0;
@@ -960,13 +949,6 @@
return 0;
}
-static int tvp5150_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
-{
- if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
- return -EINVAL;
- return tvp5150_g_sliced_fmt(sd, &fmt->fmt.sliced);
-}
-
static int tvp5150_g_chip_ident(struct v4l2_subdev *sd,
struct v4l2_dbg_chip_ident *chip)
{
@@ -1054,8 +1036,6 @@
static const struct v4l2_subdev_video_ops tvp5150_video_ops = {
.s_routing = tvp5150_s_routing,
- .g_fmt = tvp5150_g_fmt,
- .s_fmt = tvp5150_s_fmt,
};
static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = {
diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c
index 76be733..445dc93 100644
--- a/drivers/media/video/tw9910.c
+++ b/drivers/media/video/tw9910.c
@@ -903,7 +903,7 @@
#endif
};
-static int tw9910_enum_fmt(struct v4l2_subdev *sd, int index,
+static int tw9910_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
enum v4l2_mbus_pixelcode *code)
{
if (index)
@@ -977,7 +977,6 @@
ret = tw9910_video_probe(icd, client);
if (ret) {
icd->ops = NULL;
- i2c_set_clientdata(client, NULL);
kfree(priv);
}
@@ -990,7 +989,6 @@
struct soc_camera_device *icd = client->dev.platform_data;
icd->ops = NULL;
- i2c_set_clientdata(client, NULL);
kfree(priv);
return 0;
}
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
index 6248a63..c2690df 100644
--- a/drivers/media/video/usbvision/usbvision-video.c
+++ b/drivers/media/video/usbvision/usbvision-video.c
@@ -1671,8 +1671,7 @@
PDEBUG(DBG_PROBE, "");
if (usbvision == NULL) {
- dev_err(&usbvision->dev->dev,
- "%s: usb_get_intfdata() failed\n", __func__);
+ pr_err("%s: usb_get_intfdata() failed\n", __func__);
return;
}
diff --git a/drivers/mfd/88pm860x-i2c.c b/drivers/mfd/88pm860x-i2c.c
index c933b64..bc02e6b 100644
--- a/drivers/mfd/88pm860x-i2c.c
+++ b/drivers/mfd/88pm860x-i2c.c
@@ -200,8 +200,6 @@
pm860x_device_exit(chip);
i2c_unregister_device(chip->companion);
- i2c_set_clientdata(chip->client, NULL);
- i2c_set_clientdata(client, NULL);
kfree(chip);
return 0;
}
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
index 53ebfee..66379b4 100644
--- a/drivers/mfd/ab3100-core.c
+++ b/drivers/mfd/ab3100-core.c
@@ -957,7 +957,6 @@
i2c_unregister_device(ab3100->testreg_client);
exit_no_testreg_client:
exit_no_detect:
- i2c_set_clientdata(client, NULL);
kfree(ab3100);
return err;
}
@@ -979,7 +978,6 @@
* their notifiers so deactivate IRQ
*/
free_irq(client->irq, ab3100);
- i2c_set_clientdata(client, NULL);
kfree(ab3100);
return 0;
}
diff --git a/drivers/mfd/ab3550-core.c b/drivers/mfd/ab3550-core.c
index 1060f8e..f54ab62 100644
--- a/drivers/mfd/ab3550-core.c
+++ b/drivers/mfd/ab3550-core.c
@@ -1362,7 +1362,6 @@
* their notifiers so deactivate IRQ
*/
free_irq(client->irq, ab);
- i2c_set_clientdata(client, NULL);
kfree(ab);
return 0;
}
diff --git a/drivers/mfd/adp5520.c b/drivers/mfd/adp5520.c
index 0055328..3122139 100644
--- a/drivers/mfd/adp5520.c
+++ b/drivers/mfd/adp5520.c
@@ -302,7 +302,6 @@
free_irq(chip->irq, chip);
out_free_chip:
- i2c_set_clientdata(client, NULL);
kfree(chip);
return ret;
@@ -317,7 +316,6 @@
adp5520_remove_subdevs(chip);
adp5520_write(chip->dev, ADP5520_MODE_STATUS, 0);
- i2c_set_clientdata(client, NULL);
kfree(chip);
return 0;
}
diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c
index 3ad915d..c07aece 100644
--- a/drivers/mfd/da903x.c
+++ b/drivers/mfd/da903x.c
@@ -534,7 +534,6 @@
out_free_irq:
free_irq(client->irq, chip);
out_free_chip:
- i2c_set_clientdata(client, NULL);
kfree(chip);
return ret;
}
@@ -544,7 +543,6 @@
struct da903x_chip *chip = i2c_get_clientdata(client);
da903x_remove_subdevs(chip);
- i2c_set_clientdata(client, NULL);
kfree(chip);
return 0;
}
diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c
index e73f3f5..0219115 100644
--- a/drivers/mfd/max8925-i2c.c
+++ b/drivers/mfd/max8925-i2c.c
@@ -173,7 +173,6 @@
max8925_device_exit(chip);
i2c_unregister_device(chip->adc);
i2c_unregister_device(chip->rtc);
- i2c_set_clientdata(chip->i2c, NULL);
kfree(chip);
return 0;
}
diff --git a/drivers/mfd/menelaus.c b/drivers/mfd/menelaus.c
index 721948b..a3fb4bc 100644
--- a/drivers/mfd/menelaus.c
+++ b/drivers/mfd/menelaus.c
@@ -1228,7 +1228,6 @@
free_irq(client->irq, menelaus);
flush_scheduled_work();
fail1:
- i2c_set_clientdata(client, NULL);
kfree(menelaus);
return err;
}
@@ -1238,7 +1237,6 @@
struct menelaus_chip *menelaus = i2c_get_clientdata(client);
free_irq(client->irq, menelaus);
- i2c_set_clientdata(client, NULL);
kfree(menelaus);
the_menelaus = NULL;
return 0;
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
index 704736e..23e5855 100644
--- a/drivers/mfd/pcf50633-core.c
+++ b/drivers/mfd/pcf50633-core.c
@@ -336,7 +336,6 @@
return 0;
err_free:
- i2c_set_clientdata(client, NULL);
kfree(pcf);
return ret;
@@ -357,7 +356,6 @@
for (i = 0; i < PCF50633_NUM_REGULATORS; i++)
platform_device_unregister(pcf->regulator_pdev[i]);
- i2c_set_clientdata(client, NULL);
kfree(pcf);
return 0;
diff --git a/drivers/mfd/tc35892.c b/drivers/mfd/tc35892.c
index 715f095..e619e2a 100644
--- a/drivers/mfd/tc35892.c
+++ b/drivers/mfd/tc35892.c
@@ -296,7 +296,6 @@
out_removeirq:
tc35892_irq_remove(tc35892);
out_free:
- i2c_set_clientdata(i2c, NULL);
kfree(tc35892);
return ret;
}
@@ -310,7 +309,6 @@
free_irq(tc35892->i2c->irq, tc35892);
tc35892_irq_remove(tc35892);
- i2c_set_clientdata(client, NULL);
kfree(tc35892);
return 0;
diff --git a/drivers/mfd/tps65010.c b/drivers/mfd/tps65010.c
index 9b22a77..d0016b6 100644
--- a/drivers/mfd/tps65010.c
+++ b/drivers/mfd/tps65010.c
@@ -530,7 +530,6 @@
cancel_delayed_work(&tps->work);
flush_scheduled_work();
debugfs_remove(tps->file);
- i2c_set_clientdata(client, NULL);
kfree(tps);
the_tps = NULL;
return 0;
diff --git a/drivers/mfd/wm8350-i2c.c b/drivers/mfd/wm8350-i2c.c
index 7795af4..5fe5de1 100644
--- a/drivers/mfd/wm8350-i2c.c
+++ b/drivers/mfd/wm8350-i2c.c
@@ -80,7 +80,6 @@
return ret;
err:
- i2c_set_clientdata(i2c, NULL);
kfree(wm8350);
return ret;
}
@@ -90,7 +89,6 @@
struct wm8350 *wm8350 = i2c_get_clientdata(i2c);
wm8350_device_exit(wm8350);
- i2c_set_clientdata(i2c, NULL);
kfree(wm8350);
return 0;
diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c
index e08aafa..1bfef48 100644
--- a/drivers/mfd/wm8400-core.c
+++ b/drivers/mfd/wm8400-core.c
@@ -415,7 +415,6 @@
return 0;
struct_err:
- i2c_set_clientdata(i2c, NULL);
kfree(wm8400);
err:
return ret;
@@ -426,7 +425,6 @@
struct wm8400 *wm8400 = i2c_get_clientdata(i2c);
wm8400_release(wm8400);
- i2c_set_clientdata(i2c, NULL);
kfree(wm8400);
return 0;
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index f7ca3a4..559b0b3 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -643,7 +643,6 @@
kfree(at24->writebuf);
kfree(at24);
- i2c_set_clientdata(client, NULL);
return 0;
}
diff --git a/drivers/misc/vmware_balloon.c b/drivers/misc/vmware_balloon.c
index db9cd02..2a1e804 100644
--- a/drivers/misc/vmware_balloon.c
+++ b/drivers/misc/vmware_balloon.c
@@ -45,7 +45,7 @@
MODULE_AUTHOR("VMware, Inc.");
MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver");
-MODULE_VERSION("1.2.1.0-K");
+MODULE_VERSION("1.2.1.1-k");
MODULE_ALIAS("dmi:*:svnVMware*:*");
MODULE_ALIAS("vmware_vmmemctl");
MODULE_LICENSE("GPL");
@@ -101,6 +101,8 @@
/* Maximum number of page allocations without yielding processor */
#define VMW_BALLOON_YIELD_THRESHOLD 1024
+/* Maximum number of refused pages we accumulate during inflation cycle */
+#define VMW_BALLOON_MAX_REFUSED 16
/*
* Hypervisor communication port definitions.
@@ -183,6 +185,7 @@
/* transient list of non-balloonable pages */
struct list_head refused_pages;
+ unsigned int n_refused_pages;
/* balloon size in pages */
unsigned int size;
@@ -428,14 +431,21 @@
/* inform monitor */
locked = vmballoon_send_lock_page(b, page_to_pfn(page));
if (!locked) {
+ STATS_INC(b->stats.refused_alloc);
+
if (b->reset_required) {
__free_page(page);
return -EIO;
}
- /* place on list of non-balloonable pages, retry allocation */
+ /*
+ * Place page on the list of non-balloonable pages
+ * and retry allocation, unless we already accumulated
+ * too many of them, in which case take a breather.
+ */
list_add(&page->lru, &b->refused_pages);
- STATS_INC(b->stats.refused_alloc);
+ if (++b->n_refused_pages >= VMW_BALLOON_MAX_REFUSED)
+ return -EIO;
}
} while (!locked);
@@ -483,6 +493,8 @@
__free_page(page);
STATS_INC(b->stats.refused_free);
}
+
+ b->n_refused_pages = 0;
}
/*
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index e171e77..f06d06e 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -249,7 +249,7 @@
config MMC_MSM7X00A
tristate "Qualcomm MSM 7X00A SDCC Controller Support"
- depends on MMC && ARCH_MSM
+ depends on MMC && ARCH_MSM && !ARCH_MSM7X30
help
This provides support for the SD/MMC cell found in the
MSM 7X00A controllers from Qualcomm.
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 2b28168..d98ddcf 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -1157,7 +1157,6 @@
mmc_omap_start_command(host, req->cmd);
if (host->dma_in_use)
omap_start_dma(host->dma_ch);
- BUG_ON(irqs_disabled());
}
static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req)
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index eb97830..5d3f824 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -30,25 +30,6 @@
#define DRIVER_NAME "sh_mmcif"
#define DRIVER_VERSION "2010-04-28"
-#define MMCIF_CE_CMD_SET 0x00000000
-#define MMCIF_CE_ARG 0x00000008
-#define MMCIF_CE_ARG_CMD12 0x0000000C
-#define MMCIF_CE_CMD_CTRL 0x00000010
-#define MMCIF_CE_BLOCK_SET 0x00000014
-#define MMCIF_CE_CLK_CTRL 0x00000018
-#define MMCIF_CE_BUF_ACC 0x0000001C
-#define MMCIF_CE_RESP3 0x00000020
-#define MMCIF_CE_RESP2 0x00000024
-#define MMCIF_CE_RESP1 0x00000028
-#define MMCIF_CE_RESP0 0x0000002C
-#define MMCIF_CE_RESP_CMD12 0x00000030
-#define MMCIF_CE_DATA 0x00000034
-#define MMCIF_CE_INT 0x00000040
-#define MMCIF_CE_INT_MASK 0x00000044
-#define MMCIF_CE_HOST_STS1 0x00000048
-#define MMCIF_CE_HOST_STS2 0x0000004C
-#define MMCIF_CE_VERSION 0x0000007C
-
/* CE_CMD_SET */
#define CMD_MASK 0x3f000000
#define CMD_SET_RTYP_NO ((0 << 23) | (0 << 22))
@@ -207,27 +188,17 @@
wait_queue_head_t intr_wait;
};
-static inline u32 sh_mmcif_readl(struct sh_mmcif_host *host, unsigned int reg)
-{
- return readl(host->addr + reg);
-}
-
-static inline void sh_mmcif_writel(struct sh_mmcif_host *host,
- unsigned int reg, u32 val)
-{
- writel(val, host->addr + reg);
-}
static inline void sh_mmcif_bitset(struct sh_mmcif_host *host,
unsigned int reg, u32 val)
{
- writel(val | sh_mmcif_readl(host, reg), host->addr + reg);
+ writel(val | readl(host->addr + reg), host->addr + reg);
}
static inline void sh_mmcif_bitclr(struct sh_mmcif_host *host,
unsigned int reg, u32 val)
{
- writel(~val & sh_mmcif_readl(host, reg), host->addr + reg);
+ writel(~val & readl(host->addr + reg), host->addr + reg);
}
@@ -253,10 +224,10 @@
{
u32 tmp;
- tmp = 0x010f0000 & sh_mmcif_readl(host, MMCIF_CE_CLK_CTRL);
+ tmp = 0x010f0000 & sh_mmcif_readl(host->addr, MMCIF_CE_CLK_CTRL);
- sh_mmcif_writel(host, MMCIF_CE_VERSION, SOFT_RST_ON);
- sh_mmcif_writel(host, MMCIF_CE_VERSION, SOFT_RST_OFF);
+ sh_mmcif_writel(host->addr, MMCIF_CE_VERSION, SOFT_RST_ON);
+ sh_mmcif_writel(host->addr, MMCIF_CE_VERSION, SOFT_RST_OFF);
sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, tmp |
SRSPTO_256 | SRBSYTO_29 | SRWDTO_29 | SCCSTO_29);
/* byte swap on */
@@ -271,12 +242,10 @@
host->sd_error = 0;
host->wait_int = 0;
- state1 = sh_mmcif_readl(host, MMCIF_CE_HOST_STS1);
- state2 = sh_mmcif_readl(host, MMCIF_CE_HOST_STS2);
- pr_debug("%s: ERR HOST_STS1 = %08x\n", \
- DRIVER_NAME, sh_mmcif_readl(host, MMCIF_CE_HOST_STS1));
- pr_debug("%s: ERR HOST_STS2 = %08x\n", \
- DRIVER_NAME, sh_mmcif_readl(host, MMCIF_CE_HOST_STS2));
+ state1 = sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS1);
+ state2 = sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS2);
+ pr_debug("%s: ERR HOST_STS1 = %08x\n", DRIVER_NAME, state1);
+ pr_debug("%s: ERR HOST_STS2 = %08x\n", DRIVER_NAME, state2);
if (state1 & STS1_CMDSEQ) {
sh_mmcif_bitset(host, MMCIF_CE_CMD_CTRL, CMD_CTRL_BREAK);
@@ -288,7 +257,7 @@
"command sequence timeout err\n");
return -EIO;
}
- if (!(sh_mmcif_readl(host, MMCIF_CE_HOST_STS1)
+ if (!(sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS1)
& STS1_CMDSEQ))
break;
mdelay(1);
@@ -330,9 +299,9 @@
host->wait_int = 0;
blocksize = (BLOCK_SIZE_MASK &
- sh_mmcif_readl(host, MMCIF_CE_BLOCK_SET)) + 3;
+ sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3;
for (i = 0; i < blocksize / 4; i++)
- *p++ = sh_mmcif_readl(host, MMCIF_CE_DATA);
+ *p++ = sh_mmcif_readl(host->addr, MMCIF_CE_DATA);
/* buffer read end */
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFRE);
@@ -353,7 +322,8 @@
long time;
u32 blocksize, i, j, sec, *p;
- blocksize = BLOCK_SIZE_MASK & sh_mmcif_readl(host, MMCIF_CE_BLOCK_SET);
+ blocksize = BLOCK_SIZE_MASK & sh_mmcif_readl(host->addr,
+ MMCIF_CE_BLOCK_SET);
for (j = 0; j < data->sg_len; j++) {
p = sg_virt(data->sg);
host->wait_int = 0;
@@ -370,7 +340,8 @@
host->wait_int = 0;
for (i = 0; i < blocksize / 4; i++)
- *p++ = sh_mmcif_readl(host, MMCIF_CE_DATA);
+ *p++ = sh_mmcif_readl(host->addr,
+ MMCIF_CE_DATA);
}
if (j < data->sg_len - 1)
data->sg++;
@@ -397,9 +368,9 @@
host->wait_int = 0;
blocksize = (BLOCK_SIZE_MASK &
- sh_mmcif_readl(host, MMCIF_CE_BLOCK_SET)) + 3;
+ sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3;
for (i = 0; i < blocksize / 4; i++)
- sh_mmcif_writel(host, MMCIF_CE_DATA, *p++);
+ sh_mmcif_writel(host->addr, MMCIF_CE_DATA, *p++);
/* buffer write end */
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MDTRANE);
@@ -421,7 +392,8 @@
long time;
u32 i, sec, j, blocksize, *p;
- blocksize = BLOCK_SIZE_MASK & sh_mmcif_readl(host, MMCIF_CE_BLOCK_SET);
+ blocksize = BLOCK_SIZE_MASK & sh_mmcif_readl(host->addr,
+ MMCIF_CE_BLOCK_SET);
for (j = 0; j < data->sg_len; j++) {
p = sg_virt(data->sg);
@@ -439,7 +411,8 @@
host->wait_int = 0;
for (i = 0; i < blocksize / 4; i++)
- sh_mmcif_writel(host, MMCIF_CE_DATA, *p++);
+ sh_mmcif_writel(host->addr,
+ MMCIF_CE_DATA, *p++);
}
if (j < data->sg_len - 1)
data->sg++;
@@ -451,18 +424,18 @@
struct mmc_command *cmd)
{
if (cmd->flags & MMC_RSP_136) {
- cmd->resp[0] = sh_mmcif_readl(host, MMCIF_CE_RESP3);
- cmd->resp[1] = sh_mmcif_readl(host, MMCIF_CE_RESP2);
- cmd->resp[2] = sh_mmcif_readl(host, MMCIF_CE_RESP1);
- cmd->resp[3] = sh_mmcif_readl(host, MMCIF_CE_RESP0);
+ cmd->resp[0] = sh_mmcif_readl(host->addr, MMCIF_CE_RESP3);
+ cmd->resp[1] = sh_mmcif_readl(host->addr, MMCIF_CE_RESP2);
+ cmd->resp[2] = sh_mmcif_readl(host->addr, MMCIF_CE_RESP1);
+ cmd->resp[3] = sh_mmcif_readl(host->addr, MMCIF_CE_RESP0);
} else
- cmd->resp[0] = sh_mmcif_readl(host, MMCIF_CE_RESP0);
+ cmd->resp[0] = sh_mmcif_readl(host->addr, MMCIF_CE_RESP0);
}
static void sh_mmcif_get_cmd12response(struct sh_mmcif_host *host,
struct mmc_command *cmd)
{
- cmd->resp[0] = sh_mmcif_readl(host, MMCIF_CE_RESP_CMD12);
+ cmd->resp[0] = sh_mmcif_readl(host->addr, MMCIF_CE_RESP_CMD12);
}
static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host,
@@ -596,18 +569,19 @@
MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO;
if (host->data) {
- sh_mmcif_writel(host, MMCIF_CE_BLOCK_SET, 0);
- sh_mmcif_writel(host, MMCIF_CE_BLOCK_SET, mrq->data->blksz);
+ sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET, 0);
+ sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET,
+ mrq->data->blksz);
}
opc = sh_mmcif_set_cmd(host, mrq, cmd, opc);
- sh_mmcif_writel(host, MMCIF_CE_INT, 0xD80430C0);
- sh_mmcif_writel(host, MMCIF_CE_INT_MASK, mask);
+ sh_mmcif_writel(host->addr, MMCIF_CE_INT, 0xD80430C0);
+ sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, mask);
/* set arg */
- sh_mmcif_writel(host, MMCIF_CE_ARG, cmd->arg);
+ sh_mmcif_writel(host->addr, MMCIF_CE_ARG, cmd->arg);
host->wait_int = 0;
/* set cmd */
- sh_mmcif_writel(host, MMCIF_CE_CMD_SET, opc);
+ sh_mmcif_writel(host->addr, MMCIF_CE_CMD_SET, opc);
time = wait_event_interruptible_timeout(host->intr_wait,
host->wait_int == 1 || host->sd_error == 1, host->timeout);
@@ -752,43 +726,44 @@
u32 state = 0;
int err = 0;
- state = sh_mmcif_readl(host, MMCIF_CE_INT);
+ state = sh_mmcif_readl(host->addr, MMCIF_CE_INT);
if (state & INT_RBSYE) {
- sh_mmcif_writel(host, MMCIF_CE_INT, ~(INT_RBSYE | INT_CRSPE));
+ sh_mmcif_writel(host->addr, MMCIF_CE_INT,
+ ~(INT_RBSYE | INT_CRSPE));
sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MRBSYE);
} else if (state & INT_CRSPE) {
- sh_mmcif_writel(host, MMCIF_CE_INT, ~INT_CRSPE);
+ sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_CRSPE);
sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCRSPE);
} else if (state & INT_BUFREN) {
- sh_mmcif_writel(host, MMCIF_CE_INT, ~INT_BUFREN);
+ sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_BUFREN);
sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
} else if (state & INT_BUFWEN) {
- sh_mmcif_writel(host, MMCIF_CE_INT, ~INT_BUFWEN);
+ sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_BUFWEN);
sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
} else if (state & INT_CMD12DRE) {
- sh_mmcif_writel(host, MMCIF_CE_INT,
+ sh_mmcif_writel(host->addr, MMCIF_CE_INT,
~(INT_CMD12DRE | INT_CMD12RBE |
INT_CMD12CRE | INT_BUFRE));
sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCMD12DRE);
} else if (state & INT_BUFRE) {
- sh_mmcif_writel(host, MMCIF_CE_INT, ~INT_BUFRE);
+ sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_BUFRE);
sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFRE);
} else if (state & INT_DTRANE) {
- sh_mmcif_writel(host, MMCIF_CE_INT, ~INT_DTRANE);
+ sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_DTRANE);
sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MDTRANE);
} else if (state & INT_CMD12RBE) {
- sh_mmcif_writel(host, MMCIF_CE_INT,
+ sh_mmcif_writel(host->addr, MMCIF_CE_INT,
~(INT_CMD12RBE | INT_CMD12CRE));
sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCMD12RBE);
} else if (state & INT_ERR_STS) {
/* err interrupts */
- sh_mmcif_writel(host, MMCIF_CE_INT, ~state);
+ sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state);
sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state);
err = 1;
} else {
pr_debug("%s: Not support int\n", DRIVER_NAME);
- sh_mmcif_writel(host, MMCIF_CE_INT, ~state);
+ sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state);
sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state);
err = 1;
}
@@ -894,12 +869,12 @@
goto clean_up2;
}
- sh_mmcif_writel(host, MMCIF_CE_INT_MASK, MASK_ALL);
+ sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
sh_mmcif_detect(host->mmc);
pr_info("%s: driver version %s\n", DRIVER_NAME, DRIVER_VERSION);
pr_debug("%s: chip ver H'%04x\n", DRIVER_NAME,
- sh_mmcif_readl(host, MMCIF_CE_VERSION) & 0x0000ffff);
+ sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff);
return ret;
clean_up2:
@@ -917,7 +892,7 @@
struct sh_mmcif_host *host = platform_get_drvdata(pdev);
int irq[2];
- sh_mmcif_writel(host, MMCIF_CE_INT_MASK, MASK_ALL);
+ sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
irq[0] = platform_get_irq(pdev, 0);
irq[1] = platform_get_irq(pdev, 1);
diff --git a/drivers/mtd/maps/pismo.c b/drivers/mtd/maps/pismo.c
index eb476b7..f4ce273 100644
--- a/drivers/mtd/maps/pismo.c
+++ b/drivers/mtd/maps/pismo.c
@@ -234,7 +234,6 @@
/* FIXME: set_vpp needs saner arguments */
pismo_setvpp_remove_fix(pismo);
- i2c_set_clientdata(client, NULL);
kfree(pismo);
return 0;
@@ -286,7 +285,6 @@
return 0;
exit_free:
- i2c_set_clientdata(client, NULL);
kfree(pismo);
return ret;
}
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 000d65ea..91c8013 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -404,14 +404,9 @@
if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))
return -EINVAL;
- ops.oobbuf = kmalloc(length, GFP_KERNEL);
- if (!ops.oobbuf)
- return -ENOMEM;
-
- if (copy_from_user(ops.oobbuf, ptr, length)) {
- kfree(ops.oobbuf);
- return -EFAULT;
- }
+ ops.oobbuf = memdup_user(ptr, length);
+ if (IS_ERR(ops.oobbuf))
+ return PTR_ERR(ops.oobbuf);
start &= ~((uint64_t)mtd->oobsize - 1);
ret = mtd->write_oob(mtd, start, &ops);
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 98a04b3..ffc3720 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -1,13 +1,3 @@
-menuconfig MTD_NAND
- tristate "NAND Device Support"
- depends on MTD
- select MTD_NAND_IDS
- select MTD_NAND_ECC
- help
- This enables support for accessing all type of NAND flash
- devices. For further information see
- <http://www.linux-mtd.infradead.org/doc/nand.html>.
-
config MTD_NAND_ECC
tristate
@@ -19,6 +9,17 @@
Software ECC according to the Smart Media Specification.
The original Linux implementation had byte 0 and 1 swapped.
+
+menuconfig MTD_NAND
+ tristate "NAND Device Support"
+ depends on MTD
+ select MTD_NAND_IDS
+ select MTD_NAND_ECC
+ help
+ This enables support for accessing all type of NAND flash
+ devices. For further information see
+ <http://www.linux-mtd.infradead.org/doc/nand.html>.
+
if MTD_NAND
config MTD_NAND_VERIFY_WRITE
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 00aea6f..1312eda 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -232,7 +232,7 @@
if (!fun)
return -ENOMEM;
- ret = of_address_to_resource(ofdev->node, 0, &io_res);
+ ret = of_address_to_resource(ofdev->dev.of_node, 0, &io_res);
if (ret) {
dev_err(&ofdev->dev, "can't get IO base\n");
goto err1;
@@ -244,7 +244,8 @@
goto err1;
}
- prop = of_get_property(ofdev->node, "fsl,upm-addr-offset", &size);
+ prop = of_get_property(ofdev->dev.of_node, "fsl,upm-addr-offset",
+ &size);
if (!prop || size != sizeof(uint32_t)) {
dev_err(&ofdev->dev, "can't get UPM address offset\n");
ret = -EINVAL;
@@ -252,7 +253,7 @@
}
fun->upm_addr_offset = *prop;
- prop = of_get_property(ofdev->node, "fsl,upm-cmd-offset", &size);
+ prop = of_get_property(ofdev->dev.of_node, "fsl,upm-cmd-offset", &size);
if (!prop || size != sizeof(uint32_t)) {
dev_err(&ofdev->dev, "can't get UPM command offset\n");
ret = -EINVAL;
@@ -260,7 +261,7 @@
}
fun->upm_cmd_offset = *prop;
- prop = of_get_property(ofdev->node,
+ prop = of_get_property(ofdev->dev.of_node,
"fsl,upm-addr-line-cs-offsets", &size);
if (prop && (size / sizeof(uint32_t)) > 0) {
fun->mchip_count = size / sizeof(uint32_t);
@@ -276,7 +277,7 @@
for (i = 0; i < fun->mchip_count; i++) {
fun->rnb_gpio[i] = -1;
- rnb_gpio = of_get_gpio(ofdev->node, i);
+ rnb_gpio = of_get_gpio(ofdev->dev.of_node, i);
if (rnb_gpio >= 0) {
ret = gpio_request(rnb_gpio, dev_name(&ofdev->dev));
if (ret) {
@@ -292,13 +293,13 @@
}
}
- prop = of_get_property(ofdev->node, "chip-delay", NULL);
+ prop = of_get_property(ofdev->dev.of_node, "chip-delay", NULL);
if (prop)
fun->chip_delay = *prop;
else
fun->chip_delay = 50;
- prop = of_get_property(ofdev->node, "fsl,upm-wait-flags", &size);
+ prop = of_get_property(ofdev->dev.of_node, "fsl,upm-wait-flags", &size);
if (prop && size == sizeof(uint32_t))
fun->wait_flags = *prop;
else
@@ -315,7 +316,7 @@
fun->dev = &ofdev->dev;
fun->last_ctrl = NAND_CLE;
- ret = fun_chip_init(fun, ofdev->node, &io_res);
+ ret = fun_chip_init(fun, ofdev->dev.of_node, &io_res);
if (ret)
goto err2;
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 3d0867d..0a130dc 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -650,7 +650,7 @@
static int __devinit mpc5121_nfc_probe(struct of_device *op,
const struct of_device_id *match)
{
- struct device_node *rootnode, *dn = op->node;
+ struct device_node *rootnode, *dn = op->dev.of_node;
struct device *dev = &op->dev;
struct mpc5121_nfc_prv *prv;
struct resource res;
@@ -889,12 +889,12 @@
};
static struct of_platform_driver mpc5121_nfc_driver = {
- .match_table = mpc5121_nfc_match,
.probe = mpc5121_nfc_probe,
.remove = __devexit_p(mpc5121_nfc_remove),
.driver = {
- .name = DRV_NAME,
- .owner = THIS_MODULE,
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = mpc5121_nfc_match,
},
};
diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c
index 78a4232..bcfc851 100644
--- a/drivers/mtd/nand/r852.c
+++ b/drivers/mtd/nand/r852.c
@@ -150,7 +150,6 @@
if (dev->phys_dma_addr && dev->phys_dma_addr != dev->phys_bounce_buffer)
pci_unmap_single(dev->pci_dev, dev->phys_dma_addr, R852_DMA_LEN,
dev->dma_dir ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
- complete(&dev->dma_done);
}
/*
@@ -182,6 +181,7 @@
/* Set dma direction */
dev->dma_dir = do_read;
dev->dma_stage = 1;
+ INIT_COMPLETION(dev->dma_done);
dbg_verbose("doing dma %s ", do_read ? "read" : "write");
@@ -494,6 +494,11 @@
if (dev->card_unstable)
return 0;
+ if (dev->dma_error) {
+ dev->dma_error = 0;
+ return -1;
+ }
+
r852_write_reg(dev, R852_CTL, dev->ctlreg | R852_CTL_ECC_ACCESS);
ecc_reg = r852_read_reg_dword(dev, R852_DATALINE);
r852_write_reg(dev, R852_CTL, dev->ctlreg);
@@ -707,6 +712,7 @@
container_of(work, struct r852_device, card_detect_work.work);
r852_card_update_present(dev);
+ r852_update_card_detect(dev);
dev->card_unstable = 0;
/* False alarm */
@@ -722,7 +728,6 @@
else
r852_unregister_nand_device(dev);
exit:
- /* Update detection logic */
r852_update_card_detect(dev);
}
@@ -796,6 +801,7 @@
if (dma_status & R852_DMA_IRQ_ERROR) {
dbg("recieved dma error IRQ");
r852_dma_done(dev, -EIO);
+ complete(&dev->dma_done);
goto out;
}
@@ -825,8 +831,10 @@
r852_dma_enable(dev);
/* Operation done */
- if (dev->dma_stage == 3)
+ if (dev->dma_stage == 3) {
r852_dma_done(dev, 0);
+ complete(&dev->dma_done);
+ }
goto out;
}
@@ -940,18 +948,19 @@
r852_dma_test(dev);
+ dev->irq = pci_dev->irq;
+ spin_lock_init(&dev->irqlock);
+
+ dev->card_detected = 0;
+ r852_card_update_present(dev);
+
/*register irq handler*/
error = -ENODEV;
if (request_irq(pci_dev->irq, &r852_irq, IRQF_SHARED,
DRV_NAME, dev))
goto error10;
- dev->irq = pci_dev->irq;
- spin_lock_init(&dev->irqlock);
-
/* kick initial present test */
- dev->card_detected = 0;
- r852_card_update_present(dev);
queue_delayed_work(dev->card_workqueue,
&dev->card_detect_work, 0);
@@ -1081,7 +1090,7 @@
dev->card_detected ? "added" : "removed");
queue_delayed_work(dev->card_workqueue,
- &dev->card_detect_work, 1000);
+ &dev->card_detect_work, msecs_to_jiffies(1000));
return 0;
}
diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c
index 884852d..cc728b1 100644
--- a/drivers/mtd/nand/socrates_nand.c
+++ b/drivers/mtd/nand/socrates_nand.c
@@ -183,7 +183,7 @@
return -ENOMEM;
}
- host->io_base = of_iomap(ofdev->node, 0);
+ host->io_base = of_iomap(ofdev->dev.of_node, 0);
if (host->io_base == NULL) {
printk(KERN_ERR "socrates_nand: ioremap failed\n");
kfree(host);
@@ -244,7 +244,7 @@
#ifdef CONFIG_MTD_OF_PARTS
if (num_partitions == 0) {
num_partitions = of_mtd_parse_partitions(&ofdev->dev,
- ofdev->node,
+ ofdev->dev.of_node,
&partitions);
if (num_partitions < 0) {
res = num_partitions;
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 9c14975..284a5f4 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -598,8 +598,8 @@
goto rx_status_loop;
spin_lock_irqsave(&cp->lock, flags);
- cpw16_f(IntrMask, cp_intr_mask);
__napi_complete(napi);
+ cpw16_f(IntrMask, cp_intr_mask);
spin_unlock_irqrestore(&cp->lock, flags);
}
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 4ba7293..97d8068 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -860,6 +860,7 @@
}
/* if unknown chip, assume array element #0, original RTL-8139 in this case */
+ i = 0;
dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n");
dev_dbg(&pdev->dev, "TxConfig = 0x%lx\n", RTL_R32 (TxConfig));
tp->chipset = 0;
@@ -2088,8 +2089,8 @@
* again when we think we are done.
*/
spin_lock_irqsave(&tp->lock, flags);
- RTL_W16_F(IntrMask, rtl8139_intr_mask);
__napi_complete(napi);
+ RTL_W16_F(IntrMask, rtl8139_intr_mask);
spin_unlock_irqrestore(&tp->lock, flags);
}
spin_unlock(&tp->rx_lock);
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 2decc59..ce2fcdd 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2754,6 +2754,7 @@
config NETXEN_NIC
tristate "NetXen Multi port (1/10) Gigabit Ethernet NIC"
depends on PCI
+ select FW_LOADER
help
This enables the support for NetXen's Gigabit Ethernet card.
@@ -2819,6 +2820,7 @@
config QLCNIC
tristate "QLOGIC QLCNIC 1/10Gb Converged Ethernet NIC Support"
depends on PCI
+ select FW_LOADER
help
This driver supports QLogic QLE8240 and QLE8242 Converged Ethernet
devices.
diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c
index 39250b2..959add2 100644
--- a/drivers/net/bmac.c
+++ b/drivers/net/bmac.c
@@ -1654,8 +1654,11 @@
static struct macio_driver bmac_driver =
{
- .name = "bmac",
- .match_table = bmac_match,
+ .driver = {
+ .name = "bmac",
+ .owner = THIS_MODULE,
+ .of_match_table = bmac_match,
+ },
.probe = bmac_probe,
.remove = bmac_remove,
#ifdef CONFIG_PM
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 188e356..1174322 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -247,6 +247,7 @@
MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl);
static void bnx2_init_napi(struct bnx2 *bp);
+static void bnx2_del_napi(struct bnx2 *bp);
static inline u32 bnx2_tx_avail(struct bnx2 *bp, struct bnx2_tx_ring_info *txr)
{
@@ -3072,7 +3073,6 @@
u16 hw_cons, sw_cons, sw_ring_cons, sw_prod, sw_ring_prod;
struct l2_fhdr *rx_hdr;
int rx_pkt = 0, pg_ring_used = 0;
- struct pci_dev *pdev = bp->pdev;
hw_cons = bnx2_get_hw_rx_cons(bnapi);
sw_cons = rxr->rx_cons;
@@ -3098,12 +3098,10 @@
skb = rx_buf->skb;
prefetchw(skb);
- if (!get_dma_ops(&pdev->dev)->sync_single_for_cpu) {
- next_rx_buf =
- &rxr->rx_buf_ring[
- RX_RING_IDX(NEXT_RX_BD(sw_cons))];
- prefetch(next_rx_buf->desc);
- }
+ next_rx_buf =
+ &rxr->rx_buf_ring[RX_RING_IDX(NEXT_RX_BD(sw_cons))];
+ prefetch(next_rx_buf->desc);
+
rx_buf->skb = NULL;
dma_addr = dma_unmap_addr(rx_buf, mapping);
@@ -6270,6 +6268,7 @@
bnx2_free_skbs(bp);
bnx2_free_irq(bp);
bnx2_free_mem(bp);
+ bnx2_del_napi(bp);
return rc;
}
@@ -6537,6 +6536,7 @@
bnx2_free_irq(bp);
bnx2_free_skbs(bp);
bnx2_free_mem(bp);
+ bnx2_del_napi(bp);
bp->link_up = 0;
netif_carrier_off(bp->dev);
bnx2_set_power_state(bp, PCI_D3hot);
@@ -8227,7 +8227,16 @@
return str;
}
-static void __devinit
+static void
+bnx2_del_napi(struct bnx2 *bp)
+{
+ int i;
+
+ for (i = 0; i < bp->irq_nvecs; i++)
+ netif_napi_del(&bp->bnx2_napi[i].napi);
+}
+
+static void
bnx2_init_napi(struct bnx2 *bp)
{
int i;
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index fe92566..8047126 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -3919,8 +3919,9 @@
HC_INDEX_DEF_C_ETH_ISCSI_CQ_CONS;
context->cstorm_st_context.status_block_id = BNX2X_DEF_SB_ID;
- context->xstorm_st_context.statistics_data = (cli |
- XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE);
+ if (cli < MAX_X_STAT_COUNTER_ID)
+ context->xstorm_st_context.statistics_data = cli |
+ XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE;
context->xstorm_ag_context.cdu_reserved =
CDU_RSRVD_VALUE_TYPE_A(BNX2X_HW_CID(BNX2X_ISCSI_L2_CID, func),
@@ -3928,10 +3929,12 @@
ETH_CONNECTION_TYPE);
/* reset xstorm per client statistics */
- val = BAR_XSTRORM_INTMEM +
- XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
- for (i = 0; i < sizeof(struct xstorm_per_client_stats) / 4; i++)
- CNIC_WR(dev, val + i * 4, 0);
+ if (cli < MAX_X_STAT_COUNTER_ID) {
+ val = BAR_XSTRORM_INTMEM +
+ XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
+ for (i = 0; i < sizeof(struct xstorm_per_client_stats) / 4; i++)
+ CNIC_WR(dev, val + i * 4, 0);
+ }
cp->tx_cons_ptr =
&cp->bnx2x_def_status_blk->c_def_status_block.index_values[
@@ -3978,9 +3981,11 @@
BNX2X_ISCSI_RX_SB_INDEX_NUM;
context->ustorm_st_context.common.clientId = cli;
context->ustorm_st_context.common.status_block_id = BNX2X_DEF_SB_ID;
- context->ustorm_st_context.common.flags =
- USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS;
- context->ustorm_st_context.common.statistics_counter_id = cli;
+ if (cli < MAX_U_STAT_COUNTER_ID) {
+ context->ustorm_st_context.common.flags =
+ USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS;
+ context->ustorm_st_context.common.statistics_counter_id = cli;
+ }
context->ustorm_st_context.common.mc_alignment_log_size = 0;
context->ustorm_st_context.common.bd_buff_size =
cp->l2_single_buf_size;
@@ -4011,10 +4016,13 @@
/* client tstorm info */
tstorm_client.mtu = cp->l2_single_buf_size - 14;
- tstorm_client.config_flags =
- (TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE |
- TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE);
- tstorm_client.statistics_counter_id = cli;
+ tstorm_client.config_flags = TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE;
+
+ if (cli < MAX_T_STAT_COUNTER_ID) {
+ tstorm_client.config_flags |=
+ TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE;
+ tstorm_client.statistics_counter_id = cli;
+ }
CNIC_WR(dev, BAR_TSTRORM_INTMEM +
TSTORM_CLIENT_CONFIG_OFFSET(port, cli),
@@ -4024,16 +4032,21 @@
((u32 *)&tstorm_client)[1]);
/* reset tstorm per client statistics */
- val = BAR_TSTRORM_INTMEM +
- TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
- for (i = 0; i < sizeof(struct tstorm_per_client_stats) / 4; i++)
- CNIC_WR(dev, val + i * 4, 0);
+ if (cli < MAX_T_STAT_COUNTER_ID) {
+
+ val = BAR_TSTRORM_INTMEM +
+ TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
+ for (i = 0; i < sizeof(struct tstorm_per_client_stats) / 4; i++)
+ CNIC_WR(dev, val + i * 4, 0);
+ }
/* reset ustorm per client statistics */
- val = BAR_USTRORM_INTMEM +
- USTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
- for (i = 0; i < sizeof(struct ustorm_per_client_stats) / 4; i++)
- CNIC_WR(dev, val + i * 4, 0);
+ if (cli < MAX_U_STAT_COUNTER_ID) {
+ val = BAR_USTRORM_INTMEM +
+ USTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
+ for (i = 0; i < sizeof(struct ustorm_per_client_stats) / 4; i++)
+ CNIC_WR(dev, val + i * 4, 0);
+ }
cp->rx_cons_ptr =
&cp->bnx2x_def_status_blk->u_def_status_block.index_values[
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
index 3c58db5..23786ee 100644
--- a/drivers/net/cpmac.c
+++ b/drivers/net/cpmac.c
@@ -1181,7 +1181,8 @@
if (netif_msg_drv(priv))
printk(KERN_ERR "%s: Could not attach to PHY\n",
dev->name);
- return PTR_ERR(priv->phy);
+ rc = PTR_ERR(priv->phy);
+ goto fail;
}
if ((rc = register_netdev(dev))) {
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index ebdea08..68a8089 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -1047,15 +1047,14 @@
goto err_register;
/* print bus type/speed/width info */
- e_info("(PCI%s:%s:%s) ",
- ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""),
- ((hw->bus_speed == e1000_bus_speed_133) ? "133MHz" :
- (hw->bus_speed == e1000_bus_speed_120) ? "120MHz" :
- (hw->bus_speed == e1000_bus_speed_100) ? "100MHz" :
- (hw->bus_speed == e1000_bus_speed_66) ? "66MHz" : "33MHz"),
- ((hw->bus_width == e1000_bus_width_64) ? "64-bit" : "32-bit"));
-
- e_info("%pM\n", netdev->dev_addr);
+ e_info("(PCI%s:%dMHz:%d-bit) %pM\n",
+ ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""),
+ ((hw->bus_speed == e1000_bus_speed_133) ? 133 :
+ (hw->bus_speed == e1000_bus_speed_120) ? 120 :
+ (hw->bus_speed == e1000_bus_speed_100) ? 100 :
+ (hw->bus_speed == e1000_bus_speed_66) ? 66 : 33),
+ ((hw->bus_width == e1000_bus_width_64) ? 64 : 32),
+ netdev->dev_addr);
/* carrier off reporting is important to ethtool even BEFORE open */
netif_carrier_off(netdev);
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 24507f3..57a7e41 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -2554,7 +2554,7 @@
mdef = er32(MDEF(i));
/* Ignore filters with anything other than IPMI ports */
- if (mdef & !(E1000_MDEF_PORT_623 | E1000_MDEF_PORT_664))
+ if (mdef & ~(E1000_MDEF_PORT_623 | E1000_MDEF_PORT_664))
continue;
/* Enable this decision filter in MANC2H */
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 0630980..0060e42 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -40,7 +40,7 @@
#include <asm/io.h>
#define DRV_NAME "ehea"
-#define DRV_VERSION "EHEA_0103"
+#define DRV_VERSION "EHEA_0105"
/* eHEA capability flags */
#define DLPAR_PORT_ADD_REM 1
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index f547894..8b92acb 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -867,6 +867,7 @@
ehea_reset_cq_ep(pr->send_cq);
ehea_reset_cq_n1(pr->recv_cq);
ehea_reset_cq_n1(pr->send_cq);
+ rmb();
cqe = ehea_poll_rq1(pr->qp, &wqe_index);
cqe_skb = ehea_poll_cq(pr->send_cq);
@@ -2859,6 +2860,7 @@
container_of(work, struct ehea_port, reset_task);
struct net_device *dev = port->netdev;
+ mutex_lock(&dlpar_mem_lock);
port->resets++;
mutex_lock(&port->port_lock);
netif_stop_queue(dev);
@@ -2881,6 +2883,7 @@
netif_wake_queue(dev);
out:
mutex_unlock(&port->port_lock);
+ mutex_unlock(&dlpar_mem_lock);
}
static void ehea_rereg_mrs(struct work_struct *work)
@@ -3542,10 +3545,7 @@
int ret = NOTIFY_BAD;
struct memory_notify *arg = data;
- if (!mutex_trylock(&dlpar_mem_lock)) {
- ehea_info("ehea_mem_notifier must not be called parallelized");
- goto out;
- }
+ mutex_lock(&dlpar_mem_lock);
switch (action) {
case MEM_CANCEL_OFFLINE:
@@ -3574,7 +3574,6 @@
out_unlock:
mutex_unlock(&dlpar_mem_lock);
-out:
return ret;
}
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
index 85f2a2e7..45e86d1 100644
--- a/drivers/net/enic/enic.h
+++ b/drivers/net/enic/enic.h
@@ -74,7 +74,14 @@
void *devid;
};
+#define ENIC_SET_APPLIED (1 << 0)
+#define ENIC_SET_REQUEST (1 << 1)
+#define ENIC_SET_NAME (1 << 2)
+#define ENIC_SET_INSTANCE (1 << 3)
+#define ENIC_SET_HOST (1 << 4)
+
struct enic_port_profile {
+ u32 set;
u8 request;
char name[PORT_PROFILE_MAX];
u8 instance_uuid[PORT_UUID_MAX];
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index 6586b5c..bc7d6b9 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -1029,8 +1029,7 @@
return err;
}
-static int enic_set_port_profile(struct enic *enic, u8 request, u8 *mac,
- char *name, u8 *instance_uuid, u8 *host_uuid)
+static int enic_set_port_profile(struct enic *enic, u8 *mac)
{
struct vic_provinfo *vp;
u8 oui[3] = VIC_PROVINFO_CISCO_OUI;
@@ -1040,97 +1039,112 @@
"%02X%02X-%02X%02X%02X%02X%0X%02X";
int err;
- if (!name)
- return -EINVAL;
-
- if (!is_valid_ether_addr(mac))
- return -EADDRNOTAVAIL;
-
- vp = vic_provinfo_alloc(GFP_KERNEL, oui, VIC_PROVINFO_LINUX_TYPE);
- if (!vp)
- return -ENOMEM;
-
- vic_provinfo_add_tlv(vp,
- VIC_LINUX_PROV_TLV_PORT_PROFILE_NAME_STR,
- strlen(name) + 1, name);
-
- vic_provinfo_add_tlv(vp,
- VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR,
- ETH_ALEN, mac);
-
- if (instance_uuid) {
- uuid = instance_uuid;
- sprintf(uuid_str, uuid_fmt,
- uuid[0], uuid[1], uuid[2], uuid[3],
- uuid[4], uuid[5], uuid[6], uuid[7],
- uuid[8], uuid[9], uuid[10], uuid[11],
- uuid[12], uuid[13], uuid[14], uuid[15]);
- vic_provinfo_add_tlv(vp,
- VIC_LINUX_PROV_TLV_CLIENT_UUID_STR,
- sizeof(uuid_str), uuid_str);
- }
-
- if (host_uuid) {
- uuid = host_uuid;
- sprintf(uuid_str, uuid_fmt,
- uuid[0], uuid[1], uuid[2], uuid[3],
- uuid[4], uuid[5], uuid[6], uuid[7],
- uuid[8], uuid[9], uuid[10], uuid[11],
- uuid[12], uuid[13], uuid[14], uuid[15]);
- vic_provinfo_add_tlv(vp,
- VIC_LINUX_PROV_TLV_HOST_UUID_STR,
- sizeof(uuid_str), uuid_str);
- }
-
err = enic_vnic_dev_deinit(enic);
if (err)
- goto err_out;
+ return err;
- memset(&enic->pp, 0, sizeof(enic->pp));
+ switch (enic->pp.request) {
- err = enic_dev_init_prov(enic, vp);
- if (err)
- goto err_out;
+ case PORT_REQUEST_ASSOCIATE:
- enic->pp.request = request;
- memcpy(enic->pp.name, name, PORT_PROFILE_MAX);
- if (instance_uuid)
- memcpy(enic->pp.instance_uuid,
- instance_uuid, PORT_UUID_MAX);
- if (host_uuid)
- memcpy(enic->pp.host_uuid,
- host_uuid, PORT_UUID_MAX);
+ if (!(enic->pp.set & ENIC_SET_NAME) || !strlen(enic->pp.name))
+ return -EINVAL;
-err_out:
- vic_provinfo_free(vp);
+ if (!is_valid_ether_addr(mac))
+ return -EADDRNOTAVAIL;
- return err;
-}
+ vp = vic_provinfo_alloc(GFP_KERNEL, oui,
+ VIC_PROVINFO_LINUX_TYPE);
+ if (!vp)
+ return -ENOMEM;
-static int enic_unset_port_profile(struct enic *enic)
-{
- memset(&enic->pp, 0, sizeof(enic->pp));
- return enic_vnic_dev_deinit(enic);
+ vic_provinfo_add_tlv(vp,
+ VIC_LINUX_PROV_TLV_PORT_PROFILE_NAME_STR,
+ strlen(enic->pp.name) + 1, enic->pp.name);
+
+ vic_provinfo_add_tlv(vp,
+ VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR,
+ ETH_ALEN, mac);
+
+ if (enic->pp.set & ENIC_SET_INSTANCE) {
+ uuid = enic->pp.instance_uuid;
+ sprintf(uuid_str, uuid_fmt,
+ uuid[0], uuid[1], uuid[2], uuid[3],
+ uuid[4], uuid[5], uuid[6], uuid[7],
+ uuid[8], uuid[9], uuid[10], uuid[11],
+ uuid[12], uuid[13], uuid[14], uuid[15]);
+ vic_provinfo_add_tlv(vp,
+ VIC_LINUX_PROV_TLV_CLIENT_UUID_STR,
+ sizeof(uuid_str), uuid_str);
+ }
+
+ if (enic->pp.set & ENIC_SET_HOST) {
+ uuid = enic->pp.host_uuid;
+ sprintf(uuid_str, uuid_fmt,
+ uuid[0], uuid[1], uuid[2], uuid[3],
+ uuid[4], uuid[5], uuid[6], uuid[7],
+ uuid[8], uuid[9], uuid[10], uuid[11],
+ uuid[12], uuid[13], uuid[14], uuid[15]);
+ vic_provinfo_add_tlv(vp,
+ VIC_LINUX_PROV_TLV_HOST_UUID_STR,
+ sizeof(uuid_str), uuid_str);
+ }
+
+ err = enic_dev_init_prov(enic, vp);
+ vic_provinfo_free(vp);
+ if (err)
+ return err;
+ break;
+
+ case PORT_REQUEST_DISASSOCIATE:
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ enic->pp.set |= ENIC_SET_APPLIED;
+ return 0;
}
static int enic_set_vf_port(struct net_device *netdev, int vf,
struct nlattr *port[])
{
struct enic *enic = netdev_priv(netdev);
- char *name = NULL;
- u8 *instance_uuid = NULL;
- u8 *host_uuid = NULL;
- u8 request = PORT_REQUEST_DISASSOCIATE;
+
+ memset(&enic->pp, 0, sizeof(enic->pp));
+
+ if (port[IFLA_PORT_REQUEST]) {
+ enic->pp.set |= ENIC_SET_REQUEST;
+ enic->pp.request = nla_get_u8(port[IFLA_PORT_REQUEST]);
+ }
+
+ if (port[IFLA_PORT_PROFILE]) {
+ enic->pp.set |= ENIC_SET_NAME;
+ memcpy(enic->pp.name, nla_data(port[IFLA_PORT_PROFILE]),
+ PORT_PROFILE_MAX);
+ }
+
+ if (port[IFLA_PORT_INSTANCE_UUID]) {
+ enic->pp.set |= ENIC_SET_INSTANCE;
+ memcpy(enic->pp.instance_uuid,
+ nla_data(port[IFLA_PORT_INSTANCE_UUID]), PORT_UUID_MAX);
+ }
+
+ if (port[IFLA_PORT_HOST_UUID]) {
+ enic->pp.set |= ENIC_SET_HOST;
+ memcpy(enic->pp.host_uuid,
+ nla_data(port[IFLA_PORT_HOST_UUID]), PORT_UUID_MAX);
+ }
/* don't support VFs, yet */
if (vf != PORT_SELF_VF)
return -EOPNOTSUPP;
- if (port[IFLA_PORT_REQUEST])
- request = nla_get_u8(port[IFLA_PORT_REQUEST]);
+ if (!(enic->pp.set & ENIC_SET_REQUEST))
+ return -EOPNOTSUPP;
- switch (request) {
- case PORT_REQUEST_ASSOCIATE:
+ if (enic->pp.request == PORT_REQUEST_ASSOCIATE) {
/* If the interface mac addr hasn't been assigned,
* assign a random mac addr before setting port-
@@ -1139,30 +1153,9 @@
if (is_zero_ether_addr(netdev->dev_addr))
random_ether_addr(netdev->dev_addr);
-
- if (port[IFLA_PORT_PROFILE])
- name = nla_data(port[IFLA_PORT_PROFILE]);
-
- if (port[IFLA_PORT_INSTANCE_UUID])
- instance_uuid =
- nla_data(port[IFLA_PORT_INSTANCE_UUID]);
-
- if (port[IFLA_PORT_HOST_UUID])
- host_uuid = nla_data(port[IFLA_PORT_HOST_UUID]);
-
- return enic_set_port_profile(enic, request,
- netdev->dev_addr, name,
- instance_uuid, host_uuid);
-
- case PORT_REQUEST_DISASSOCIATE:
-
- return enic_unset_port_profile(enic);
-
- default:
- break;
}
- return -EOPNOTSUPP;
+ return enic_set_port_profile(enic, netdev->dev_addr);
}
static int enic_get_vf_port(struct net_device *netdev, int vf,
@@ -1172,14 +1165,12 @@
int err, error, done;
u16 response = PORT_PROFILE_RESPONSE_SUCCESS;
- /* don't support VFs, yet */
- if (vf != PORT_SELF_VF)
- return -EOPNOTSUPP;
+ if (!(enic->pp.set & ENIC_SET_APPLIED))
+ return -ENODATA;
err = enic_dev_init_done(enic, &done, &error);
-
if (err)
- return err;
+ error = err;
switch (error) {
case ERR_SUCCESS:
@@ -1202,12 +1193,15 @@
NLA_PUT_U16(skb, IFLA_PORT_REQUEST, enic->pp.request);
NLA_PUT_U16(skb, IFLA_PORT_RESPONSE, response);
- NLA_PUT(skb, IFLA_PORT_PROFILE, PORT_PROFILE_MAX,
- enic->pp.name);
- NLA_PUT(skb, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX,
- enic->pp.instance_uuid);
- NLA_PUT(skb, IFLA_PORT_HOST_UUID, PORT_UUID_MAX,
- enic->pp.host_uuid);
+ if (enic->pp.set & ENIC_SET_NAME)
+ NLA_PUT(skb, IFLA_PORT_PROFILE, PORT_PROFILE_MAX,
+ enic->pp.name);
+ if (enic->pp.set & ENIC_SET_INSTANCE)
+ NLA_PUT(skb, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX,
+ enic->pp.instance_uuid);
+ if (enic->pp.set & ENIC_SET_HOST)
+ NLA_PUT(skb, IFLA_PORT_HOST_UUID, PORT_UUID_MAX,
+ enic->pp.host_uuid);
return 0;
diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c
index 2b3e16d..e0d3328 100644
--- a/drivers/net/enic/vnic_dev.c
+++ b/drivers/net/enic/vnic_dev.c
@@ -709,7 +709,7 @@
{
u64 a0, a1 = len;
int wait = 1000;
- u64 prov_pa;
+ dma_addr_t prov_pa;
void *prov_buf;
int ret;
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index 6838dfc..4c27465 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -87,6 +87,7 @@
#include <linux/bitops.h>
#include <asm/io.h>
#include <asm/uaccess.h>
+#include <asm/byteorder.h>
/* These identify the driver base version and may not be removed. */
static char version[] __devinitdata =
@@ -230,7 +231,7 @@
* The EPIC100 Rx and Tx buffer descriptors. Note that these
* really ARE host-endian; it's not a misannotation. We tell
* the card to byteswap them internally on big-endian hosts -
- * look for #ifdef CONFIG_BIG_ENDIAN in epic_open().
+ * look for #ifdef __BIG_ENDIAN in epic_open().
*/
struct epic_tx_desc {
@@ -690,7 +691,7 @@
outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
/* Tell the chip to byteswap descriptors on big-endian hosts */
-#ifdef CONFIG_BIG_ENDIAN
+#ifdef __BIG_ENDIAN
outl(0x4432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
inl(ioaddr + GENCTL);
outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
@@ -806,7 +807,7 @@
for (i = 16; i > 0; i--)
outl(0x0008, ioaddr + TEST1);
-#ifdef CONFIG_BIG_ENDIAN
+#ifdef __BIG_ENDIAN
outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
#else
outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index ddf7a86..edfff92 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -1373,10 +1373,9 @@
if (ndev) {
fep = netdev_priv(ndev);
- if (netif_running(ndev)) {
- netif_device_detach(ndev);
- fec_stop(ndev);
- }
+ if (netif_running(ndev))
+ fec_enet_close(ndev);
+ clk_disable(fep->clk);
}
return 0;
}
@@ -1385,12 +1384,13 @@
fec_resume(struct platform_device *dev)
{
struct net_device *ndev = platform_get_drvdata(dev);
+ struct fec_enet_private *fep;
if (ndev) {
- if (netif_running(ndev)) {
- fec_enet_init(ndev, 0);
- netif_device_attach(ndev);
- }
+ fep = netdev_priv(ndev);
+ clk_enable(fep->clk);
+ if (netif_running(ndev))
+ fec_enet_open(ndev);
}
return 0;
}
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c
index 0f90685..3607340 100644
--- a/drivers/net/fs_enet/mii-bitbang.c
+++ b/drivers/net/fs_enet/mii-bitbang.c
@@ -169,7 +169,7 @@
new_bus->name = "CPM2 Bitbanged MII",
- ret = fs_mii_bitbang_init(new_bus, ofdev->node);
+ ret = fs_mii_bitbang_init(new_bus, ofdev->dev.of_node);
if (ret)
goto out_free_bus;
@@ -181,7 +181,7 @@
new_bus->parent = &ofdev->dev;
dev_set_drvdata(&ofdev->dev, new_bus);
- ret = of_mdiobus_register(new_bus, ofdev->node);
+ ret = of_mdiobus_register(new_bus, ofdev->dev.of_node);
if (ret)
goto out_free_irqs;
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 1830f31..28b53d1 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -381,10 +381,14 @@
/* Insert receive time stamps into padding alignment bytes */
if (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER) {
rctrl &= ~RCTRL_PAL_MASK;
- rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE | RCTRL_PADDING(8);
+ rctrl |= RCTRL_PADDING(8);
priv->padding = 8;
}
+ /* Enable HW time stamping if requested from user space */
+ if (priv->hwts_rx_en)
+ rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE;
+
/* keep vlan related bits if it's enabled */
if (priv->vlgrp) {
rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT;
@@ -806,12 +810,20 @@
switch (config.rx_filter) {
case HWTSTAMP_FILTER_NONE:
- priv->hwts_rx_en = 0;
+ if (priv->hwts_rx_en) {
+ stop_gfar(netdev);
+ priv->hwts_rx_en = 0;
+ startup_gfar(netdev);
+ }
break;
default:
if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER))
return -ERANGE;
- priv->hwts_rx_en = 1;
+ if (!priv->hwts_rx_en) {
+ stop_gfar(netdev);
+ priv->hwts_rx_en = 1;
+ startup_gfar(netdev);
+ }
config.rx_filter = HWTSTAMP_FILTER_ALL;
break;
}
@@ -2643,6 +2655,10 @@
dma_unmap_single(&priv->ofdev->dev, bdp->bufPtr,
priv->rx_buffer_size, DMA_FROM_DEVICE);
+ if (unlikely(!(bdp->status & RXBD_ERR) &&
+ bdp->length > priv->rx_buffer_size))
+ bdp->status = RXBD_LARGE;
+
/* We drop the frame if we failed to allocate a new buffer */
if (unlikely(!newskb || !(bdp->status & RXBD_LAST) ||
bdp->status & RXBD_ERR)) {
diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c
index 1159d91..9595b1b 100644
--- a/drivers/net/ixgbe/ixgbe_common.c
+++ b/drivers/net/ixgbe/ixgbe_common.c
@@ -1188,6 +1188,7 @@
IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
} else {
hw_dbg(hw, "RAR index %d is out of range.\n", index);
+ return IXGBE_ERR_RAR_INDEX;
}
return 0;
@@ -1219,6 +1220,7 @@
IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
} else {
hw_dbg(hw, "RAR index %d is out of range.\n", index);
+ return IXGBE_ERR_RAR_INDEX;
}
/* clear VMDq pool/queue selection for this RAR */
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index c50a754..3a93a81 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -2077,25 +2077,6 @@
return 0;
}
-/*
- * this function must be called before setting the new value of
- * rx_itr_setting
- */
-static bool ixgbe_reenable_rsc(struct ixgbe_adapter *adapter,
- struct ethtool_coalesce *ec)
-{
- /* check the old value and enable RSC if necessary */
- if ((adapter->rx_itr_setting == 0) &&
- (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)) {
- adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
- adapter->netdev->features |= NETIF_F_LRO;
- DPRINTK(PROBE, INFO, "rx-usecs set to %d, re-enabling RSC\n",
- ec->rx_coalesce_usecs);
- return true;
- }
- return false;
-}
-
static int ixgbe_set_coalesce(struct net_device *netdev,
struct ethtool_coalesce *ec)
{
@@ -2124,9 +2105,6 @@
(1000000/ec->rx_coalesce_usecs < IXGBE_MIN_INT_RATE))
return -EINVAL;
- /* check the old value and enable RSC if necessary */
- need_reset = ixgbe_reenable_rsc(adapter, ec);
-
/* store the value in ints/second */
adapter->rx_eitr_param = 1000000/ec->rx_coalesce_usecs;
@@ -2135,9 +2113,6 @@
/* clear the lower bit as its used for dynamic state */
adapter->rx_itr_setting &= ~1;
} else if (ec->rx_coalesce_usecs == 1) {
- /* check the old value and enable RSC if necessary */
- need_reset = ixgbe_reenable_rsc(adapter, ec);
-
/* 1 means dynamic mode */
adapter->rx_eitr_param = 20000;
adapter->rx_itr_setting = 1;
@@ -2157,10 +2132,11 @@
*/
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED;
- netdev->features &= ~NETIF_F_LRO;
- DPRINTK(PROBE, INFO,
- "rx-usecs set to 0, disabling RSC\n");
-
+ if (netdev->features & NETIF_F_LRO) {
+ netdev->features &= ~NETIF_F_LRO;
+ DPRINTK(PROBE, INFO, "rx-usecs set to 0, "
+ "disabling LRO/RSC\n");
+ }
need_reset = true;
}
}
@@ -2255,6 +2231,9 @@
}
} else if (!adapter->rx_itr_setting) {
netdev->features &= ~ETH_FLAG_LRO;
+ if (data & ETH_FLAG_LRO)
+ DPRINTK(PROBE, INFO, "rx-usecs set to 0, "
+ "LRO/RSC cannot be enabled.\n");
}
}
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index d571d10..ce30c62 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -642,7 +642,7 @@
u32 txoff = IXGBE_TFCS_TXOFF;
#ifdef CONFIG_IXGBE_DCB
- if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
+ if (adapter->dcb_cfg.pfc_mode_enable) {
int tc;
int reg_idx = tx_ring->reg_idx;
int dcb_i = adapter->ring_feature[RING_F_DCB].indices;
@@ -5282,6 +5282,10 @@
u32 i, missed_rx = 0, mpc, bprc, lxon, lxoff, xon_off_tot;
u64 non_eop_descs = 0, restart_queue = 0;
+ if (test_bit(__IXGBE_DOWN, &adapter->state) ||
+ test_bit(__IXGBE_RESETTING, &adapter->state))
+ return;
+
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
u64 rsc_count = 0;
u64 rsc_flush = 0;
diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c
index 09e1911..48325a5 100644
--- a/drivers/net/ixgbe/ixgbe_phy.c
+++ b/drivers/net/ixgbe/ixgbe_phy.c
@@ -575,6 +575,8 @@
* 4 SFP_DA_CORE1 - 82599-specific
* 5 SFP_SR/LR_CORE0 - 82599-specific
* 6 SFP_SR/LR_CORE1 - 82599-specific
+ * 7 SFP_act_lmt_DA_CORE0 - 82599-specific
+ * 8 SFP_act_lmt_DA_CORE1 - 82599-specific
*/
if (hw->mac.type == ixgbe_mac_82598EB) {
if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h
index 2eb6e15..cdd1998 100644
--- a/drivers/net/ixgbe/ixgbe_type.h
+++ b/drivers/net/ixgbe/ixgbe_type.h
@@ -2609,6 +2609,7 @@
#define IXGBE_ERR_EEPROM_VERSION -24
#define IXGBE_ERR_NO_SPACE -25
#define IXGBE_ERR_OVERTEMP -26
+#define IXGBE_ERR_RAR_INDEX -27
#define IXGBE_NOT_IMPLEMENTED 0x7FFFFFFF
#endif /* _IXGBE_TYPE_H_ */
diff --git a/drivers/net/korina.c b/drivers/net/korina.c
index 26bf1b7..c7a9bef 100644
--- a/drivers/net/korina.c
+++ b/drivers/net/korina.c
@@ -135,6 +135,7 @@
struct napi_struct napi;
struct timer_list media_check_timer;
struct mii_if_info mii_if;
+ struct work_struct restart_task;
struct net_device *dev;
int phy_addr;
};
@@ -375,7 +376,7 @@
if (devcs & ETH_RX_LE)
dev->stats.rx_length_errors++;
if (devcs & ETH_RX_OVR)
- dev->stats.rx_over_errors++;
+ dev->stats.rx_fifo_errors++;
if (devcs & ETH_RX_CV)
dev->stats.rx_frame_errors++;
if (devcs & ETH_RX_CES)
@@ -764,10 +765,9 @@
/* Initialize the receive descriptors */
for (i = 0; i < KORINA_NUM_RDS; i++) {
- skb = dev_alloc_skb(KORINA_RBSIZE + 2);
+ skb = netdev_alloc_skb_ip_align(dev, KORINA_RBSIZE);
if (!skb)
return -ENOMEM;
- skb_reserve(skb, 2);
lp->rx_skb[i] = skb;
lp->rd_ring[i].control = DMA_DESC_IOD |
DMA_COUNT(KORINA_RBSIZE);
@@ -890,12 +890,12 @@
/*
* Restart the RC32434 ethernet controller.
- * FIXME: check the return status where we call it
*/
-static int korina_restart(struct net_device *dev)
+static void korina_restart_task(struct work_struct *work)
{
- struct korina_private *lp = netdev_priv(dev);
- int ret;
+ struct korina_private *lp = container_of(work,
+ struct korina_private, restart_task);
+ struct net_device *dev = lp->dev;
/*
* Disable interrupts
@@ -916,10 +916,9 @@
napi_disable(&lp->napi);
- ret = korina_init(dev);
- if (ret < 0) {
+ if (korina_init(dev) < 0) {
printk(KERN_ERR "%s: cannot restart device\n", dev->name);
- return ret;
+ return;
}
korina_multicast_list(dev);
@@ -927,8 +926,6 @@
enable_irq(lp->ovr_irq);
enable_irq(lp->tx_irq);
enable_irq(lp->rx_irq);
-
- return ret;
}
static void korina_clear_and_restart(struct net_device *dev, u32 value)
@@ -937,7 +934,7 @@
netif_stop_queue(dev);
writel(value, &lp->eth_regs->ethintfc);
- korina_restart(dev);
+ schedule_work(&lp->restart_task);
}
/* Ethernet Tx Underflow interrupt */
@@ -962,11 +959,8 @@
static void korina_tx_timeout(struct net_device *dev)
{
struct korina_private *lp = netdev_priv(dev);
- unsigned long flags;
- spin_lock_irqsave(&lp->lock, flags);
- korina_restart(dev);
- spin_unlock_irqrestore(&lp->lock, flags);
+ schedule_work(&lp->restart_task);
}
/* Ethernet Rx Overflow interrupt */
@@ -1086,6 +1080,8 @@
napi_disable(&lp->napi);
+ cancel_work_sync(&lp->restart_task);
+
free_irq(lp->rx_irq, dev);
free_irq(lp->tx_irq, dev);
free_irq(lp->ovr_irq, dev);
@@ -1198,6 +1194,8 @@
}
setup_timer(&lp->media_check_timer, korina_poll_media, (unsigned long) dev);
+ INIT_WORK(&lp->restart_task, korina_restart_task);
+
printk(KERN_INFO "%s: " DRV_NAME "-" DRV_VERSION " " DRV_RELDATE "\n",
dev->name);
out:
diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c
index ce5d6e9..c27f429 100644
--- a/drivers/net/lib82596.c
+++ b/drivers/net/lib82596.c
@@ -1343,7 +1343,7 @@
DEB(DEB_MULTI,
printk(KERN_DEBUG
"%s: set multicast list, %d entries, promisc %s, allmulti %s\n",
- dev->name, dev->mc_count,
+ dev->name, netdev_mc_count(dev),
dev->flags & IFF_PROMISC ? "ON" : "OFF",
dev->flags & IFF_ALLMULTI ? "ON" : "OFF"));
diff --git a/drivers/net/mace.c b/drivers/net/mace.c
index b6855a6..1c5221f 100644
--- a/drivers/net/mace.c
+++ b/drivers/net/mace.c
@@ -997,8 +997,11 @@
static struct macio_driver mace_driver =
{
- .name = "mace",
- .match_table = mace_match,
+ .driver = {
+ .name = "mace",
+ .owner = THIS_MODULE,
+ .of_match_table = mace_match,
+ },
.probe = mace_probe,
.remove = mace_remove,
};
diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c
index 8e9704f..869f0ea 100644
--- a/drivers/net/mipsnet.c
+++ b/drivers/net/mipsnet.c
@@ -247,7 +247,7 @@
.ndo_set_mac_address = eth_mac_addr,
};
-static int __init mipsnet_probe(struct platform_device *dev)
+static int __devinit mipsnet_probe(struct platform_device *dev)
{
struct net_device *netdev;
int err;
diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c
index f26e547..3a41b6a 100644
--- a/drivers/net/netxen/netxen_nic_ctx.c
+++ b/drivers/net/netxen/netxen_nic_ctx.c
@@ -629,7 +629,8 @@
if (addr == NULL) {
dev_err(&pdev->dev, "%s: failed to allocate tx desc ring\n",
netdev->name);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto err_out_free;
}
tx_ring->desc_head = (struct cmd_desc_type0 *)addr;
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index 5c496f8..29d7b93d0 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -1159,9 +1159,6 @@
window = CRB_HI(off);
- if (adapter->ahw.crb_win == window)
- return;
-
writel(window, addr);
if (readl(addr) != window) {
if (printk_ratelimit())
@@ -1169,7 +1166,6 @@
"failed to set CRB window to %d off 0x%lx\n",
window, off);
}
- adapter->ahw.crb_win = window;
}
static void __iomem *
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index 045a7c8..c865dda 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -218,7 +218,7 @@
if (cmd_buf_arr == NULL) {
dev_err(&pdev->dev, "%s: failed to allocate cmd buffer ring\n",
netdev->name);
- return -ENOMEM;
+ goto err_out;
}
memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring));
tx_ring->cmd_buf_arr = cmd_buf_arr;
@@ -230,7 +230,7 @@
if (rds_ring == NULL) {
dev_err(&pdev->dev, "%s: failed to allocate rds ring struct\n",
netdev->name);
- return -ENOMEM;
+ goto err_out;
}
recv_ctx->rds_rings = rds_ring;
@@ -1805,9 +1805,10 @@
netxen_ctx_msg msg = 0;
struct list_head *head;
+ spin_lock(&rds_ring->lock);
+
producer = rds_ring->producer;
- spin_lock(&rds_ring->lock);
head = &rds_ring->free_list;
while (!list_empty(head)) {
@@ -1829,7 +1830,6 @@
producer = get_next_index(producer, rds_ring->num_desc);
}
- spin_unlock(&rds_ring->lock);
if (count) {
rds_ring->producer = producer;
@@ -1853,6 +1853,8 @@
NETXEN_RCV_PRODUCER_OFFSET), msg);
}
}
+
+ spin_unlock(&rds_ring->lock);
}
static void
@@ -1864,10 +1866,11 @@
int producer, count = 0;
struct list_head *head;
- producer = rds_ring->producer;
if (!spin_trylock(&rds_ring->lock))
return;
+ producer = rds_ring->producer;
+
head = &rds_ring->free_list;
while (!list_empty(head)) {
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index 6f77a76..bfdef72 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -1727,6 +1727,7 @@
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
+ PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"),
PCMCIA_MFC_DEVICE_CIS_PROD_ID12(0, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
PCMCIA_MFC_DEVICE_CIS_PROD_ID4(0, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0175, 0x0000, "cis/DP83903.cis"),
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 7b6fe89..307cd17 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -322,6 +322,7 @@
return -ENOMEM;
smc = netdev_priv(dev);
smc->p_dev = link;
+ link->priv = dev;
spin_lock_init(&smc->lock);
link->io.NumPorts1 = 16;
@@ -1504,12 +1505,20 @@
writeb(cor & ~COR_IREQ_ENA, smc->base + MOT_LAN + CISREG_COR);
writeb(cor, smc->base + MOT_LAN + CISREG_COR);
}
-#ifdef DOES_NOT_WORK
- if (smc->base != NULL) { /* Megahertz MFC's */
- readb(smc->base+MEGAHERTZ_ISR);
- readb(smc->base+MEGAHERTZ_ISR);
+
+ if ((smc->base != NULL) && /* Megahertz MFC's */
+ (smc->manfid == MANFID_MEGAHERTZ) &&
+ (smc->cardid == PRODID_MEGAHERTZ_EM3288)) {
+
+ u_char tmp;
+ tmp = readb(smc->base+MEGAHERTZ_ISR);
+ tmp = readb(smc->base+MEGAHERTZ_ISR);
+
+ /* Retrigger interrupt if needed */
+ writeb(tmp, smc->base + MEGAHERTZ_ISR);
+ writeb(tmp, smc->base + MEGAHERTZ_ISR);
}
-#endif
+
spin_unlock(&smc->lock);
return IRQ_RETVAL(handled);
}
diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c
index 8ee929b..29c39ff 100644
--- a/drivers/net/phy/lxt.c
+++ b/drivers/net/phy/lxt.c
@@ -53,6 +53,9 @@
#define MII_LXT971_ISR 19 /* Interrupt Status Register */
+/* register definitions for the 973 */
+#define MII_LXT973_PCR 16 /* Port Configuration Register */
+#define PCR_FIBER_SELECT 1
MODULE_DESCRIPTION("Intel LXT PHY driver");
MODULE_AUTHOR("Andy Fleming");
@@ -119,6 +122,33 @@
return err;
}
+static int lxt973_probe(struct phy_device *phydev)
+{
+ int val = phy_read(phydev, MII_LXT973_PCR);
+
+ if (val & PCR_FIBER_SELECT) {
+ /*
+ * If fiber is selected, then the only correct setting
+ * is 100Mbps, full duplex, and auto negotiation off.
+ */
+ val = phy_read(phydev, MII_BMCR);
+ val |= (BMCR_SPEED100 | BMCR_FULLDPLX);
+ val &= ~BMCR_ANENABLE;
+ phy_write(phydev, MII_BMCR, val);
+ /* Remember that the port is in fiber mode. */
+ phydev->priv = lxt973_probe;
+ } else {
+ phydev->priv = NULL;
+ }
+ return 0;
+}
+
+static int lxt973_config_aneg(struct phy_device *phydev)
+{
+ /* Do nothing if port is in fiber mode. */
+ return phydev->priv ? 0 : genphy_config_aneg(phydev);
+}
+
static struct phy_driver lxt970_driver = {
.phy_id = 0x78100000,
.name = "LXT970",
@@ -146,6 +176,18 @@
.driver = { .owner = THIS_MODULE,},
};
+static struct phy_driver lxt973_driver = {
+ .phy_id = 0x00137a10,
+ .name = "LXT973",
+ .phy_id_mask = 0xfffffff0,
+ .features = PHY_BASIC_FEATURES,
+ .flags = 0,
+ .probe = lxt973_probe,
+ .config_aneg = lxt973_config_aneg,
+ .read_status = genphy_read_status,
+ .driver = { .owner = THIS_MODULE,},
+};
+
static int __init lxt_init(void)
{
int ret;
@@ -157,9 +199,15 @@
ret = phy_driver_register(&lxt971_driver);
if (ret)
goto err2;
+
+ ret = phy_driver_register(&lxt973_driver);
+ if (ret)
+ goto err3;
return 0;
- err2:
+ err3:
+ phy_driver_unregister(&lxt971_driver);
+ err2:
phy_driver_unregister(&lxt970_driver);
err1:
return ret;
@@ -169,6 +217,7 @@
{
phy_driver_unregister(&lxt970_driver);
phy_driver_unregister(&lxt971_driver);
+ phy_driver_unregister(&lxt973_driver);
}
module_init(lxt_init);
@@ -177,6 +226,7 @@
static struct mdio_device_id lxt_tbl[] = {
{ 0x78100000, 0xfffffff0 },
{ 0x001378e0, 0xfffffff0 },
+ { 0x00137a10, 0xfffffff0 },
{ }
};
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index c5f8eb1..1b2c291 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -1422,7 +1422,7 @@
flen = len;
if (nfree > 0) {
if (pch->speed == 0) {
- flen = totlen/nfree;
+ flen = len/nfree;
if (nbigger > 0) {
flen++;
nbigger--;
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 217e709..96b6cfb 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -559,6 +559,11 @@
break;
udelay(25);
}
+ /*
+ * According to hardware specs a 20us delay is required after write
+ * complete indication, but before sending next command.
+ */
+ udelay(20);
}
static int mdio_read(void __iomem *ioaddr, int reg_addr)
@@ -578,6 +583,12 @@
}
udelay(25);
}
+ /*
+ * According to hardware specs a 20us delay is required after read
+ * complete indication, but before sending next command.
+ */
+ udelay(20);
+
return value;
}
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index 2e6fd89..4762c91 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -830,7 +830,7 @@
static inline unsigned int efx_port_num(struct efx_nic *efx)
{
- return PCI_FUNC(efx->pci_dev->devfn);
+ return efx->net_dev->dev_id;
}
/**
diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c
index 727b422..f2b1e61 100644
--- a/drivers/net/sfc/siena.c
+++ b/drivers/net/sfc/siena.c
@@ -206,6 +206,7 @@
{
struct siena_nic_data *nic_data;
bool already_attached = 0;
+ efx_oword_t reg;
int rc;
/* Allocate storage for hardware specific data */
@@ -220,6 +221,9 @@
goto fail1;
}
+ efx_reado(efx, ®, FR_AZ_CS_DEBUG);
+ efx->net_dev->dev_id = EFX_OWORD_FIELD(reg, FRF_CZ_CS_PORT_NUM) - 1;
+
efx_mcdi_init(efx);
/* Recover from a failed assertion before probing */
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 2111c7b..7985165 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -717,11 +717,24 @@
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
}
+/* Enable Rx/Tx */
+static void sky2_enable_rx_tx(struct sky2_port *sky2)
+{
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ u16 reg;
+
+ reg = gma_read16(hw, port, GM_GP_CTRL);
+ reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
+ gma_write16(hw, port, GM_GP_CTRL, reg);
+}
+
/* Force a renegotiation */
static void sky2_phy_reinit(struct sky2_port *sky2)
{
spin_lock_bh(&sky2->phy_lock);
sky2_phy_init(sky2->hw, sky2->port);
+ sky2_enable_rx_tx(sky2);
spin_unlock_bh(&sky2->phy_lock);
}
@@ -2040,7 +2053,6 @@
{
struct sky2_hw *hw = sky2->hw;
unsigned port = sky2->port;
- u16 reg;
static const char *fc_name[] = {
[FC_NONE] = "none",
[FC_TX] = "tx",
@@ -2048,10 +2060,7 @@
[FC_BOTH] = "both",
};
- /* enable Rx/Tx */
- reg = gma_read16(hw, port, GM_GP_CTRL);
- reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
- gma_write16(hw, port, GM_GP_CTRL, reg);
+ sky2_enable_rx_tx(sky2);
gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c
index 20ab161..737df60 100644
--- a/drivers/net/tehuti.c
+++ b/drivers/net/tehuti.c
@@ -646,7 +646,7 @@
error = copy_from_user(data, ifr->ifr_data, sizeof(data));
if (error) {
pr_err("cant copy from user\n");
- RET(error);
+ RET(-EFAULT);
}
DBG("%d 0x%x 0x%x\n", data[0], data[1], data[2]);
}
@@ -665,7 +665,7 @@
data[2]);
error = copy_to_user(ifr->ifr_data, data, sizeof(data));
if (error)
- RET(error);
+ RET(-EFAULT);
break;
case BDX_OP_WRITE:
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index c0e7000..06b552f 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -367,8 +367,8 @@
static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, };
-#define dr32(reg) readl(de->regs + (reg))
-#define dw32(reg,val) writel((val), de->regs + (reg))
+#define dr32(reg) ioread32(de->regs + (reg))
+#define dw32(reg, val) iowrite32((val), de->regs + (reg))
static void de_rx_err_acct (struct de_private *de, unsigned rx_tail,
@@ -1706,6 +1706,7 @@
int value, boguscnt = 100000;
do {
value = dr32(ROMCmd);
+ rmb();
} while (value < 0 && --boguscnt > 0);
de->dev->dev_addr[i] = value;
udelay(1);
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 4a34833..807470e 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3215,6 +3215,8 @@
__func__, __LINE__, (u32) skb);
if (skb) {
skb->data = skb->head + NET_SKB_PAD;
+ skb->len = 0;
+ skb_reset_tail_pointer(skb);
__skb_queue_head(&ugeth->rx_recycle, skb);
}
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c
index 1f802e90..9516f38 100644
--- a/drivers/net/usb/asix.c
+++ b/drivers/net/usb/asix.c
@@ -344,7 +344,7 @@
return 2;
}
- if (size > ETH_FRAME_LEN) {
+ if (size > dev->net->mtu + ETH_HLEN) {
netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n",
size);
return 0;
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index 0a3c41f..4dd2351 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -1334,7 +1334,6 @@
/* check for port already opened, if not set the termios */
serial->open_count++;
if (serial->open_count == 1) {
- tty->low_latency = 1;
serial->rx_state = RX_IDLE;
/* Force default termio settings */
_hso_serial_set_termios(tty, NULL);
diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c
index b504bd5..d14e207 100644
--- a/drivers/net/vxge/vxge-main.c
+++ b/drivers/net/vxge/vxge-main.c
@@ -2262,7 +2262,8 @@
vxge_debug_init(VXGE_ERR,
"%s: memory allocation failed",
VXGE_DRIVER_NAME);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto alloc_entries_failed;
}
vdev->vxge_entries =
@@ -2271,8 +2272,8 @@
if (!vdev->vxge_entries) {
vxge_debug_init(VXGE_ERR, "%s: memory allocation failed",
VXGE_DRIVER_NAME);
- kfree(vdev->entries);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto alloc_vxge_entries_failed;
}
for (i = 0, j = 0; i < vdev->no_of_vpath; i++) {
@@ -2303,22 +2304,32 @@
vxge_debug_init(VXGE_ERR,
"%s: MSI-X enable failed for %d vectors, ret: %d",
VXGE_DRIVER_NAME, vdev->intr_cnt, ret);
+ if ((max_config_vpath != VXGE_USE_DEFAULT) || (ret < 3)) {
+ ret = -ENODEV;
+ goto enable_msix_failed;
+ }
+
kfree(vdev->entries);
kfree(vdev->vxge_entries);
vdev->entries = NULL;
vdev->vxge_entries = NULL;
-
- if ((max_config_vpath != VXGE_USE_DEFAULT) || (ret < 3))
- return -ENODEV;
/* Try with less no of vector by reducing no of vpaths count */
temp = (ret - 1)/2;
vxge_close_vpaths(vdev, temp);
vdev->no_of_vpath = temp;
goto start;
- } else if (ret < 0)
- return -ENODEV;
-
+ } else if (ret < 0) {
+ ret = -ENODEV;
+ goto enable_msix_failed;
+ }
return 0;
+
+enable_msix_failed:
+ kfree(vdev->vxge_entries);
+alloc_vxge_entries_failed:
+ kfree(vdev->entries);
+alloc_entries_failed:
+ return ret;
}
static int vxge_enable_msix(struct vxgedev *vdev)
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index 166e77d..e47f5a9 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -37,8 +37,6 @@
#include <net/x25device.h>
#include "x25_asy.h"
-#include <net/x25device.h>
-
static struct net_device **x25_asy_devs;
static int x25_asy_maxdev = SL_NRUNIT;
diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c
index 3f283bf..1149135 100644
--- a/drivers/net/wimax/i2400m/fw.c
+++ b/drivers/net/wimax/i2400m/fw.c
@@ -1192,7 +1192,7 @@
unsigned module_type, header_len, major_version, minor_version,
module_id, module_vendor, date, size;
- module_type = bcf_hdr->module_type;
+ module_type = le32_to_cpu(bcf_hdr->module_type);
header_len = sizeof(u32) * le32_to_cpu(bcf_hdr->header_len);
major_version = (le32_to_cpu(bcf_hdr->header_version) & 0xffff0000)
>> 16;
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c
index e0c244b..31c0080 100644
--- a/drivers/net/wireless/ath/ath5k/attach.c
+++ b/drivers/net/wireless/ath/ath5k/attach.c
@@ -126,6 +126,7 @@
ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT;
ah->ah_noise_floor = -95; /* until first NF calibration is run */
sc->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO;
+ ah->ah_current_channel = &sc->channels[0];
/*
* Find the mac version
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index cc6d41d..648972d 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -195,7 +195,7 @@
static int __devinit ath5k_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id);
static void __devexit ath5k_pci_remove(struct pci_dev *pdev);
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int ath5k_pci_suspend(struct device *dev);
static int ath5k_pci_resume(struct device *dev);
@@ -203,7 +203,7 @@
#define ATH5K_PM_OPS (&ath5k_pm_ops)
#else
#define ATH5K_PM_OPS NULL
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_SLEEP */
static struct pci_driver ath5k_pci_driver = {
.name = KBUILD_MODNAME,
@@ -222,7 +222,6 @@
static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ath5k_txq *txq);
static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan);
-static int ath5k_reset_wake(struct ath5k_softc *sc);
static int ath5k_start(struct ieee80211_hw *hw);
static void ath5k_stop(struct ieee80211_hw *hw);
static int ath5k_add_interface(struct ieee80211_hw *hw,
@@ -709,7 +708,7 @@
ieee80211_free_hw(hw);
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int ath5k_pci_suspend(struct device *dev)
{
struct ieee80211_hw *hw = pci_get_drvdata(to_pci_dev(dev));
@@ -735,7 +734,7 @@
ath5k_led_enable(sc);
return 0;
}
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_SLEEP */
/***********************\
@@ -2770,7 +2769,7 @@
{
struct ath5k_softc *sc = (void *)data;
- ath5k_reset_wake(sc);
+ ath5k_reset(sc, sc->curchan);
}
/*
@@ -2941,23 +2940,13 @@
ath5k_beacon_config(sc);
/* intrs are enabled by ath5k_beacon_config */
+ ieee80211_wake_queues(sc->hw);
+
return 0;
err:
return ret;
}
-static int
-ath5k_reset_wake(struct ath5k_softc *sc)
-{
- int ret;
-
- ret = ath5k_reset(sc, sc->curchan);
- if (!ret)
- ieee80211_wake_queues(sc->hw);
-
- return ret;
-}
-
static int ath5k_start(struct ieee80211_hw *hw)
{
return ath5k_init(hw->priv);
@@ -3151,13 +3140,15 @@
if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
if (*new_flags & FIF_PROMISC_IN_BSS) {
- rfilt |= AR5K_RX_FILTER_PROM;
__set_bit(ATH_STAT_PROMISC, sc->status);
} else {
__clear_bit(ATH_STAT_PROMISC, sc->status);
}
}
+ if (test_bit(ATH_STAT_PROMISC, sc->status))
+ rfilt |= AR5K_RX_FILTER_PROM;
+
/* Note, AR5K_RX_FILTER_MCAST is already enabled */
if (*new_flags & FIF_ALLMULTI) {
mfilt[0] = ~0;
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index 1b81c47..492cbb1 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -1814,6 +1814,13 @@
u8 def_ant, tx_ant, ee_mode;
u32 sta_id1 = 0;
+ /* if channel is not initialized yet we can't set the antennas
+ * so just store the mode. it will be set on the next reset */
+ if (channel == NULL) {
+ ah->ah_ant_mode = ant_mode;
+ return;
+ }
+
def_ant = ah->ah_def_ant;
ATH5K_TRACE(ah->ah_sc);
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index db72461..29b31a6 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -594,6 +594,7 @@
local_info_t *local;
int ret = 1;
struct hostap_cs_priv *hw_priv;
+ unsigned long flags;
PDEBUG(DEBUG_FLOW, "prism2_config()\n");
@@ -625,9 +626,15 @@
local->hw_priv = hw_priv;
hw_priv->link = link;
+ /*
+ * Make sure the IRQ handler cannot proceed until at least
+ * dev->base_addr is initialized.
+ */
+ spin_lock_irqsave(&local->irq_init_lock, flags);
+
ret = pcmcia_request_irq(link, prism2_interrupt);
if (ret)
- goto failed;
+ goto failed_unlock;
/*
* This actually configures the PCMCIA socket -- setting up
@@ -636,11 +643,13 @@
*/
ret = pcmcia_request_configuration(link, &link->conf);
if (ret)
- goto failed;
+ goto failed_unlock;
dev->irq = link->irq;
dev->base_addr = link->io.BasePort1;
+ spin_unlock_irqrestore(&local->irq_init_lock, flags);
+
/* Finally, report what we've done */
printk(KERN_INFO "%s: index 0x%02x: ",
dev_info, link->conf.ConfigIndex);
@@ -667,6 +676,8 @@
return ret;
+ failed_unlock:
+ spin_unlock_irqrestore(&local->irq_init_lock, flags);
failed:
kfree(hw_priv);
prism2_release((u_long)link);
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index d707328..2f999fc 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -2618,17 +2618,20 @@
int events = 0;
u16 ev;
+ iface = netdev_priv(dev);
+ local = iface->local;
+
/* Detect early interrupt before driver is fully configued */
+ spin_lock(&local->irq_init_lock);
if (!dev->base_addr) {
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: Interrupt, but dev not configured\n",
dev->name);
}
+ spin_unlock(&local->irq_init_lock);
return IRQ_HANDLED;
}
-
- iface = netdev_priv(dev);
- local = iface->local;
+ spin_unlock(&local->irq_init_lock);
prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 0);
@@ -3147,6 +3150,7 @@
spin_lock_init(&local->cmdlock);
spin_lock_init(&local->baplock);
spin_lock_init(&local->lock);
+ spin_lock_init(&local->irq_init_lock);
mutex_init(&local->rid_bap_mtx);
if (card_idx < 0 || card_idx >= MAX_PARM_DEVICES)
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h
index 3d23891..1ba33be 100644
--- a/drivers/net/wireless/hostap/hostap_wlan.h
+++ b/drivers/net/wireless/hostap/hostap_wlan.h
@@ -654,7 +654,7 @@
rwlock_t iface_lock; /* hostap_interfaces read lock; use write lock
* when removing entries from the list.
* TX and RX paths can use read lock. */
- spinlock_t cmdlock, baplock, lock;
+ spinlock_t cmdlock, baplock, lock, irq_init_lock;
struct mutex rid_bap_mtx;
u16 infofid; /* MAC buffer id for info frame */
/* txfid, intransmitfid, next_txtid, and next_alloc are protected by
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 068f7f8..c44a303 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -2852,6 +2852,7 @@
.isr = iwl_isr_legacy,
.config_ap = iwl3945_config_ap,
.manage_ibss_station = iwl3945_manage_ibss_station,
+ .recover_from_tx_stall = iwl_bg_monitor_recover,
.check_plcp_health = iwl3945_good_plcp_health,
.debugfs_ops = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index 1004cfc..0f292a2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -1119,10 +1119,9 @@
struct iwl_scan_channel *scan_ch)
{
const struct ieee80211_supported_band *sband;
- const struct iwl_channel_info *ch_info;
u16 passive_dwell = 0;
u16 active_dwell = 0;
- int i, added = 0;
+ int added = 0;
u16 channel = 0;
sband = iwl_get_hw_mode(priv, band);
@@ -1137,32 +1136,7 @@
if (passive_dwell <= active_dwell)
passive_dwell = active_dwell + 1;
- /* only scan single channel, good enough to reset the RF */
- /* pick the first valid not in-use channel */
- if (band == IEEE80211_BAND_5GHZ) {
- for (i = 14; i < priv->channel_count; i++) {
- if (priv->channel_info[i].channel !=
- le16_to_cpu(priv->staging_rxon.channel)) {
- channel = priv->channel_info[i].channel;
- ch_info = iwl_get_channel_info(priv,
- band, channel);
- if (is_channel_valid(ch_info))
- break;
- }
- }
- } else {
- for (i = 0; i < 14; i++) {
- if (priv->channel_info[i].channel !=
- le16_to_cpu(priv->staging_rxon.channel)) {
- channel =
- priv->channel_info[i].channel;
- ch_info = iwl_get_channel_info(priv,
- band, channel);
- if (is_channel_valid(ch_info))
- break;
- }
- }
- }
+ channel = iwl_get_single_channel_number(priv, band);
if (channel) {
scan_ch->channel = cpu_to_le16(channel);
scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index c402bfc..7d614c4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -1125,6 +1125,7 @@
struct ieee80211_sta *sta;
struct iwl_station_priv *sta_priv;
+ rcu_read_lock();
sta = ieee80211_find_sta(priv->vif, hdr->addr1);
if (sta) {
sta_priv = (void *)sta->drv_priv;
@@ -1133,6 +1134,7 @@
atomic_dec_return(&sta_priv->pending_frames) == 0)
ieee80211_sta_block_awake(priv->hw, sta, false);
}
+ rcu_read_unlock();
ieee80211_tx_status_irqsafe(priv->hw, skb);
}
@@ -1297,6 +1299,11 @@
sta_id = ba_resp->sta_id;
tid = ba_resp->tid;
agg = &priv->stations[sta_id].tid[tid].agg;
+ if (unlikely(agg->txq_id != scd_flow)) {
+ IWL_ERR(priv, "BA scd_flow %d does not match txq_id %d\n",
+ scd_flow, agg->txq_id);
+ return;
+ }
/* Find index just before block-ack window */
index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index aef4f71..24aff65 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1484,6 +1484,156 @@
}
+/*****************************************************************************
+ *
+ * sysfs attributes
+ *
+ *****************************************************************************/
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+
+/*
+ * The following adds a new attribute to the sysfs representation
+ * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/)
+ * used for controlling the debug level.
+ *
+ * See the level definitions in iwl for details.
+ *
+ * The debug_level being managed using sysfs below is a per device debug
+ * level that is used instead of the global debug level if it (the per
+ * device debug level) is set.
+ */
+static ssize_t show_debug_level(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ struct iwl_priv *priv = dev_get_drvdata(d);
+ return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv));
+}
+static ssize_t store_debug_level(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct iwl_priv *priv = dev_get_drvdata(d);
+ unsigned long val;
+ int ret;
+
+ ret = strict_strtoul(buf, 0, &val);
+ if (ret)
+ IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf);
+ else {
+ priv->debug_level = val;
+ if (iwl_alloc_traffic_mem(priv))
+ IWL_ERR(priv,
+ "Not enough memory to generate traffic log\n");
+ }
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
+ show_debug_level, store_debug_level);
+
+
+#endif /* CONFIG_IWLWIFI_DEBUG */
+
+
+static ssize_t show_temperature(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ struct iwl_priv *priv = dev_get_drvdata(d);
+
+ if (!iwl_is_alive(priv))
+ return -EAGAIN;
+
+ return sprintf(buf, "%d\n", priv->temperature);
+}
+
+static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
+
+static ssize_t show_tx_power(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ struct iwl_priv *priv = dev_get_drvdata(d);
+
+ if (!iwl_is_ready_rf(priv))
+ return sprintf(buf, "off\n");
+ else
+ return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
+}
+
+static ssize_t store_tx_power(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct iwl_priv *priv = dev_get_drvdata(d);
+ unsigned long val;
+ int ret;
+
+ ret = strict_strtoul(buf, 10, &val);
+ if (ret)
+ IWL_INFO(priv, "%s is not in decimal form.\n", buf);
+ else {
+ ret = iwl_set_tx_power(priv, val, false);
+ if (ret)
+ IWL_ERR(priv, "failed setting tx power (0x%d).\n",
+ ret);
+ else
+ ret = count;
+ }
+ return ret;
+}
+
+static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
+
+static ssize_t show_rts_ht_protection(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ struct iwl_priv *priv = dev_get_drvdata(d);
+
+ return sprintf(buf, "%s\n",
+ priv->cfg->use_rts_for_ht ? "RTS/CTS" : "CTS-to-self");
+}
+
+static ssize_t store_rts_ht_protection(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct iwl_priv *priv = dev_get_drvdata(d);
+ unsigned long val;
+ int ret;
+
+ ret = strict_strtoul(buf, 10, &val);
+ if (ret)
+ IWL_INFO(priv, "Input is not in decimal form.\n");
+ else {
+ if (!iwl_is_associated(priv))
+ priv->cfg->use_rts_for_ht = val ? true : false;
+ else
+ IWL_ERR(priv, "Sta associated with AP - "
+ "Change protection mechanism is not allowed\n");
+ ret = count;
+ }
+ return ret;
+}
+
+static DEVICE_ATTR(rts_ht_protection, S_IWUSR | S_IRUGO,
+ show_rts_ht_protection, store_rts_ht_protection);
+
+
+static struct attribute *iwl_sysfs_entries[] = {
+ &dev_attr_temperature.attr,
+ &dev_attr_tx_power.attr,
+ &dev_attr_rts_ht_protection.attr,
+#ifdef CONFIG_IWLWIFI_DEBUG
+ &dev_attr_debug_level.attr,
+#endif
+ NULL
+};
+
+static struct attribute_group iwl_attribute_group = {
+ .name = NULL, /* put in device directory */
+ .attrs = iwl_sysfs_entries,
+};
+
/******************************************************************************
*
* uCode download functions
@@ -1965,6 +2115,13 @@
if (err)
IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
+ err = sysfs_create_group(&priv->pci_dev->dev.kobj,
+ &iwl_attribute_group);
+ if (err) {
+ IWL_ERR(priv, "failed to create sysfs device attributes\n");
+ goto out_unbind;
+ }
+
/* We have our copies now, allow OS release its copies */
release_firmware(ucode_raw);
complete(&priv->_agn.firmware_loading_complete);
@@ -3234,10 +3391,12 @@
int ret;
u8 sta_id;
- sta_priv->common.sta_id = IWL_INVALID_STATION;
-
IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
sta->addr);
+ mutex_lock(&priv->mutex);
+ IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
+ sta->addr);
+ sta_priv->common.sta_id = IWL_INVALID_STATION;
atomic_set(&sta_priv->pending_frames, 0);
if (vif->type == NL80211_IFTYPE_AP)
@@ -3249,6 +3408,7 @@
IWL_ERR(priv, "Unable to add station %pM (%d)\n",
sta->addr, ret);
/* Should we return success if return code is EEXIST ? */
+ mutex_unlock(&priv->mutex);
return ret;
}
@@ -3258,147 +3418,13 @@
IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
sta->addr);
iwl_rs_rate_init(priv, sta, sta_id);
+ mutex_unlock(&priv->mutex);
return 0;
}
/*****************************************************************************
*
- * sysfs attributes
- *
- *****************************************************************************/
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-
-/*
- * The following adds a new attribute to the sysfs representation
- * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/)
- * used for controlling the debug level.
- *
- * See the level definitions in iwl for details.
- *
- * The debug_level being managed using sysfs below is a per device debug
- * level that is used instead of the global debug level if it (the per
- * device debug level) is set.
- */
-static ssize_t show_debug_level(struct device *d,
- struct device_attribute *attr, char *buf)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
- return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv));
-}
-static ssize_t store_debug_level(struct device *d,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
- unsigned long val;
- int ret;
-
- ret = strict_strtoul(buf, 0, &val);
- if (ret)
- IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf);
- else {
- priv->debug_level = val;
- if (iwl_alloc_traffic_mem(priv))
- IWL_ERR(priv,
- "Not enough memory to generate traffic log\n");
- }
- return strnlen(buf, count);
-}
-
-static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
- show_debug_level, store_debug_level);
-
-
-#endif /* CONFIG_IWLWIFI_DEBUG */
-
-
-static ssize_t show_temperature(struct device *d,
- struct device_attribute *attr, char *buf)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
-
- if (!iwl_is_alive(priv))
- return -EAGAIN;
-
- return sprintf(buf, "%d\n", priv->temperature);
-}
-
-static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
-
-static ssize_t show_tx_power(struct device *d,
- struct device_attribute *attr, char *buf)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
-
- if (!iwl_is_ready_rf(priv))
- return sprintf(buf, "off\n");
- else
- return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
-}
-
-static ssize_t store_tx_power(struct device *d,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
- unsigned long val;
- int ret;
-
- ret = strict_strtoul(buf, 10, &val);
- if (ret)
- IWL_INFO(priv, "%s is not in decimal form.\n", buf);
- else {
- ret = iwl_set_tx_power(priv, val, false);
- if (ret)
- IWL_ERR(priv, "failed setting tx power (0x%d).\n",
- ret);
- else
- ret = count;
- }
- return ret;
-}
-
-static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
-
-static ssize_t show_rts_ht_protection(struct device *d,
- struct device_attribute *attr, char *buf)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
-
- return sprintf(buf, "%s\n",
- priv->cfg->use_rts_for_ht ? "RTS/CTS" : "CTS-to-self");
-}
-
-static ssize_t store_rts_ht_protection(struct device *d,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
- unsigned long val;
- int ret;
-
- ret = strict_strtoul(buf, 10, &val);
- if (ret)
- IWL_INFO(priv, "Input is not in decimal form.\n");
- else {
- if (!iwl_is_associated(priv))
- priv->cfg->use_rts_for_ht = val ? true : false;
- else
- IWL_ERR(priv, "Sta associated with AP - "
- "Change protection mechanism is not allowed\n");
- ret = count;
- }
- return ret;
-}
-
-static DEVICE_ATTR(rts_ht_protection, S_IWUSR | S_IRUGO,
- show_rts_ht_protection, store_rts_ht_protection);
-
-
-/*****************************************************************************
- *
* driver setup and teardown
*
*****************************************************************************/
@@ -3550,21 +3576,6 @@
kfree(priv->scan_cmd);
}
-static struct attribute *iwl_sysfs_entries[] = {
- &dev_attr_temperature.attr,
- &dev_attr_tx_power.attr,
- &dev_attr_rts_ht_protection.attr,
-#ifdef CONFIG_IWLWIFI_DEBUG
- &dev_attr_debug_level.attr,
-#endif
- NULL
-};
-
-static struct attribute_group iwl_attribute_group = {
- .name = NULL, /* put in device directory */
- .attrs = iwl_sysfs_entries,
-};
-
static struct ieee80211_ops iwl_hw_ops = {
.tx = iwl_mac_tx,
.start = iwl_mac_start,
@@ -3750,11 +3761,6 @@
IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
goto out_disable_msi;
}
- err = sysfs_create_group(&pdev->dev.kobj, &iwl_attribute_group);
- if (err) {
- IWL_ERR(priv, "failed to create sysfs device attributes\n");
- goto out_free_irq;
- }
iwl_setup_deferred_work(priv);
iwl_setup_rx_handlers(priv);
@@ -3788,15 +3794,13 @@
err = iwl_request_firmware(priv, true);
if (err)
- goto out_remove_sysfs;
+ goto out_destroy_workqueue;
return 0;
- out_remove_sysfs:
+ out_destroy_workqueue:
destroy_workqueue(priv->workqueue);
priv->workqueue = NULL;
- sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
- out_free_irq:
free_irq(priv->pci_dev->irq, priv);
iwl_free_isr_ict(priv);
out_disable_msi:
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 5a7eca8..426e955 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -854,6 +854,45 @@
}
EXPORT_SYMBOL(iwl_set_rxon_chain);
+/* Return valid channel */
+u8 iwl_get_single_channel_number(struct iwl_priv *priv,
+ enum ieee80211_band band)
+{
+ const struct iwl_channel_info *ch_info;
+ int i;
+ u8 channel = 0;
+
+ /* only scan single channel, good enough to reset the RF */
+ /* pick the first valid not in-use channel */
+ if (band == IEEE80211_BAND_5GHZ) {
+ for (i = 14; i < priv->channel_count; i++) {
+ if (priv->channel_info[i].channel !=
+ le16_to_cpu(priv->staging_rxon.channel)) {
+ channel = priv->channel_info[i].channel;
+ ch_info = iwl_get_channel_info(priv,
+ band, channel);
+ if (is_channel_valid(ch_info))
+ break;
+ }
+ }
+ } else {
+ for (i = 0; i < 14; i++) {
+ if (priv->channel_info[i].channel !=
+ le16_to_cpu(priv->staging_rxon.channel)) {
+ channel =
+ priv->channel_info[i].channel;
+ ch_info = iwl_get_channel_info(priv,
+ band, channel);
+ if (is_channel_valid(ch_info))
+ break;
+ }
+ }
+ }
+
+ return channel;
+}
+EXPORT_SYMBOL(iwl_get_single_channel_number);
+
/**
* iwl_set_rxon_channel - Set the phymode and channel values in staging RXON
* @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 7e5a5ba..31775bd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -343,6 +343,8 @@
int iwl_full_rxon_required(struct iwl_priv *priv);
void iwl_set_rxon_chain(struct iwl_priv *priv);
int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch);
+u8 iwl_get_single_channel_number(struct iwl_priv *priv,
+ enum ieee80211_band band);
void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf);
u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
struct ieee80211_sta_ht_cap *sta_ht_inf);
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 5d3f51f..386c5f9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -491,6 +491,7 @@
mutex_lock(&priv->mutex);
+ cancel_delayed_work_sync(&priv->scan_check);
set_bit(STATUS_SCAN_ABORTING, &priv->status);
iwl_send_scan_abort(priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index 83a2636..c27c13f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -1373,10 +1373,14 @@
IWL_DEBUG_INFO(priv, "received request to remove station %pM\n",
sta->addr);
+ mutex_lock(&priv->mutex);
+ IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n",
+ sta->addr);
ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr);
if (ret)
IWL_ERR(priv, "Error removing station %pM\n",
sta->addr);
+ mutex_unlock(&priv->mutex);
return ret;
}
EXPORT_SYMBOL(iwl_mac_sta_remove);
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 3e5bffb..a27872d 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -1844,6 +1844,49 @@
#endif
}
+static int iwl3945_get_single_channel_for_scan(struct iwl_priv *priv,
+ struct ieee80211_vif *vif,
+ enum ieee80211_band band,
+ struct iwl3945_scan_channel *scan_ch)
+{
+ const struct ieee80211_supported_band *sband;
+ u16 passive_dwell = 0;
+ u16 active_dwell = 0;
+ int added = 0;
+ u8 channel = 0;
+
+ sband = iwl_get_hw_mode(priv, band);
+ if (!sband) {
+ IWL_ERR(priv, "invalid band\n");
+ return added;
+ }
+
+ active_dwell = iwl_get_active_dwell_time(priv, band, 0);
+ passive_dwell = iwl_get_passive_dwell_time(priv, band, vif);
+
+ if (passive_dwell <= active_dwell)
+ passive_dwell = active_dwell + 1;
+
+
+ channel = iwl_get_single_channel_number(priv, band);
+
+ if (channel) {
+ scan_ch->channel = channel;
+ scan_ch->type = 0; /* passive */
+ scan_ch->active_dwell = cpu_to_le16(active_dwell);
+ scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+ /* Set txpower levels to defaults */
+ scan_ch->tpc.dsp_atten = 110;
+ if (band == IEEE80211_BAND_5GHZ)
+ scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
+ else
+ scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
+ added++;
+ } else
+ IWL_ERR(priv, "no valid channel found\n");
+ return added;
+}
+
static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
enum ieee80211_band band,
u8 is_active, u8 n_probes,
@@ -2992,9 +3035,16 @@
/* select Rx antennas */
scan->flags |= iwl3945_get_antenna_flags(priv);
- scan->channel_count =
- iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
- (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
+ if (priv->is_internal_short_scan) {
+ scan->channel_count =
+ iwl3945_get_single_channel_for_scan(priv, vif, band,
+ (void *)&scan->data[le16_to_cpu(
+ scan->tx_cmd.len)]);
+ } else {
+ scan->channel_count =
+ iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
+ (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
+ }
if (scan->channel_count == 0) {
IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
@@ -3387,10 +3437,13 @@
bool is_ap = vif->type == NL80211_IFTYPE_STATION;
u8 sta_id;
- sta_priv->common.sta_id = IWL_INVALID_STATION;
-
IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
sta->addr);
+ mutex_lock(&priv->mutex);
+ IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
+ sta->addr);
+ sta_priv->common.sta_id = IWL_INVALID_STATION;
+
ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap,
&sta_id);
@@ -3398,6 +3451,7 @@
IWL_ERR(priv, "Unable to add station %pM (%d)\n",
sta->addr, ret);
/* Should we return success if return code is EEXIST ? */
+ mutex_unlock(&priv->mutex);
return ret;
}
@@ -3407,6 +3461,7 @@
IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
sta->addr);
iwl3945_rs_rate_init(priv, sta, sta_id);
+ mutex_unlock(&priv->mutex);
return 0;
}
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c
index 6a04c21..817fffc 100644
--- a/drivers/net/wireless/libertas_tf/main.c
+++ b/drivers/net/wireless/libertas_tf/main.c
@@ -549,7 +549,7 @@
prxpd = (struct rxpd *) skb->data;
- stats.flag = 0;
+ memset(&stats, 0, sizeof(stats));
if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK)))
stats.flag |= RX_FLAG_FAILED_FCS_CRC;
stats.freq = priv->cur_freq;
diff --git a/drivers/net/wireless/orinoco/airport.c b/drivers/net/wireless/orinoco/airport.c
index 9bcee10..4a0a0e5 100644
--- a/drivers/net/wireless/orinoco/airport.c
+++ b/drivers/net/wireless/orinoco/airport.c
@@ -239,8 +239,11 @@
MODULE_DEVICE_TABLE(of, airport_match);
static struct macio_driver airport_driver = {
- .name = DRIVER_NAME,
- .match_table = airport_match,
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = airport_match,
+ },
.probe = airport_attach,
.remove = airport_detach,
.suspend = airport_suspend,
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c
index 07c4528..a5ea89c 100644
--- a/drivers/net/wireless/p54/p54pci.c
+++ b/drivers/net/wireless/p54/p54pci.c
@@ -41,6 +41,8 @@
{ PCI_DEVICE(0x1260, 0x3877) },
/* Intersil PRISM Javelin/Xbow Wireless LAN adapter */
{ PCI_DEVICE(0x1260, 0x3886) },
+ /* Intersil PRISM Xbow Wireless LAN adapter (Symbol AP-300) */
+ { PCI_DEVICE(0x1260, 0xffff) },
{ },
};
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index d5b197b..7307325 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -80,6 +80,7 @@
{USB_DEVICE(0x1413, 0x5400)}, /* Telsey 802.11g USB2.0 Adapter */
{USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */
{USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */
+ {USB_DEVICE(0x413c, 0x5513)}, /* Dell WLA3310 USB Wireless Adapter */
{USB_DEVICE(0x413c, 0x8102)}, /* Spinnaker DUT */
{USB_DEVICE(0x413c, 0x8104)}, /* Cohiba Proto board */
{}
diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c
index d234285..c561332 100644
--- a/drivers/net/wireless/wl12xx/wl1251_sdio.c
+++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c
@@ -259,6 +259,7 @@
sdio_disable_func(func);
release:
sdio_release_host(func);
+ wl1251_free_hw(wl);
return ret;
}
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
index b3e5580..4952c3b 100644
--- a/drivers/pci/hotplug/cpqphp_core.c
+++ b/drivers/pci/hotplug/cpqphp_core.c
@@ -828,7 +828,14 @@
pci_name(pdev), err);
return err;
}
+
bus = pdev->subordinate;
+ if (!bus) {
+ dev_notice(&pdev->dev, "the device is not a bridge, "
+ "skipping\n");
+ rc = -ENODEV;
+ goto err_disable_device;
+ }
/* Need to read VID early b/c it's used to differentiate CPQ and INTC
* discovery
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 796828f..c9171be 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -340,7 +340,7 @@
int dmar_disabled = 1;
#endif /*CONFIG_DMAR_DEFAULT_ON*/
-static int __initdata dmar_map_gfx = 1;
+static int dmar_map_gfx = 1;
static int dmar_forcedac;
static int intel_iommu_strict;
@@ -1874,14 +1874,15 @@
}
}
if (found) {
+ spin_unlock_irqrestore(&device_domain_lock, flags);
free_devinfo_mem(info);
domain_exit(domain);
domain = found;
} else {
list_add(&info->link, &domain->devices);
list_add(&info->global, &device_domain_list);
+ spin_unlock_irqrestore(&device_domain_lock, flags);
}
- spin_unlock_irqrestore(&device_domain_lock, flags);
}
found_domain:
@@ -3603,7 +3604,8 @@
pte = dmar_domain->pgd;
if (dma_pte_present(pte)) {
free_pgtable_page(dmar_domain->pgd);
- dmar_domain->pgd = (struct dma_pte *)dma_pte_addr(pte);
+ dmar_domain->pgd = (struct dma_pte *)
+ phys_to_virt(dma_pte_addr(pte));
}
dmar_domain->agaw--;
}
@@ -3719,6 +3721,12 @@
*/
printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n");
rwbf_quirk = 1;
+
+ /* https://bugzilla.redhat.com/show_bug.cgi?id=538163 */
+ if (dev->revision == 0x07) {
+ printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n");
+ dmar_map_gfx = 0;
+ }
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index afd2fbf..c9957f6 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -1035,39 +1035,6 @@
return retval;
}
-static void pci_remove_slot_links(struct pci_dev *dev)
-{
- char func[10];
- struct pci_slot *slot;
-
- sysfs_remove_link(&dev->dev.kobj, "slot");
- list_for_each_entry(slot, &dev->bus->slots, list) {
- if (slot->number != PCI_SLOT(dev->devfn))
- continue;
- snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn));
- sysfs_remove_link(&slot->kobj, func);
- }
-}
-
-static int pci_create_slot_links(struct pci_dev *dev)
-{
- int result = 0;
- char func[10];
- struct pci_slot *slot;
-
- list_for_each_entry(slot, &dev->bus->slots, list) {
- if (slot->number != PCI_SLOT(dev->devfn))
- continue;
- result = sysfs_create_link(&dev->dev.kobj, &slot->kobj, "slot");
- if (result)
- goto out;
- snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn));
- result = sysfs_create_link(&slot->kobj, &dev->dev.kobj, func);
- }
-out:
- return result;
-}
-
int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
{
int retval;
@@ -1130,8 +1097,6 @@
if (retval)
goto err_vga_file;
- pci_create_slot_links(pdev);
-
return 0;
err_vga_file:
@@ -1181,8 +1146,6 @@
if (!sysfs_initialized)
return;
- pci_remove_slot_links(pdev);
-
pci_remove_capabilities_sysfs(pdev);
if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 60f30e7..740fb4e 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -2292,6 +2292,7 @@
pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
}
}
+EXPORT_SYMBOL_GPL(pci_msi_off);
#ifndef HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_SIZE
int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size)
diff --git a/drivers/pci/pcie/pme/pcie_pme.c b/drivers/pci/pcie/pme/pcie_pme.c
index aac285a..d672a0a 100644
--- a/drivers/pci/pcie/pme/pcie_pme.c
+++ b/drivers/pci/pcie/pme/pcie_pme.c
@@ -34,7 +34,7 @@
* being registered. Consequently, the interrupt-based PCIe PME signaling will
* not be used by any PCIe root ports in that case.
*/
-static bool pcie_pme_disabled;
+static bool pcie_pme_disabled = true;
/*
* The PCI Express Base Specification 2.0, Section 6.1.8, states the following:
@@ -64,12 +64,19 @@
static int __init pcie_pme_setup(char *str)
{
- if (!strcmp(str, "off"))
- pcie_pme_disabled = true;
- else if (!strcmp(str, "force"))
+ if (!strncmp(str, "auto", 4))
+ pcie_pme_disabled = false;
+ else if (!strncmp(str, "force", 5))
pcie_pme_force_enable = true;
- else if (!strcmp(str, "nomsi"))
- pcie_pme_msi_disabled = true;
+
+ str = strchr(str, ',');
+ if (str) {
+ str++;
+ str += strspn(str, " \t");
+ if (*str && !strcmp(str, "nomsi"))
+ pcie_pme_msi_disabled = true;
+ }
+
return 1;
}
__setup("pcie_pme=", pcie_pme_setup);
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index b7512cf..477345d 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1457,7 +1457,8 @@
conf5 &= ~(1 << 24); /* Clear bit 24 */
switch (pdev->device) {
- case PCI_DEVICE_ID_JMICRON_JMB360:
+ case PCI_DEVICE_ID_JMICRON_JMB360: /* SATA single port */
+ case PCI_DEVICE_ID_JMICRON_JMB362: /* SATA dual ports */
/* The controller should be in single function ahci mode */
conf1 |= 0x0002A100; /* Set 8, 13, 15, 17 */
break;
@@ -1493,12 +1494,14 @@
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB360, quirk_jmicron_ata);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, quirk_jmicron_ata);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB362, quirk_jmicron_ata);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, quirk_jmicron_ata);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, quirk_jmicron_ata);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, quirk_jmicron_ata);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, quirk_jmicron_ata);
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB360, quirk_jmicron_ata);
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, quirk_jmicron_ata);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB362, quirk_jmicron_ata);
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, quirk_jmicron_ata);
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, quirk_jmicron_ata);
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, quirk_jmicron_ata);
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 17bed18..92379e2 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -97,16 +97,16 @@
root = pci_find_parent_resource(dev, res);
if (!root) {
- dev_err(&dev->dev, "no compatible bridge window for %pR\n",
- res);
+ dev_info(&dev->dev, "no compatible bridge window for %pR\n",
+ res);
return -EINVAL;
}
conflict = request_resource_conflict(root, res);
if (conflict) {
- dev_err(&dev->dev,
- "address space collision: %pR conflicts with %s %pR\n",
- res, conflict->name, conflict);
+ dev_info(&dev->dev,
+ "address space collision: %pR conflicts with %s %pR\n",
+ res, conflict->name, conflict);
return -EBUSY;
}
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c
index e0189cf..659eaa0 100644
--- a/drivers/pci/slot.c
+++ b/drivers/pci/slot.c
@@ -97,50 +97,6 @@
return bus_speed_read(slot->bus->cur_bus_speed, buf);
}
-static void remove_sysfs_files(struct pci_slot *slot)
-{
- char func[10];
- struct list_head *tmp;
-
- list_for_each(tmp, &slot->bus->devices) {
- struct pci_dev *dev = pci_dev_b(tmp);
- if (PCI_SLOT(dev->devfn) != slot->number)
- continue;
- sysfs_remove_link(&dev->dev.kobj, "slot");
-
- snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn));
- sysfs_remove_link(&slot->kobj, func);
- }
-}
-
-static int create_sysfs_files(struct pci_slot *slot)
-{
- int result;
- char func[10];
- struct list_head *tmp;
-
- list_for_each(tmp, &slot->bus->devices) {
- struct pci_dev *dev = pci_dev_b(tmp);
- if (PCI_SLOT(dev->devfn) != slot->number)
- continue;
-
- result = sysfs_create_link(&dev->dev.kobj, &slot->kobj, "slot");
- if (result)
- goto fail;
-
- snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn));
- result = sysfs_create_link(&slot->kobj, &dev->dev.kobj, func);
- if (result)
- goto fail;
- }
-
- return 0;
-
-fail:
- remove_sysfs_files(slot);
- return result;
-}
-
static void pci_slot_release(struct kobject *kobj)
{
struct pci_dev *dev;
@@ -153,8 +109,6 @@
if (PCI_SLOT(dev->devfn) == slot->number)
dev->slot = NULL;
- remove_sysfs_files(slot);
-
list_del(&slot->list);
kfree(slot);
@@ -346,8 +300,6 @@
INIT_LIST_HEAD(&slot->list);
list_add(&slot->list, &parent->slots);
- create_sysfs_files(slot);
-
list_for_each_entry(dev, &parent->devices, bus_list)
if (PCI_SLOT(dev->devfn) == slot_nr)
dev->slot = slot;
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 7ef7ade..9fc3398 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -671,6 +671,7 @@
if (old_funcs != new_funcs) {
/* we need to re-start */
pcmcia_card_remove(s, NULL);
+ s->functions = 0;
pcmcia_card_add(s);
}
}
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index 1a648b9..25e5e30 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -1157,7 +1157,7 @@
unsigned int i, m, hwirq;
pcmconf8xx_t *pcmcia;
int status;
- struct device_node *np = ofdev->node;
+ struct device_node *np = ofdev->dev.of_node;
pcmcia_info("%s\n", version);
@@ -1301,7 +1301,7 @@
.driver = {
.name = driver_name,
.owner = THIS_MODULE,
- .match_table = m8xx_pcmcia_match,
+ .of_match_table = m8xx_pcmcia_match,
},
.probe = m8xx_probe,
.remove = m8xx_remove,
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 424e576..f1d4137 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -880,6 +880,12 @@
.restore_state = ti_restore_state,
.sock_init = ti_init,
},
+ [CARDBUS_TYPE_ENE] = {
+ .override = ene_override,
+ .save_state = ti_save_state,
+ .restore_state = ti_restore_state,
+ .sock_init = ti_init,
+ },
#endif
#ifdef CONFIG_YENTA_RICOH
[CARDBUS_TYPE_RICOH] = {
@@ -902,14 +908,6 @@
.restore_state = o2micro_restore_state,
},
#endif
-#ifdef CONFIG_YENTA_TI
- [CARDBUS_TYPE_ENE] = {
- .override = ene_override,
- .save_state = ti_save_state,
- .restore_state = ti_restore_state,
- .sock_init = ti_init,
- },
-#endif
};
@@ -975,7 +973,7 @@
/* probes the PCI interrupt, use only on override functions */
static int yenta_probe_cb_irq(struct yenta_socket *socket)
{
- u8 reg;
+ u8 reg = 0;
if (!socket->cb_irq)
return -1;
@@ -989,7 +987,8 @@
}
/* generate interrupt, wait */
- reg = exca_readb(socket, I365_CSCINT);
+ if (!socket->dev->irq)
+ reg = exca_readb(socket, I365_CSCINT);
exca_writeb(socket, I365_CSCINT, reg | I365_CSC_STSCHG);
cb_writel(socket, CB_SOCKET_EVENT, -1);
cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK);
diff --git a/drivers/power/max17040_battery.c b/drivers/power/max17040_battery.c
index f3e22c9..2f2f9a6 100644
--- a/drivers/power/max17040_battery.c
+++ b/drivers/power/max17040_battery.c
@@ -225,7 +225,6 @@
ret = power_supply_register(&client->dev, &chip->battery);
if (ret) {
dev_err(&client->dev, "failed: power supply register\n");
- i2c_set_clientdata(client, NULL);
kfree(chip);
return ret;
}
@@ -245,7 +244,6 @@
power_supply_unregister(&chip->battery);
cancel_delayed_work(&chip->work);
- i2c_set_clientdata(client, NULL);
kfree(chip);
return 0;
}
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c
index 671a7d1..8ae3732 100644
--- a/drivers/regulator/lp3971.c
+++ b/drivers/regulator/lp3971.c
@@ -519,8 +519,6 @@
struct lp3971 *lp3971 = i2c_get_clientdata(i2c);
int i;
- i2c_set_clientdata(i2c, NULL);
-
for (i = 0; i < lp3971->num_regulators; i++)
regulator_unregister(lp3971->rdev[i]);
diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c
index b3c1afc..2b54d9d 100644
--- a/drivers/regulator/max1586.c
+++ b/drivers/regulator/max1586.c
@@ -244,7 +244,6 @@
for (i = 0; i <= MAX1586_V6; i++)
if (rdev[i])
regulator_unregister(rdev[i]);
- i2c_set_clientdata(client, NULL);
kfree(rdev);
return 0;
diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c
index bfc4c5f..4520ace 100644
--- a/drivers/regulator/max8649.c
+++ b/drivers/regulator/max8649.c
@@ -357,7 +357,6 @@
dev_info(info->dev, "Max8649 regulator device is detected.\n");
return 0;
out:
- i2c_set_clientdata(client, NULL);
kfree(info);
return ret;
}
@@ -369,7 +368,6 @@
if (info) {
if (info->regulator)
regulator_unregister(info->regulator);
- i2c_set_clientdata(client, NULL);
kfree(info);
}
diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c
index 3790b21..d97220e 100644
--- a/drivers/regulator/max8660.c
+++ b/drivers/regulator/max8660.c
@@ -471,7 +471,6 @@
for (i = 0; i < MAX8660_V_END; i++)
if (rdev[i])
regulator_unregister(rdev[i]);
- i2c_set_clientdata(client, NULL);
kfree(rdev);
return 0;
diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c
index 8e2f209..f50afc9 100644
--- a/drivers/regulator/tps65023-regulator.c
+++ b/drivers/regulator/tps65023-regulator.c
@@ -538,9 +538,6 @@
struct tps_pmic *tps = i2c_get_clientdata(client);
int i;
- /* clear the client data in i2c */
- i2c_set_clientdata(client, NULL);
-
for (i = 0; i < TPS65023_NUM_REGULATOR; i++)
regulator_unregister(tps->rdev[i]);
diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c
index 92a8f6c..34647fc 100644
--- a/drivers/rtc/rtc-davinci.c
+++ b/drivers/rtc/rtc-davinci.c
@@ -29,6 +29,7 @@
#include <linux/bcd.h>
#include <linux/platform_device.h>
#include <linux/io.h>
+#include <linux/slab.h>
/*
* The DaVinci RTC is a simple RTC with the following
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index de033b7..d827ce5 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -777,7 +777,7 @@
read_rtc:
/* read RTC registers */
- tmp = ds1307->read_block_data(ds1307->client, 0, 8, buf);
+ tmp = ds1307->read_block_data(ds1307->client, ds1307->offset, 8, buf);
if (tmp != 8) {
pr_debug("read error %d\n", tmp);
err = -EIO;
@@ -862,7 +862,7 @@
if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
tmp += 12;
i2c_smbus_write_byte_data(client,
- DS1307_REG_HOUR,
+ ds1307->offset + DS1307_REG_HOUR,
bin2bcd(tmp));
}
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c
index 6194573..1f0007f 100644
--- a/drivers/rtc/rtc-ds1374.c
+++ b/drivers/rtc/rtc-ds1374.c
@@ -403,7 +403,6 @@
free_irq(client->irq, client);
out_free:
- i2c_set_clientdata(client, NULL);
kfree(ds1374);
return ret;
}
@@ -422,7 +421,6 @@
}
rtc_device_unregister(ds1374->rtc);
- i2c_set_clientdata(client, NULL);
kfree(ds1374);
return 0;
}
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c
index f0dbf9c..db5d8c4 100644
--- a/drivers/rtc/rtc-mpc5121.c
+++ b/drivers/rtc/rtc-mpc5121.c
@@ -279,7 +279,7 @@
if (!rtc)
return -ENOMEM;
- rtc->regs = of_iomap(op->node, 0);
+ rtc->regs = of_iomap(op->dev.of_node, 0);
if (!rtc->regs) {
dev_err(&op->dev, "%s: couldn't map io space\n", __func__);
err = -ENOSYS;
@@ -290,7 +290,7 @@
dev_set_drvdata(&op->dev, rtc);
- rtc->irq = irq_of_parse_and_map(op->node, 1);
+ rtc->irq = irq_of_parse_and_map(op->dev.of_node, 1);
err = request_irq(rtc->irq, mpc5121_rtc_handler, IRQF_DISABLED,
"mpc5121-rtc", &op->dev);
if (err) {
@@ -299,7 +299,7 @@
goto out_dispose;
}
- rtc->irq_periodic = irq_of_parse_and_map(op->node, 0);
+ rtc->irq_periodic = irq_of_parse_and_map(op->dev.of_node, 0);
err = request_irq(rtc->irq_periodic, mpc5121_rtc_handler_upd,
IRQF_DISABLED, "mpc5121-rtc_upd", &op->dev);
if (err) {
@@ -365,9 +365,11 @@
};
static struct of_platform_driver mpc5121_rtc_driver = {
- .owner = THIS_MODULE,
- .name = "mpc5121-rtc",
- .match_table = mpc5121_rtc_match,
+ .driver = {
+ .name = "mpc5121-rtc",
+ .owner = THIS_MODULE,
+ .of_match_table = mpc5121_rtc_match,
+ },
.probe = mpc5121_rtc_probe,
.remove = __devexit_p(mpc5121_rtc_remove),
};
diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c
index b65c82f..789f62f 100644
--- a/drivers/rtc/rtc-rx8025.c
+++ b/drivers/rtc/rtc-rx8025.c
@@ -632,7 +632,6 @@
rtc_device_unregister(rx8025->rtc);
errout_free:
- i2c_set_clientdata(client, NULL);
kfree(rx8025);
errout:
@@ -656,7 +655,6 @@
rx8025_sysfs_unregister(&client->dev);
rtc_device_unregister(rx8025->rtc);
- i2c_set_clientdata(client, NULL);
kfree(rx8025);
return 0;
}
diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c
index def4d39..f789e00 100644
--- a/drivers/rtc/rtc-s35390a.c
+++ b/drivers/rtc/rtc-s35390a.c
@@ -275,7 +275,6 @@
if (s35390a->client[i])
i2c_unregister_device(s35390a->client[i]);
kfree(s35390a);
- i2c_set_clientdata(client, NULL);
exit:
return err;
@@ -292,7 +291,6 @@
rtc_device_unregister(s35390a->rtc);
kfree(s35390a);
- i2c_set_clientdata(client, NULL);
return 0;
}
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index e5972b2..70b68d3 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -495,8 +495,6 @@
pr_debug("s3c2410_rtc: RTCCON=%02x\n",
readb(s3c_rtc_base + S3C2410_RTCCON));
- s3c_rtc_setfreq(&pdev->dev, 1);
-
device_init_wakeup(&pdev->dev, 1);
/* register RTC and exit */
@@ -510,14 +508,17 @@
goto err_nortc;
}
+ s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data;
+
if (s3c_rtc_cpu_type == TYPE_S3C64XX)
rtc->max_user_freq = 32768;
else
rtc->max_user_freq = 128;
- s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data;
-
platform_set_drvdata(pdev, rtc);
+
+ s3c_rtc_setfreq(&pdev->dev, 1);
+
return 0;
err_nortc:
diff --git a/drivers/s390/cio/itcw.c b/drivers/s390/cio/itcw.c
index 17da9ab..a0ae295 100644
--- a/drivers/s390/cio/itcw.c
+++ b/drivers/s390/cio/itcw.c
@@ -42,7 +42,7 @@
* size_t size;
*
* size = itcw_calc_size(1, 2, 0);
- * buffer = kmalloc(size, GFP_DMA);
+ * buffer = kmalloc(size, GFP_KERNEL | GFP_DMA);
* if (!buffer)
* return -ENOMEM;
* itcw = itcw_init(buffer, size, ITCW_OP_READ, 1, 2, 0);
diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c
index 18735b3..3ddb4dc 100644
--- a/drivers/scsi/mac53c94.c
+++ b/drivers/scsi/mac53c94.c
@@ -542,8 +542,11 @@
static struct macio_driver mac53c94_driver =
{
- .name = "mac53c94",
- .match_table = mac53c94_match,
+ .driver = {
+ .name = "mac53c94",
+ .owner = THIS_MODULE,
+ .of_match_table = mac53c94_match,
+ },
.probe = mac53c94_probe,
.remove = mac53c94_remove,
};
diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c
index a1c97e8..1f784fd 100644
--- a/drivers/scsi/mesh.c
+++ b/drivers/scsi/mesh.c
@@ -2036,8 +2036,11 @@
static struct macio_driver mesh_driver =
{
- .name = "mesh",
- .match_table = mesh_match,
+ .driver = {
+ .name = "mesh",
+ .owner = THIS_MODULE,
+ .of_match_table = mesh_match,
+ },
.probe = mesh_probe,
.remove = mesh_remove,
.shutdown = mesh_shutdown,
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 829cc37..8802e48 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -97,6 +97,7 @@
#endif
static int sd_revalidate_disk(struct gendisk *);
+static void sd_unlock_native_capacity(struct gendisk *disk);
static int sd_probe(struct device *);
static int sd_remove(struct device *);
static void sd_shutdown(struct device *);
@@ -1101,6 +1102,7 @@
#endif
.media_changed = sd_media_changed,
.revalidate_disk = sd_revalidate_disk,
+ .unlock_native_capacity = sd_unlock_native_capacity,
};
static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd)
@@ -2121,6 +2123,26 @@
}
/**
+ * sd_unlock_native_capacity - unlock native capacity
+ * @disk: struct gendisk to set capacity for
+ *
+ * Block layer calls this function if it detects that partitions
+ * on @disk reach beyond the end of the device. If the SCSI host
+ * implements ->unlock_native_capacity() method, it's invoked to
+ * give it a chance to adjust the device capacity.
+ *
+ * CONTEXT:
+ * Defined by block layer. Might sleep.
+ */
+static void sd_unlock_native_capacity(struct gendisk *disk)
+{
+ struct scsi_device *sdev = scsi_disk(disk)->device;
+
+ if (sdev->host->hostt->unlock_native_capacity)
+ sdev->host->hostt->unlock_native_capacity(sdev);
+}
+
+/**
* sd_format_disk_name - format disk name
* @prefix: name prefix - ie. "sd" for SCSI disks
* @index: index of the disk to format name for
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 01c012d..746a446 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -982,6 +982,18 @@
#define PCI_SUBDEVICE_ID_POCTAL422 0x0408
#define PCI_VENDOR_ID_ADVANTECH 0x13fe
#define PCI_DEVICE_ID_ADVANTECH_PCI3620 0x3620
+#define PCI_DEVICE_ID_TITAN_200I 0x8028
+#define PCI_DEVICE_ID_TITAN_400I 0x8048
+#define PCI_DEVICE_ID_TITAN_800I 0x8088
+#define PCI_DEVICE_ID_TITAN_800EH 0xA007
+#define PCI_DEVICE_ID_TITAN_800EHB 0xA008
+#define PCI_DEVICE_ID_TITAN_400EH 0xA009
+#define PCI_DEVICE_ID_TITAN_100E 0xA010
+#define PCI_DEVICE_ID_TITAN_200E 0xA012
+#define PCI_DEVICE_ID_TITAN_400E 0xA013
+#define PCI_DEVICE_ID_TITAN_800E 0xA014
+#define PCI_DEVICE_ID_TITAN_200EI 0xA016
+#define PCI_DEVICE_ID_TITAN_200EISI 0xA017
/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
@@ -1541,6 +1553,10 @@
pbn_b3_4_115200,
pbn_b3_8_115200,
+ pbn_b4_bt_2_921600,
+ pbn_b4_bt_4_921600,
+ pbn_b4_bt_8_921600,
+
/*
* Board-specific versions.
*/
@@ -1995,6 +2011,25 @@
.uart_offset = 8,
},
+ [pbn_b4_bt_2_921600] = {
+ .flags = FL_BASE4,
+ .num_ports = 2,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [pbn_b4_bt_4_921600] = {
+ .flags = FL_BASE4,
+ .num_ports = 4,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+ [pbn_b4_bt_8_921600] = {
+ .flags = FL_BASE4,
+ .num_ports = 8,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
+
/*
* Entries following this are board-specific.
*/
@@ -3043,6 +3078,42 @@
{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b0_bt_8_921600 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200I,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b4_bt_2_921600 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400I,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b4_bt_4_921600 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800I,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b4_bt_8_921600 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400EH,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_4_921600 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800EH,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_4_921600 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800EHB,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_4_921600 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100E,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_1_4000000 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200E,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_2_4000000 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400E,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_4_4000000 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800E,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_8_4000000 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EI,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_2_4000000 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EISI,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_2_4000000 },
{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
diff --git a/drivers/serial/altera_uart.c b/drivers/serial/altera_uart.c
index bcee156..0f11896 100644
--- a/drivers/serial/altera_uart.c
+++ b/drivers/serial/altera_uart.c
@@ -89,15 +89,12 @@
static unsigned int altera_uart_get_mctrl(struct uart_port *port)
{
struct altera_uart *pp = container_of(port, struct altera_uart, port);
- unsigned long flags;
unsigned int sigs;
- spin_lock_irqsave(&port->lock, flags);
sigs =
(readl(port->membase + ALTERA_UART_STATUS_REG) &
ALTERA_UART_STATUS_CTS_MSK) ? TIOCM_CTS : 0;
sigs |= (pp->sigs & TIOCM_RTS);
- spin_unlock_irqrestore(&port->lock, flags);
return sigs;
}
@@ -105,49 +102,37 @@
static void altera_uart_set_mctrl(struct uart_port *port, unsigned int sigs)
{
struct altera_uart *pp = container_of(port, struct altera_uart, port);
- unsigned long flags;
- spin_lock_irqsave(&port->lock, flags);
pp->sigs = sigs;
if (sigs & TIOCM_RTS)
pp->imr |= ALTERA_UART_CONTROL_RTS_MSK;
else
pp->imr &= ~ALTERA_UART_CONTROL_RTS_MSK;
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
- spin_unlock_irqrestore(&port->lock, flags);
}
static void altera_uart_start_tx(struct uart_port *port)
{
struct altera_uart *pp = container_of(port, struct altera_uart, port);
- unsigned long flags;
- spin_lock_irqsave(&port->lock, flags);
pp->imr |= ALTERA_UART_CONTROL_TRDY_MSK;
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
- spin_unlock_irqrestore(&port->lock, flags);
}
static void altera_uart_stop_tx(struct uart_port *port)
{
struct altera_uart *pp = container_of(port, struct altera_uart, port);
- unsigned long flags;
- spin_lock_irqsave(&port->lock, flags);
pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK;
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
- spin_unlock_irqrestore(&port->lock, flags);
}
static void altera_uart_stop_rx(struct uart_port *port)
{
struct altera_uart *pp = container_of(port, struct altera_uart, port);
- unsigned long flags;
- spin_lock_irqsave(&port->lock, flags);
pp->imr &= ~ALTERA_UART_CONTROL_RRDY_MSK;
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
- spin_unlock_irqrestore(&port->lock, flags);
}
static void altera_uart_break_ctl(struct uart_port *port, int break_state)
@@ -272,10 +257,14 @@
unsigned int isr;
isr = readl(port->membase + ALTERA_UART_STATUS_REG) & pp->imr;
+
+ spin_lock(&port->lock);
if (isr & ALTERA_UART_STATUS_RRDY_MSK)
altera_uart_rx_chars(pp);
if (isr & ALTERA_UART_STATUS_TRDY_MSK)
altera_uart_tx_chars(pp);
+ spin_unlock(&port->lock);
+
return IRQ_RETVAL(isr);
}
@@ -402,31 +391,24 @@
return 0;
}
-static void altera_uart_console_putc(struct console *co, const char c)
+static void altera_uart_console_putc(struct uart_port *port, const char c)
{
- struct uart_port *port = &(altera_uart_ports + co->index)->port;
- int i;
+ while (!(readl(port->membase + ALTERA_UART_STATUS_REG) &
+ ALTERA_UART_STATUS_TRDY_MSK))
+ cpu_relax();
- for (i = 0; i < 0x10000; i++) {
- if (readl(port->membase + ALTERA_UART_STATUS_REG) &
- ALTERA_UART_STATUS_TRDY_MSK)
- break;
- }
writel(c, port->membase + ALTERA_UART_TXDATA_REG);
- for (i = 0; i < 0x10000; i++) {
- if (readl(port->membase + ALTERA_UART_STATUS_REG) &
- ALTERA_UART_STATUS_TRDY_MSK)
- break;
- }
}
static void altera_uart_console_write(struct console *co, const char *s,
unsigned int count)
{
+ struct uart_port *port = &(altera_uart_ports + co->index)->port;
+
for (; count; count--, s++) {
- altera_uart_console_putc(co, *s);
+ altera_uart_console_putc(port, *s);
if (*s == '\n')
- altera_uart_console_putc(co, '\r');
+ altera_uart_console_putc(port, '\r');
}
}
@@ -516,7 +498,7 @@
return 0;
}
-static int altera_uart_remove(struct platform_device *pdev)
+static int __devexit altera_uart_remove(struct platform_device *pdev)
{
struct uart_port *port;
int i;
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
index 96f7e74..511cbf6 100644
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -797,7 +797,7 @@
gpio_free(uart->rts_pin);
#endif
#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
- if (UART_GET_IER(uart) && EDSSI)
+ if (UART_GET_IER(uart) & EDSSI)
free_irq(uart->status_irq, uart);
#endif
}
@@ -869,7 +869,12 @@
}
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
- quot = uart_get_divisor(port, baud) - ANOMALY_05000230;
+ quot = uart_get_divisor(port, baud);
+
+ /* If discipline is not IRDA, apply ANOMALY_05000230 */
+ if (termios->c_line != N_IRDA)
+ quot -= ANOMALY_05000230;
+
spin_lock_irqsave(&uart->port.lock, flags);
UART_SET_ANOMALY_THRESHOLD(uart, USEC_PER_SEC / baud * 15);
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index 9eb62a2..cd6cf57 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -930,6 +930,83 @@
}
}
+#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_CPM_CONSOLE)
+/*
+ * Write a string to the serial port
+ * Note that this is called with interrupts already disabled
+ */
+static void cpm_uart_early_write(struct uart_cpm_port *pinfo,
+ const char *string, u_int count)
+{
+ unsigned int i;
+ cbd_t __iomem *bdp, *bdbase;
+ unsigned char *cpm_outp_addr;
+
+ /* Get the address of the host memory buffer.
+ */
+ bdp = pinfo->tx_cur;
+ bdbase = pinfo->tx_bd_base;
+
+ /*
+ * Now, do each character. This is not as bad as it looks
+ * since this is a holding FIFO and not a transmitting FIFO.
+ * We could add the complexity of filling the entire transmit
+ * buffer, but we would just wait longer between accesses......
+ */
+ for (i = 0; i < count; i++, string++) {
+ /* Wait for transmitter fifo to empty.
+ * Ready indicates output is ready, and xmt is doing
+ * that, not that it is ready for us to send.
+ */
+ while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
+ ;
+
+ /* Send the character out.
+ * If the buffer address is in the CPM DPRAM, don't
+ * convert it.
+ */
+ cpm_outp_addr = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr),
+ pinfo);
+ *cpm_outp_addr = *string;
+
+ out_be16(&bdp->cbd_datlen, 1);
+ setbits16(&bdp->cbd_sc, BD_SC_READY);
+
+ if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
+ bdp = bdbase;
+ else
+ bdp++;
+
+ /* if a LF, also do CR... */
+ if (*string == 10) {
+ while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
+ ;
+
+ cpm_outp_addr = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr),
+ pinfo);
+ *cpm_outp_addr = 13;
+
+ out_be16(&bdp->cbd_datlen, 1);
+ setbits16(&bdp->cbd_sc, BD_SC_READY);
+
+ if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
+ bdp = bdbase;
+ else
+ bdp++;
+ }
+ }
+
+ /*
+ * Finally, Wait for transmitter & holding register to empty
+ * and restore the IER
+ */
+ while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
+ ;
+
+ pinfo->tx_cur = bdp;
+}
+#endif
+
#ifdef CONFIG_CONSOLE_POLL
/* Serial polling routines for writing and reading from the uart while
* in an interrupt or debug context.
@@ -999,7 +1076,7 @@
static char ch[2];
ch[0] = (char)c;
- cpm_uart_early_write(pinfo->port.line, ch, 1);
+ cpm_uart_early_write(pinfo, ch, 1);
}
#endif /* CONFIG_CONSOLE_POLL */
@@ -1130,9 +1207,6 @@
u_int count)
{
struct uart_cpm_port *pinfo = &cpm_uart_ports[co->index];
- unsigned int i;
- cbd_t __iomem *bdp, *bdbase;
- unsigned char *cp;
unsigned long flags;
int nolock = oops_in_progress;
@@ -1142,66 +1216,7 @@
spin_lock_irqsave(&pinfo->port.lock, flags);
}
- /* Get the address of the host memory buffer.
- */
- bdp = pinfo->tx_cur;
- bdbase = pinfo->tx_bd_base;
-
- /*
- * Now, do each character. This is not as bad as it looks
- * since this is a holding FIFO and not a transmitting FIFO.
- * We could add the complexity of filling the entire transmit
- * buffer, but we would just wait longer between accesses......
- */
- for (i = 0; i < count; i++, s++) {
- /* Wait for transmitter fifo to empty.
- * Ready indicates output is ready, and xmt is doing
- * that, not that it is ready for us to send.
- */
- while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
- ;
-
- /* Send the character out.
- * If the buffer address is in the CPM DPRAM, don't
- * convert it.
- */
- cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
- *cp = *s;
-
- out_be16(&bdp->cbd_datlen, 1);
- setbits16(&bdp->cbd_sc, BD_SC_READY);
-
- if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
- bdp = bdbase;
- else
- bdp++;
-
- /* if a LF, also do CR... */
- if (*s == 10) {
- while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
- ;
-
- cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
- *cp = 13;
-
- out_be16(&bdp->cbd_datlen, 1);
- setbits16(&bdp->cbd_sc, BD_SC_READY);
-
- if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
- bdp = bdbase;
- else
- bdp++;
- }
- }
-
- /*
- * Finally, Wait for transmitter & holding register to empty
- * and restore the IER
- */
- while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
- ;
-
- pinfo->tx_cur = bdp;
+ cpm_uart_early_write(pinfo, s, count);
if (unlikely(nolock)) {
local_irq_restore(flags);
diff --git a/drivers/serial/msm_serial.c b/drivers/serial/msm_serial.c
index ecdc0fa..f8c816e 100644
--- a/drivers/serial/msm_serial.c
+++ b/drivers/serial/msm_serial.c
@@ -41,19 +41,6 @@
unsigned int imr;
};
-#define UART_TO_MSM(uart_port) ((struct msm_port *) uart_port)
-
-static inline void msm_write(struct uart_port *port, unsigned int val,
- unsigned int off)
-{
- __raw_writel(val, port->membase + off);
-}
-
-static inline unsigned int msm_read(struct uart_port *port, unsigned int off)
-{
- return __raw_readl(port->membase + off);
-}
-
static void msm_stop_tx(struct uart_port *port)
{
struct msm_port *msm_port = UART_TO_MSM(port);
@@ -320,11 +307,7 @@
struct msm_port *msm_port = UART_TO_MSM(port);
clk_enable(msm_port->clk);
-
- msm_write(port, 0xC0, UART_MREG);
- msm_write(port, 0xB2, UART_NREG);
- msm_write(port, 0x7D, UART_DREG);
- msm_write(port, 0x1C, UART_MNDREG);
+ msm_serial_set_mnd_regs(port);
}
static int msm_startup(struct uart_port *port)
@@ -706,6 +689,8 @@
if (unlikely(IS_ERR(msm_port->clk)))
return PTR_ERR(msm_port->clk);
port->uartclk = clk_get_rate(msm_port->clk);
+ printk(KERN_INFO "uartclk = %d\n", port->uartclk);
+
resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (unlikely(!resource))
diff --git a/drivers/serial/msm_serial.h b/drivers/serial/msm_serial.h
index 689f1fa..f6ca9ca 100644
--- a/drivers/serial/msm_serial.h
+++ b/drivers/serial/msm_serial.h
@@ -114,4 +114,60 @@
#define UART_MISR 0x0010
#define UART_ISR 0x0014
+#define UART_TO_MSM(uart_port) ((struct msm_port *) uart_port)
+
+static inline
+void msm_write(struct uart_port *port, unsigned int val, unsigned int off)
+{
+ __raw_writel(val, port->membase + off);
+}
+
+static inline
+unsigned int msm_read(struct uart_port *port, unsigned int off)
+{
+ return __raw_readl(port->membase + off);
+}
+
+/*
+ * Setup the MND registers to use the TCXO clock.
+ */
+static inline void msm_serial_set_mnd_regs_tcxo(struct uart_port *port)
+{
+ msm_write(port, 0x06, UART_MREG);
+ msm_write(port, 0xF1, UART_NREG);
+ msm_write(port, 0x0F, UART_DREG);
+ msm_write(port, 0x1A, UART_MNDREG);
+}
+
+/*
+ * Setup the MND registers to use the TCXO clock divided by 4.
+ */
+static inline void msm_serial_set_mnd_regs_tcxoby4(struct uart_port *port)
+{
+ msm_write(port, 0x18, UART_MREG);
+ msm_write(port, 0xF6, UART_NREG);
+ msm_write(port, 0x0F, UART_DREG);
+ msm_write(port, 0x0A, UART_MNDREG);
+}
+
+static inline
+void msm_serial_set_mnd_regs_from_uartclk(struct uart_port *port)
+{
+ if (port->uartclk == 19200000)
+ msm_serial_set_mnd_regs_tcxo(port);
+ else
+ msm_serial_set_mnd_regs_tcxoby4(port);
+}
+
+/*
+ * TROUT has a specific defect that makes it report it's uartclk
+ * as 19.2Mhz (TCXO) when it's actually 4.8Mhz (TCXO/4). This special
+ * cases TROUT to use the right clock.
+ */
+#ifdef CONFIG_MACH_TROUT
+#define msm_serial_set_mnd_regs msm_serial_set_mnd_regs_tcxoby4
+#else
+#define msm_serial_set_mnd_regs msm_serial_set_mnd_regs_from_uartclk
+#endif
+
#endif /* __DRIVERS_SERIAL_MSM_SERIAL_H */
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c
index cabbdc7..5b9cde7 100644
--- a/drivers/serial/pmac_zilog.c
+++ b/drivers/serial/pmac_zilog.c
@@ -2005,8 +2005,11 @@
MODULE_DEVICE_TABLE (of, pmz_match);
static struct macio_driver pmz_driver = {
- .name = "pmac_zilog",
- .match_table = pmz_match,
+ .driver = {
+ .name = "pmac_zilog",
+ .owner = THIS_MODULE,
+ .of_match_table = pmz_match,
+ },
.probe = pmz_attach,
.remove = pmz_detach,
.suspend = pmz_suspend,
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index dadd686..ab17c08 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -715,6 +715,8 @@
PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0057, 0x0021),
PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0089, 0x110a),
PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0104, 0x000a),
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0d0a),
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0e0a),
PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0xea15),
PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0109, 0x0501),
PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0138, 0x110a),
@@ -724,8 +726,6 @@
PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x016c, 0x0081),
PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x021b, 0x0101),
PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x08a1, 0xc0ab),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0d0a),
- PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0e0a),
PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3288", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x04cd2988, 0x46a52d63),
PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3336", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x0143b773, 0x46a52d63),
PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "EM1144T", "PCMCIA MODEM", 0xf510db04, 0x856d66c8, 0xbd6c43ef),
@@ -768,17 +768,26 @@
PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x0276),
PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0039),
PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0006),
+ PCMCIA_DEVICE_MANF_CARD(0x0105, 0x0101), /* TDK DF2814 */
+ PCMCIA_DEVICE_MANF_CARD(0x0105, 0x100a), /* Xircom CM-56G */
+ PCMCIA_DEVICE_MANF_CARD(0x0105, 0x3e0a), /* TDK DF5660 */
PCMCIA_DEVICE_MANF_CARD(0x0105, 0x410a),
+ PCMCIA_DEVICE_MANF_CARD(0x0107, 0x0002), /* USRobotics 14,400 */
PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d50),
PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d51),
PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d52),
PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d53),
PCMCIA_DEVICE_MANF_CARD(0x010b, 0xd180),
+ PCMCIA_DEVICE_MANF_CARD(0x0115, 0x3330), /* USRobotics/SUN 14,400 */
+ PCMCIA_DEVICE_MANF_CARD(0x0124, 0x0100), /* Nokia DTP-2 ver II */
+ PCMCIA_DEVICE_MANF_CARD(0x0134, 0x5600), /* LASAT COMMUNICATIONS A/S */
PCMCIA_DEVICE_MANF_CARD(0x0137, 0x000e),
PCMCIA_DEVICE_MANF_CARD(0x0137, 0x001b),
PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0025),
PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0045),
PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0052),
+ PCMCIA_DEVICE_MANF_CARD(0x016c, 0x0006), /* Psion 56K+Fax */
+ PCMCIA_DEVICE_MANF_CARD(0x0200, 0x0001), /* MultiMobile */
PCMCIA_DEVICE_PROD_ID134("ADV", "TECH", "COMpad-32/85", 0x67459937, 0x916d02ba, 0x8fbe92ae),
PCMCIA_DEVICE_PROD_ID124("GATEWAY2000", "CC3144", "PCMCIA MODEM", 0x506bccae, 0xcb3685f1, 0xbd6c43ef),
PCMCIA_DEVICE_PROD_ID14("MEGAHERTZ", "PCMCIA MODEM", 0xf510db04, 0xbd6c43ef),
@@ -792,21 +801,27 @@
PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 33600 FAX/DATA MODEM", 0xa3a3062c, 0x5a00ce95),
PCMCIA_DEVICE_PROD_ID12("Computerboards, Inc.", "PCM-COM422", 0xd0b78f51, 0x7e2d49ed),
PCMCIA_DEVICE_PROD_ID12("Dr. Neuhaus", "FURY CARD 14K4", 0x76942813, 0x8b96ce65),
+ PCMCIA_DEVICE_PROD_ID12("IBM", "ISDN/56K/GSM", 0xb569a6e5, 0xfee5297b),
PCMCIA_DEVICE_PROD_ID12("Intelligent", "ANGIA FAX/MODEM", 0xb496e65e, 0xf31602a6),
PCMCIA_DEVICE_PROD_ID12("Intel", "MODEM 2400+", 0x816cc815, 0x412729fb),
+ PCMCIA_DEVICE_PROD_ID12("Intertex", "IX34-PCMCIA", 0xf8a097e3, 0x97880447),
PCMCIA_DEVICE_PROD_ID12("IOTech Inc ", "PCMCIA Dual RS-232 Serial Port Card", 0x3bd2d898, 0x92abc92f),
PCMCIA_DEVICE_PROD_ID12("MACRONIX", "FAX/MODEM", 0x668388b3, 0x3f9bdf2f),
PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT1432LT", 0x5f73be51, 0x0b3e2383),
PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT2834LT", 0x5f73be51, 0x4cd7c09e),
PCMCIA_DEVICE_PROD_ID12("OEM ", "C288MX ", 0xb572d360, 0xd2385b7a),
+ PCMCIA_DEVICE_PROD_ID12("Option International", "V34bis GSM/PSTN Data/Fax Modem", 0x9d7cd6f5, 0x5cb8bf41),
PCMCIA_DEVICE_PROD_ID12("PCMCIA ", "C336MX ", 0x99bcafe9, 0xaa25bcab),
PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f),
PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "Dual RS-232 Serial Port PC Card", 0xc4420b35, 0x031a380d),
+ PCMCIA_DEVICE_PROD_ID12("Telia", "SurfinBird 560P/A+", 0xe2cdd5e, 0xc9314b38),
+ PCMCIA_DEVICE_PROD_ID1("Smart Serial Port", 0x2d8ce292),
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "cis/PCMLM28.cis"),
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "cis/PCMLM28.cis"),
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
+ PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"),
PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "cis/3CCFEM556.cis"),
diff --git a/drivers/sfi/sfi_core.c b/drivers/sfi/sfi_core.c
index 0051959..ceba593 100644
--- a/drivers/sfi/sfi_core.c
+++ b/drivers/sfi/sfi_core.c
@@ -441,8 +441,10 @@
ret = sysfs_create_bin_file(tables_kobj,
&tbl_attr->attr);
- if (ret)
+ if (ret) {
kfree(tbl_attr);
+ tbl_attr = NULL;
+ }
sfi_unmap_table(th);
return tbl_attr;
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c
index c585574b..e91a23e 100644
--- a/drivers/sh/intc.c
+++ b/drivers/sh/intc.c
@@ -16,6 +16,8 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/module.h>
@@ -855,8 +857,8 @@
primary = 1;
if (!data[0] && !data[1])
- pr_warning("intc: missing unique irq mask for "
- "irq %d (vect 0x%04x)\n", irq, irq2evt(irq));
+ pr_warning("missing unique irq mask for irq %d (vect 0x%04x)\n",
+ irq, irq2evt(irq));
data[0] = data[0] ? data[0] : intc_mask_data(desc, d, enum_id, 1);
data[1] = data[1] ? data[1] : intc_prio_data(desc, d, enum_id, 1);
@@ -952,7 +954,7 @@
struct intc_desc_int *d;
struct resource *res;
- pr_info("intc: Registered controller '%s' with %u IRQs\n",
+ pr_info("Registered controller '%s' with %u IRQs\n",
desc->name, hw->nr_vectors);
d = kzalloc(sizeof(*d), GFP_NOWAIT);
@@ -1148,7 +1150,7 @@
if (unlikely(!uimask))
return -ENOMEM;
- pr_info("intc: userimask support registered for levels 0 -> %d\n",
+ pr_info("userimask support registered for levels 0 -> %d\n",
default_prio_level - 1);
return 0;
@@ -1286,7 +1288,7 @@
}
if (error)
- pr_err("intc: sysdev registration error\n");
+ pr_err("sysdev registration error\n");
return error;
}
diff --git a/drivers/spi/mpc512x_psc_spi.c b/drivers/spi/mpc512x_psc_spi.c
index 28a126d..2534b1e 100644
--- a/drivers/spi/mpc512x_psc_spi.c
+++ b/drivers/spi/mpc512x_psc_spi.c
@@ -512,29 +512,29 @@
u64 regaddr64, size64;
s16 id = -1;
- regaddr_p = of_get_address(op->node, 0, &size64, NULL);
+ regaddr_p = of_get_address(op->dev.of_node, 0, &size64, NULL);
if (!regaddr_p) {
dev_err(&op->dev, "Invalid PSC address\n");
return -EINVAL;
}
- regaddr64 = of_translate_address(op->node, regaddr_p);
+ regaddr64 = of_translate_address(op->dev.of_node, regaddr_p);
/* get PSC id (0..11, used by port_config) */
if (op->dev.platform_data == NULL) {
const u32 *psc_nump;
- psc_nump = of_get_property(op->node, "cell-index", NULL);
+ psc_nump = of_get_property(op->dev.of_node, "cell-index", NULL);
if (!psc_nump || *psc_nump > 11) {
dev_err(&op->dev, "mpc512x_psc_spi: Device node %s "
"has invalid cell-index property\n",
- op->node->full_name);
+ op->dev.of_node->full_name);
return -EINVAL;
}
id = *psc_nump;
}
return mpc512x_psc_spi_do_probe(&op->dev, (u32) regaddr64, (u32) size64,
- irq_of_parse_and_map(op->node, 0), id);
+ irq_of_parse_and_map(op->dev.of_node, 0), id);
}
static int __exit mpc512x_psc_spi_of_remove(struct of_device *op)
@@ -550,12 +550,12 @@
MODULE_DEVICE_TABLE(of, mpc512x_psc_spi_of_match);
static struct of_platform_driver mpc512x_psc_spi_of_driver = {
- .match_table = mpc512x_psc_spi_of_match,
.probe = mpc512x_psc_spi_of_probe,
.remove = __exit_p(mpc512x_psc_spi_of_remove),
.driver = {
.name = "mpc512x-psc-spi",
.owner = THIS_MODULE,
+ .of_match_table = mpc512x_psc_spi_of_match,
},
};
diff --git a/drivers/spi/spi_ppc4xx.c b/drivers/spi/spi_ppc4xx.c
index 19c0b3b..d53466a 100644
--- a/drivers/spi/spi_ppc4xx.c
+++ b/drivers/spi/spi_ppc4xx.c
@@ -397,7 +397,7 @@
struct spi_master *master;
struct spi_bitbang *bbp;
struct resource resource;
- struct device_node *np = op->node;
+ struct device_node *np = op->dev.of_node;
struct device *dev = &op->dev;
struct device_node *opbnp;
int ret;
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index b5c3b30..984a754 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -141,5 +141,11 @@
source "drivers/staging/adis16255/Kconfig"
+source "drivers/staging/xgifb/Kconfig"
+
+source "drivers/staging/mrst-touchscreen/Kconfig"
+
+source "drivers/staging/msm/Kconfig"
+
endif # !STAGING_EXCLUDE_BUILD
endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index e330dd5..9fa2513 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -51,3 +51,6 @@
obj-$(CONFIG_CXT1E1) += cxt1e1/
obj-$(CONFIG_TI_ST) += ti-st/
obj-$(CONFIG_ADIS16255) += adis16255/
+obj-$(CONFIG_FB_XGI) += xgifb/
+obj-$(CONFIG_TOUCHSCREEN_MRSTOUCH) += mrst-touchscreen/
+obj-$(CONFIG_MSM_STAGING) += msm/
diff --git a/drivers/staging/adis16255/Kconfig b/drivers/staging/adis16255/Kconfig
index a642be6..a883c1f 100644
--- a/drivers/staging/adis16255/Kconfig
+++ b/drivers/staging/adis16255/Kconfig
@@ -1,5 +1,5 @@
config ADIS16255
- tristate "Ananlog Devices ADIS16250/16255"
+ tristate "Analog Devices ADIS16250/16255"
depends on SPI && SYSFS
---help---
If you say yes here you get support for the Analog Devices
diff --git a/drivers/staging/adis16255/adis16255.c b/drivers/staging/adis16255/adis16255.c
index 1ba11f0..55d66e2 100644
--- a/drivers/staging/adis16255/adis16255.c
+++ b/drivers/staging/adis16255/adis16255.c
@@ -361,7 +361,7 @@
/*-------------------------------------------------------------------------*/
-static int spi_adis16255_probe(struct spi_device *spi)
+static int __devinit spi_adis16255_probe(struct spi_device *spi)
{
struct adis16255_init_data *init_data = spi->dev.platform_data;
@@ -421,7 +421,7 @@
return status;
}
-static int spi_adis16255_remove(struct spi_device *spi)
+static int __devexit spi_adis16255_remove(struct spi_device *spi)
{
struct spi_adis16255_data *spiadis = dev_get_drvdata(&spi->dev);
diff --git a/drivers/staging/batman-adv/bat_sysfs.c b/drivers/staging/batman-adv/bat_sysfs.c
index e2c000b..212bc21 100644
--- a/drivers/staging/batman-adv/bat_sysfs.c
+++ b/drivers/staging/batman-adv/bat_sysfs.c
@@ -225,9 +225,9 @@
NULL,
};
-static ssize_t transtable_local_read(struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buff, loff_t off, size_t count)
+static ssize_t transtable_local_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buff, loff_t off, size_t count)
{
struct device *dev = to_dev(kobj->parent);
struct net_device *net_dev = to_net_dev(dev);
@@ -235,9 +235,9 @@
return hna_local_fill_buffer_text(net_dev, buff, count, off);
}
-static ssize_t transtable_global_read(struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buff, loff_t off, size_t count)
+static ssize_t transtable_global_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buff, loff_t off, size_t count)
{
struct device *dev = to_dev(kobj->parent);
struct net_device *net_dev = to_net_dev(dev);
@@ -245,9 +245,9 @@
return hna_global_fill_buffer_text(net_dev, buff, count, off);
}
-static ssize_t originators_read(struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buff, loff_t off, size_t count)
+static ssize_t originators_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buff, loff_t off, size_t count)
{
struct device *dev = to_dev(kobj->parent);
struct net_device *net_dev = to_net_dev(dev);
@@ -255,9 +255,9 @@
return orig_fill_buffer_text(net_dev, buff, count, off);
}
-static ssize_t vis_data_read(struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buff, loff_t off, size_t count)
+static ssize_t vis_data_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buff, loff_t off, size_t count)
{
struct device *dev = to_dev(kobj->parent);
struct net_device *net_dev = to_net_dev(dev);
diff --git a/drivers/staging/batman-adv/device.c b/drivers/staging/batman-adv/device.c
index ad82ec4..32204b5 100644
--- a/drivers/staging/batman-adv/device.c
+++ b/drivers/staging/batman-adv/device.c
@@ -196,7 +196,7 @@
kfree(device_packet);
if (error)
- return error;
+ return -EFAULT;
return sizeof(struct icmp_packet);
}
@@ -309,7 +309,7 @@
struct device_packet *device_packet;
unsigned long flags;
- device_packet = kmalloc(sizeof(struct device_packet), GFP_KERNEL);
+ device_packet = kmalloc(sizeof(struct device_packet), GFP_ATOMIC);
if (!device_packet)
return;
diff --git a/drivers/staging/batman-adv/main.c b/drivers/staging/batman-adv/main.c
index 9d13979..74c70d5 100644
--- a/drivers/staging/batman-adv/main.c
+++ b/drivers/staging/batman-adv/main.c
@@ -127,7 +127,10 @@
return 0;
unreg_soft_device:
- unregister_netdevice(soft_device);
+ unregister_netdev(soft_device);
+ soft_device = NULL;
+ return -ENOMEM;
+
free_soft_device:
free_netdev(soft_device);
soft_device = NULL;
diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c
index d8536e2..ac69ed8 100644
--- a/drivers/staging/batman-adv/send.c
+++ b/drivers/staging/batman-adv/send.c
@@ -440,6 +440,9 @@
hlist_del(&forw_packet->list);
spin_unlock_irqrestore(&forw_bcast_list_lock, flags);
+ if (atomic_read(&module_state) == MODULE_DEACTIVATING)
+ goto out;
+
/* rebroadcast packet */
rcu_read_lock();
list_for_each_entry_rcu(batman_if, &if_list, list) {
@@ -453,15 +456,15 @@
forw_packet->num_packets++;
- /* if we still have some more bcasts to send and we are not shutting
- * down */
- if ((forw_packet->num_packets < 3) &&
- (atomic_read(&module_state) != MODULE_DEACTIVATING))
+ /* if we still have some more bcasts to send */
+ if (forw_packet->num_packets < 3) {
_add_bcast_packet_to_list(forw_packet, ((5 * HZ) / 1000));
- else {
- forw_packet_free(forw_packet);
- atomic_inc(&bcast_queue_left);
+ return;
}
+
+out:
+ forw_packet_free(forw_packet);
+ atomic_inc(&bcast_queue_left);
}
void send_outstanding_bat_packet(struct work_struct *work)
@@ -476,6 +479,9 @@
hlist_del(&forw_packet->list);
spin_unlock_irqrestore(&forw_bat_list_lock, flags);
+ if (atomic_read(&module_state) == MODULE_DEACTIVATING)
+ goto out;
+
send_packet(forw_packet);
/**
@@ -483,10 +489,10 @@
* to determine the queues wake up time unless we are
* shutting down
*/
- if ((forw_packet->own) &&
- (atomic_read(&module_state) != MODULE_DEACTIVATING))
+ if (forw_packet->own)
schedule_own_packet(forw_packet->if_incoming);
+out:
/* don't count own packet */
if (!forw_packet->own)
atomic_inc(&batman_queue_left);
diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
index 8ce307e..aad4732 100644
--- a/drivers/staging/comedi/Kconfig
+++ b/drivers/staging/comedi/Kconfig
@@ -100,15 +100,6 @@
if COMEDI_ISA_DRIVERS && ISA
-config COMEDI_8255
- tristate "Generic 8255 support"
- default N
- ---help---
- Enable generic 8255 support.
-
- To compile this driver as a module, choose M here: the module will be
- called 8255.
-
config COMEDI_ACL7225B
tristate "ADlink NuDAQ ACL-7225b and compatibles support"
default N
@@ -130,6 +121,7 @@
config COMEDI_PCL724
tristate "Advantech PCL-722/724/731 and ADlink ACL-7122/7124/PET-48DIO"
+ select COMEDI_8255
default N
---help---
Enable support for Advantech PCL-724, PCL-722, PCL-731 and
@@ -198,6 +190,7 @@
config COMEDI_PCM3724
tristate "Advantech PCM-3724 PC/104 card support"
+ select COMEDI_8255
default N
---help---
Enable support for Advantech PCM-3724 PC/104 cards.
@@ -232,18 +225,9 @@
To compile this driver as a module, choose M here: the module will be
called rti802.
-config COMEDI_DAS08
- tristate "DAS-08 compatible ISA, PC/104 and PCMCIA card support"
- default N
- ---help---
- Enable support for Keithley Metrabyte/ComputerBoards DAS08
- and compatible ISA and PC/104 cards
-
- To compile this driver as a module, choose M here: the module will be
- called das08.
-
config COMEDI_DAS16M1
tristate "MeasurementComputing CIO-DAS16/M1DAS-16 ISA card support"
+ select COMEDI_8255
select COMEDI_FC
default N
---help---
@@ -254,6 +238,7 @@
config COMEDI_DAS16
tristate "DAS-16 compatible ISA and PC/104 card support"
+ select COMEDI_8255
select COMEDI_FC
default N
---help---
@@ -385,6 +370,7 @@
config COMEDI_AIO_AIO12_8
tristate "I/O Products PC/104 AIO12-8 Analog I/O Board support"
+ select COMEDI_8255
default N
---help---
Enable support for I/O Products PC/104 AIO12-8 Analog I/O Board
@@ -466,6 +452,7 @@
config COMEDI_NI_ATMIO16D
tristate "NI AT-MIO16/AT-MIO16D series ISA-PNP card support"
depends on ISAPNP && COMEDI_NI_COMMON
+ select COMEDI_8255
default N
---help---
Enable support for National Instruments AT-MIO16/AT-MIO16D cards.
@@ -667,6 +654,7 @@
config COMEDI_ADL_PCI6208
tristate "ADLink PCI-6208A support"
+ select COMEDI_8255
default N
---help---
Enable support for ADLink PCI-6208A cards
@@ -751,6 +739,7 @@
config COMEDI_ADV_PCI_DIO
tristate "Advantech PCI DIO card support"
+ select COMEDI_8255
default N
---help---
Enable support for Advantech PCI DIO cards
@@ -762,6 +751,7 @@
config COMEDI_AMPLC_DIO200
tristate "Amplicon PC272E and PCI272 DIO board support"
+ select COMEDI_8255
default N
---help---
Enable support for Amplicon PC272E and PCI272 DIO boards
@@ -771,6 +761,7 @@
config COMEDI_AMPLC_PC236
tristate "Amplicon PC36AT and PCI236 DIO board support"
+ select COMEDI_8255
default N
---help---
Enable support for Amplicon PC36AT and PCI236 DIO boards
@@ -799,6 +790,7 @@
config COMEDI_AMPLC_PCI230
tristate "Amplicon PCI230 and PCI260 support"
+ select COMEDI_8255
default N
---help---
Enable support for Amplicon PCI230 and PCI260 Multifunction I/O
@@ -869,6 +861,7 @@
config COMEDI_DAQBOARD2000
tristate "IOtech DAQboard/2000 support"
+ select COMEDI_8255
default N
---help---
Enable support for the IOtech DAQboard/2000
@@ -896,6 +889,7 @@
config COMEDI_CB_PCIDAS64
tristate "MeasurementComputing PCI-DAS 64xx, 60xx, and 4020 support"
+ select COMEDI_8255
select COMEDI_FC
default N
---help---
@@ -907,6 +901,7 @@
config COMEDI_CB_PCIDAS
tristate "MeasurementComputing PCI-DAS support"
+ select COMEDI_8255
select COMEDI_FC
default N
---help---
@@ -920,6 +915,7 @@
config COMEDI_CB_PCIDDA
tristate "MeasurementComputing PCI-DDA series support"
+ select COMEDI_8255
default N
---help---
Enable support for ComputerBoards/MeasurementComputing PCI-DDA
@@ -931,6 +927,7 @@
config COMEDI_CB_PCIDIO
tristate "MeasurementComputing PCI-DIO series support"
+ select COMEDI_8255
default N
---help---
Enable support for ComputerBoards/MeasurementComputing PCI-DIO series
@@ -941,6 +938,7 @@
config COMEDI_CB_PCIMDAS
tristate "MeasurementComputing PCIM-DAS1602/16 support"
+ select COMEDI_8255
default N
---help---
Enable support for ComputerBoards/MeasurementComputing PCI Migration
@@ -951,6 +949,7 @@
config COMEDI_CB_PCIMDDA
tristate "MeasurementComputing PCIM-DDA06-16 support"
+ select COMEDI_8255
default N
---help---
Enable support for ComputerBoards/MeasurementComputing PCIM-DDA06-16
@@ -1026,6 +1025,7 @@
config COMEDI_NI_PCIDIO
tristate "NI PCI-DIO32HS, PCI-DIO96, PCI-6533, PCI-6503 support"
depends on COMEDI_MITE
+ select COMEDI_8255
default N
---help---
Enable support for National Instruments PCI-DIO-32HS, PXI-6533,
@@ -1058,6 +1058,7 @@
config COMEDI_RTD520
tristate "Real Time Devices PCI4520/DM7520 support"
+ select COMEDI_8255
default N
---help---
Enable support for Real Time Devices PCI4520/DM7520
@@ -1097,7 +1098,7 @@
menuconfig COMEDI_PCMCIA_DRIVERS
tristate "Comedi PCMCIA drivers"
- depends on COMEDI && PCMCIA && PCCARD
+ depends on COMEDI && (PCMCIA || PCCARD)
default N
---help---
Enable comedi PCMCIA and PCCARD drivers to be built
@@ -1142,6 +1143,7 @@
config COMEDI_NI_DAQ_DIO24_CS
tristate "NI DAQ-Card DIO-24 PCMCIA support"
depends on COMEDI_NI_COMMON
+ select COMEDI_8255
default N
---help---
Enable support for the National Instruments PCMCIA DAQ-Card DIO-24
@@ -1162,8 +1164,8 @@
config COMEDI_NI_MIO_CS
tristate "NI DAQCard E series PCMCIA support"
depends on COMEDI_NI_TIO && COMEDI_NI_COMMON
- default N
select COMEDI_FC
+ default N
---help---
Enable support for the National Instruments PCMCIA DAQCard E series
DAQCard-ai-16xe-50, DAQCard-ai-16e-4, DAQCard-6062E, DAQCard-6024E
@@ -1265,7 +1267,8 @@
config COMEDI_NI_TIO
tristate "NI general purpose counter support"
- select COMEDI_MITE
+ depends on COMEDI_MITE
+ select COMEDI_8255
default N
---help---
Enable support for National Instruments general purpose counters.
@@ -1278,6 +1281,8 @@
config COMEDI_NI_LABPC
tristate "NI Lab-PC and compatibles ISA and PCI support"
+ depends on COMEDI_MITE
+ select COMEDI_8255
select COMEDI_FC
default N
---help---
@@ -1291,8 +1296,40 @@
endif # COMEDI_NI_COMMON
+config COMEDI_8255
+ tristate "Generic 8255 support"
+ depends on COMEDI
+ default N
+ ---help---
+ Enable generic 8255 support.
+
+ You should enable compilation this driver if you plan to use a board
+ that has an 8255 chip. For multifunction boards, the main driver will
+ configure the 8255 subdevice automatically.
+
+ Note that most PCI 8255 boards do NOT work with this driver, and
+ need a separate driver as a wrapper.
+
+ To compile this driver as a module, choose M here: the module will be
+ called 8255.
+
+config COMEDI_DAS08
+ tristate "DAS-08 compatible support"
+ depends on COMEDI
+ select COMEDI_8255
+ default N
+ ---help---
+ Enable support for DAS08 and compatible ISA, PC/104 and PCI cards.
+
+ Note that PCMCIA DAS08 cards are not directly supported by this
+ driver, and need a separate driver as a wrapper.
+
+ To compile this driver as a module, choose M here: the module will be
+ called das08.
+
config COMEDI_FC
tristate "Comedi shared functions for low-level driver support"
+ depends on COMEDI
default N
---help---
Enable support for shared functions for low-level drivers.
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index aced00e..aeb2c00 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -83,7 +83,7 @@
static int do_chaninfo_ioctl(struct comedi_device *dev,
struct comedi_chaninfo __user *arg);
static int do_bufinfo_ioctl(struct comedi_device *dev,
- struct comedi_bufinfo __user *arg);
+ struct comedi_bufinfo __user *arg, void *file);
static int do_cmd_ioctl(struct comedi_device *dev,
struct comedi_cmd __user *arg, void *file);
static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg,
@@ -169,7 +169,8 @@
break;
case COMEDI_BUFINFO:
rc = do_bufinfo_ioctl(dev,
- (struct comedi_bufinfo __user *)arg);
+ (struct comedi_bufinfo __user *)arg,
+ file);
break;
case COMEDI_LOCK:
rc = do_lock_ioctl(dev, arg, file);
@@ -563,7 +564,7 @@
*/
static int do_bufinfo_ioctl(struct comedi_device *dev,
- struct comedi_bufinfo __user *arg)
+ struct comedi_bufinfo __user *arg, void *file)
{
struct comedi_bufinfo bi;
struct comedi_subdevice *s;
@@ -576,6 +577,10 @@
return -EINVAL;
s = dev->subdevices + bi.subdevice;
+
+ if (s->lock && s->lock != file)
+ return -EACCES;
+
async = s->async;
if (!async) {
@@ -584,8 +589,17 @@
bi.buf_read_ptr = 0;
bi.buf_write_count = 0;
bi.buf_read_count = 0;
+ bi.bytes_read = 0;
+ bi.bytes_written = 0;
goto copyback;
}
+ if (!s->busy) {
+ bi.bytes_read = 0;
+ bi.bytes_written = 0;
+ goto copyback_position;
+ }
+ if (s->busy != file)
+ return -EACCES;
if (bi.bytes_read && (s->subdev_flags & SDF_CMD_READ)) {
bi.bytes_read = comedi_buf_read_alloc(async, bi.bytes_read);
@@ -604,6 +618,7 @@
comedi_buf_write_free(async, bi.bytes_written);
}
+copyback_position:
bi.buf_write_count = async->buf_write_count;
bi.buf_write_ptr = async->buf_write_ptr;
bi.buf_read_count = async->buf_read_count;
@@ -1576,6 +1591,19 @@
while (nbytes > 0 && !retval) {
set_current_state(TASK_INTERRUPTIBLE);
+ if (!(comedi_get_subdevice_runflags(s) & SRF_RUNNING)) {
+ if (count == 0) {
+ if (comedi_get_subdevice_runflags(s) &
+ SRF_ERROR) {
+ retval = -EPIPE;
+ } else {
+ retval = 0;
+ }
+ do_become_nonbusy(dev, s);
+ }
+ break;
+ }
+
n = nbytes;
m = n;
@@ -1588,16 +1616,6 @@
n = m;
if (n == 0) {
- if (!(comedi_get_subdevice_runflags(s) & SRF_RUNNING)) {
- if (comedi_get_subdevice_runflags(s) &
- SRF_ERROR) {
- retval = -EPIPE;
- } else {
- retval = 0;
- }
- do_become_nonbusy(dev, s);
- break;
- }
if (file->f_flags & O_NONBLOCK) {
retval = -EAGAIN;
break;
diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile
index 5ccf246..354fb7d 100644
--- a/drivers/staging/comedi/drivers/Makefile
+++ b/drivers/staging/comedi/drivers/Makefile
@@ -12,7 +12,6 @@
obj-$(CONFIG_COMEDI_SKEL) += skel.o
# Comedi ISA drivers
-obj-$(CONFIG_COMEDI_8255) += 8255.o
obj-$(CONFIG_COMEDI_ACL7225B) += acl7225b.o
obj-$(CONFIG_COMEDI_PCL711) += pcl711.o
obj-$(CONFIG_COMEDI_PCL724) += pcl724.o
@@ -26,7 +25,6 @@
obj-$(CONFIG_COMEDI_PCM3730) += pcm3730.o
obj-$(CONFIG_COMEDI_RTI800) += rti800.o
obj-$(CONFIG_COMEDI_RTI802) += rti802.o
-obj-$(CONFIG_COMEDI_DAS08) += das08.o
obj-$(CONFIG_COMEDI_DAS16M1) += das16m1.o
obj-$(CONFIG_COMEDI_DAS16) += das16.o
obj-$(CONFIG_COMEDI_DAS800) += das800.o
@@ -135,4 +133,6 @@
obj-$(CONFIG_COMEDI_NI_TIO) += ni_tiocmd.o
obj-$(CONFIG_COMEDI_NI_LABPC) += ni_labpc.o
+obj-$(CONFIG_COMEDI_8255) += 8255.o
+obj-$(CONFIG_COMEDI_DAS08) += das08.o
obj-$(CONFIG_COMEDI_FC) += comedi_fc.o
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
index 2c98641..b18e81d 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
@@ -68,6 +68,10 @@
#include "addi_common.h"
#include "addi_amcc_s5933.h"
+#ifndef ADDIDATA_DRIVER_NAME
+#define ADDIDATA_DRIVER_NAME "addi_common"
+#endif
+
/* Update-0.7.57->0.7.68MODULE_AUTHOR("ADDI-DATA GmbH <info@addi-data.com>"); */
/* Update-0.7.57->0.7.68MODULE_DESCRIPTION("Comedi ADDI-DATA module"); */
/* Update-0.7.57->0.7.68MODULE_LICENSE("GPL"); */
@@ -2528,7 +2532,7 @@
#define n_boardtypes (sizeof(boardtypes)/sizeof(struct addi_board))
static struct comedi_driver driver_addi = {
- .driver_name = "addi_common",
+ .driver_name = ADDIDATA_DRIVER_NAME,
.module = THIS_MODULE,
.attach = i_ADDI_Attach,
.detach = i_ADDI_Detach,
@@ -2570,10 +2574,6 @@
struct pcilst_struct *card = NULL;
unsigned char pci_bus, pci_slot, pci_func;
int i_Dma = 0;
- static char c_Identifier[150];
-
- sprintf(c_Identifier, "Addi-Data GmbH Comedi %s",
- this_board->pc_DriverName);
ret = alloc_private(dev, sizeof(struct addi_private));
if (ret < 0)
@@ -2583,7 +2583,7 @@
v_pci_card_list_init(this_board->i_VendorId, 1); /* 1 for displaying the list.. */
pci_list_builded = 1;
}
- /* printk("comedi%d: addi_common: board=%s",dev->minor,this_board->pc_DriverName); */
+ /* printk("comedi%d: "ADDIDATA_DRIVER_NAME": board=%s",dev->minor,this_board->pc_DriverName); */
if ((this_board->i_Dma) && (it->options[2] == 0)) {
i_Dma = 1;
@@ -2648,7 +2648,7 @@
if (irq > 0) {
if (request_irq(irq, v_ADDI_Interrupt, IRQF_SHARED,
- c_Identifier, dev) < 0) {
+ this_board->pc_DriverName, dev) < 0) {
printk(", unable to allocate IRQ %u, DISABLING IT",
irq);
irq = 0; /* Can't use IRQ */
diff --git a/drivers/staging/comedi/drivers/addi_apci_035.c b/drivers/staging/comedi/drivers/addi_apci_035.c
index da454e8..6dfcbe8 100644
--- a/drivers/staging/comedi/drivers/addi_apci_035.c
+++ b/drivers/staging/comedi/drivers/addi_apci_035.c
@@ -2,4 +2,6 @@
#define ADDIDATA_WATCHDOG 2 /* Or shold it be something else */
+#define ADDIDATA_DRIVER_NAME "addi_apci_035"
+
#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c
index fa2056e..4722ec8 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1032.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1032.c
@@ -1,3 +1,5 @@
#define CONFIG_APCI_1032 1
+#define ADDIDATA_DRIVER_NAME "addi_apci_1032"
+
#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c
index 7a5cae5..db3dafd 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1500.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1500.c
@@ -1,3 +1,5 @@
#define CONFIG_APCI_1500 1
+#define ADDIDATA_DRIVER_NAME "addi_apci_1500"
+
#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c
index 8d414844..f591baf 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1516.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1516.c
@@ -1,3 +1,5 @@
#define CONFIG_APCI_1516 1
+#define ADDIDATA_DRIVER_NAME "addi_apci_1516"
+
#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c
index 0351cdd..6f5c923 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1564.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1564.c
@@ -1,3 +1,5 @@
#define CONFIG_APCI_1564 1
+#define ADDIDATA_DRIVER_NAME "addi_apci_1564"
+
#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_16xx.c b/drivers/staging/comedi/drivers/addi_apci_16xx.c
index 5067990..1d926ad 100644
--- a/drivers/staging/comedi/drivers/addi_apci_16xx.c
+++ b/drivers/staging/comedi/drivers/addi_apci_16xx.c
@@ -1,3 +1,5 @@
#define CONFIG_APCI_16XX 1
+#define ADDIDATA_DRIVER_NAME "addi_apci_16xx"
+
#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_1710.c b/drivers/staging/comedi/drivers/addi_apci_1710.c
index c433445..df6ba8c 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1710.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1710.c
@@ -1,3 +1,5 @@
#define CONFIG_APCI_1710 1
+#define ADDIDATA_DRIVER_NAME "addi_apci_1710"
+
#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_2016.c b/drivers/staging/comedi/drivers/addi_apci_2016.c
index 271c47c..7266e41 100644
--- a/drivers/staging/comedi/drivers/addi_apci_2016.c
+++ b/drivers/staging/comedi/drivers/addi_apci_2016.c
@@ -1,3 +1,5 @@
#define CONFIG_APCI_2016 1
+#define ADDIDATA_DRIVER_NAME "addi_apci_2016"
+
#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c
index 5108ea2..f67da94 100644
--- a/drivers/staging/comedi/drivers/addi_apci_2032.c
+++ b/drivers/staging/comedi/drivers/addi_apci_2032.c
@@ -1,3 +1,5 @@
#define CONFIG_APCI_2032 1
+#define ADDIDATA_DRIVER_NAME "addi_apci_2032"
+
#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_2200.c b/drivers/staging/comedi/drivers/addi_apci_2200.c
index e439f83..bc7f7d6 100644
--- a/drivers/staging/comedi/drivers/addi_apci_2200.c
+++ b/drivers/staging/comedi/drivers/addi_apci_2200.c
@@ -1,3 +1,5 @@
#define CONFIG_APCI_2200 1
+#define ADDIDATA_DRIVER_NAME "addi_apci_2200"
+
#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_3001.c b/drivers/staging/comedi/drivers/addi_apci_3001.c
index df97c30..d86c420 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3001.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3001.c
@@ -1,3 +1,5 @@
#define CONFIG_APCI_3001 1
+#define ADDIDATA_DRIVER_NAME "addi_apci_3001"
+
#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c
index 9183125..0b22cf1 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3120.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3120.c
@@ -1,3 +1,5 @@
#define CONFIG_APCI_3120 1
+#define ADDIDATA_DRIVER_NAME "addi_apci_3120"
+
#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_3200.c b/drivers/staging/comedi/drivers/addi_apci_3200.c
index f25a70b..1593139 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3200.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3200.c
@@ -1,3 +1,5 @@
#define CONFIG_APCI_3200 1
+#define ADDIDATA_DRIVER_NAME "addi_apci_3200"
+
#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_3300.c b/drivers/staging/comedi/drivers/addi_apci_3300.c
index 1ee4778..733c69a 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3300.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3300.c
@@ -1,3 +1,5 @@
#define CONFIG_APCI_3300 1
+#define ADDIDATA_DRIVER_NAME "addi_apci_3300"
+
#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c
index 1049e20..d8a01b1 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3501.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3501.c
@@ -1,3 +1,5 @@
#define CONFIG_APCI_3501 1
+#define ADDIDATA_DRIVER_NAME "addi_apci_3501"
+
#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
index fb9deb70..942bc9e 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
@@ -1,3 +1,5 @@
#define CONFIG_APCI_3XXX 1
+#define ADDIDATA_DRIVER_NAME "addi_apci_3xxx"
+
#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
index 36a254c..39d112b 100644
--- a/drivers/staging/comedi/drivers/adl_pci9111.c
+++ b/drivers/staging/comedi/drivers/adl_pci9111.c
@@ -824,9 +824,12 @@
plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
false, true, true);
- dev_private->scan_delay =
- (async_cmd->scan_begin_arg / (async_cmd->convert_arg *
- async_cmd->chanlist_len)) - 1;
+ if (async_cmd->scan_begin_src == TRIG_TIMER) {
+ dev_private->scan_delay =
+ (async_cmd->scan_begin_arg /
+ (async_cmd->convert_arg *
+ async_cmd->chanlist_len)) - 1;
+ }
break;
diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
index 40eeecf..e424a0c 100644
--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
+++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
@@ -7,17 +7,17 @@
*/
/*
Driver: adv_pci_dio
-Description: Advantech PCI-1730, PCI-1733, PCI-1734, PCI-1736UP,
- PCI-1750, PCI-1751, PCI-1752, PCI-1753/E, PCI-1754,
- PCI-1756, PCI-1762
+Description: Advantech PCI-1730, PCI-1733, PCI-1734, PCI-1735U,
+ PCI-1736UP, PCI-1750, PCI-1751, PCI-1752, PCI-1753/E,
+ PCI-1754, PCI-1756, PCI-1762
Author: Michal Dobes <dobes@tesnet.cz>
Devices: [Advantech] PCI-1730 (adv_pci_dio), PCI-1733,
- PCI-1734, PCI-1736UP, PCI-1750,
+ PCI-1734, PCI-1735U, PCI-1736UP, PCI-1750,
PCI-1751, PCI-1752, PCI-1753,
PCI-1753+PCI-1753E, PCI-1754, PCI-1756,
PCI-1760, PCI-1762
Status: untested
-Updated: Mon, 14 Apr 2008 10:43:08 +0100
+Updated: Tue, 04 May 2010 13:00:00 +0000
This driver supports now only insn interface for DI/DO/DIO.
@@ -35,6 +35,7 @@
#include "comedi_pci.h"
#include "8255.h"
+#include "8253.h"
#undef PCI_DIO_EXTDEBUG /* if defined, enable extensive debug logging */
@@ -49,7 +50,7 @@
/* hardware types of the cards */
enum hw_cards_id {
- TYPE_PCI1730, TYPE_PCI1733, TYPE_PCI1734, TYPE_PCI1736,
+ TYPE_PCI1730, TYPE_PCI1733, TYPE_PCI1734, TYPE_PCI1735, TYPE_PCI1736,
TYPE_PCI1750,
TYPE_PCI1751,
TYPE_PCI1752,
@@ -67,7 +68,10 @@
#define MAX_DI_SUBDEVS 2 /* max number of DI subdevices per card */
#define MAX_DO_SUBDEVS 2 /* max number of DO subdevices per card */
#define MAX_DIO_SUBDEVG 2 /* max number of DIO subdevices group per card */
+#define MAX_8254_SUBDEVS 1 /* max number of 8254 counter subdevs per card */
+ /* (could be more than one 8254 per subdevice) */
+#define SIZE_8254 4 /* 8254 IO space length */
#define SIZE_8255 4 /* 8255 IO space length */
#define PCIDIO_MAINREG 2 /* main I/O region for all Advantech cards? */
@@ -85,6 +89,12 @@
#define PCI1734_IDO 0 /* W: Isolated digital output 0-31 */
#define PCI173x_BOARDID 4 /* R: Board I/D switch for 1730/3/4 */
+/* Advantech PCI-1735U */
+#define PCI1735_DI 0 /* R: Digital input 0-31 */
+#define PCI1735_DO 0 /* W: Digital output 0-31 */
+#define PCI1735_C8254 4 /* R/W: 8254 counter */
+#define PCI1735_BOARDID 8 /* R: Board I/D switch for 1735U */
+
/* Advantech PCI-1736UP */
#define PCI1736_IDI 0 /* R: Isolated digital input 0-15 */
#define PCI1736_IDO 0 /* W: Isolated digital output 0-15 */
@@ -192,7 +202,8 @@
struct diosubd_data {
int chans; /* num of chans */
int addr; /* PCI address ofset */
- int regs; /* number of registers to read or 8255 subdevices */
+ int regs; /* number of registers to read or 8255
+ subdevices or 8254 chips */
unsigned int specflags; /* addon subdevice flags */
};
@@ -206,6 +217,7 @@
struct diosubd_data sdo[MAX_DO_SUBDEVS]; /* DO chans */
struct diosubd_data sdio[MAX_DIO_SUBDEVG]; /* DIO 8255 chans */
struct diosubd_data boardid; /* card supports board ID switch */
+ struct diosubd_data s8254[MAX_8254_SUBDEVS]; /* 8254 subdevices */
enum hw_io_access io_access;
};
@@ -214,6 +226,7 @@
PCI_VENDOR_ID_ADVANTECH, 0x1730, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
PCI_VENDOR_ID_ADVANTECH, 0x1733, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
PCI_VENDOR_ID_ADVANTECH, 0x1734, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
+ PCI_VENDOR_ID_ADVANTECH, 0x1735, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
PCI_VENDOR_ID_ADVANTECH, 0x1750, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
PCI_VENDOR_ID_ADVANTECH, 0x1751, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
@@ -235,14 +248,15 @@
{{16, PCI1730_DO, 2, 0}, {16, PCI1730_IDO, 2, 0}},
{{0, 0, 0, 0}, {0, 0, 0, 0}},
{4, PCI173x_BOARDID, 1, SDF_INTERNAL},
- IO_8b,
- },
+ {{0, 0, 0, 0}},
+ IO_8b},
{"pci1733", PCI_VENDOR_ID_ADVANTECH, 0x1733, PCIDIO_MAINREG,
TYPE_PCI1733,
{{0, 0, 0, 0}, {32, PCI1733_IDI, 4, 0}},
{{0, 0, 0, 0}, {0, 0, 0, 0}},
{{0, 0, 0, 0}, {0, 0, 0, 0}},
{4, PCI173x_BOARDID, 1, SDF_INTERNAL},
+ {{0, 0, 0, 0}},
IO_8b},
{"pci1734", PCI_VENDOR_ID_ADVANTECH, 0x1734, PCIDIO_MAINREG,
TYPE_PCI1734,
@@ -250,6 +264,15 @@
{{0, 0, 0, 0}, {32, PCI1734_IDO, 4, 0}},
{{0, 0, 0, 0}, {0, 0, 0, 0}},
{4, PCI173x_BOARDID, 1, SDF_INTERNAL},
+ {{0, 0, 0, 0}},
+ IO_8b},
+ {"pci1735", PCI_VENDOR_ID_ADVANTECH, 0x1735, PCIDIO_MAINREG,
+ TYPE_PCI1735,
+ {{32, PCI1735_DI, 4, 0}, {0, 0, 0, 0}},
+ {{32, PCI1735_DO, 4, 0}, {0, 0, 0, 0}},
+ {{0, 0, 0, 0}, {0, 0, 0, 0}},
+ { 4, PCI1735_BOARDID, 1, SDF_INTERNAL},
+ {{3, PCI1735_C8254, 1, 0}},
IO_8b},
{"pci1736", PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI1736_MAINREG,
TYPE_PCI1736,
@@ -257,14 +280,15 @@
{{0, 0, 0, 0}, {16, PCI1736_IDO, 2, 0}},
{{0, 0, 0, 0}, {0, 0, 0, 0}},
{4, PCI1736_BOARDID, 1, SDF_INTERNAL},
- IO_8b,
- },
+ {{0, 0, 0, 0}},
+ IO_8b},
{"pci1750", PCI_VENDOR_ID_ADVANTECH, 0x1750, PCIDIO_MAINREG,
TYPE_PCI1750,
{{0, 0, 0, 0}, {16, PCI1750_IDI, 2, 0}},
{{0, 0, 0, 0}, {16, PCI1750_IDO, 2, 0}},
{{0, 0, 0, 0}, {0, 0, 0, 0}},
{0, 0, 0, 0},
+ {{0, 0, 0, 0}},
IO_8b},
{"pci1751", PCI_VENDOR_ID_ADVANTECH, 0x1751, PCIDIO_MAINREG,
TYPE_PCI1751,
@@ -272,6 +296,7 @@
{{0, 0, 0, 0}, {0, 0, 0, 0}},
{{48, PCI1751_DIO, 2, 0}, {0, 0, 0, 0}},
{0, 0, 0, 0},
+ {{0, 0, 0, 0}},
IO_8b},
{"pci1752", PCI_VENDOR_ID_ADVANTECH, 0x1752, PCIDIO_MAINREG,
TYPE_PCI1752,
@@ -279,6 +304,7 @@
{{32, PCI1752_IDO, 2, 0}, {32, PCI1752_IDO2, 2, 0}},
{{0, 0, 0, 0}, {0, 0, 0, 0}},
{4, PCI175x_BOARDID, 1, SDF_INTERNAL},
+ {{0, 0, 0, 0}},
IO_16b},
{"pci1753", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG,
TYPE_PCI1753,
@@ -286,6 +312,7 @@
{{0, 0, 0, 0}, {0, 0, 0, 0}},
{{96, PCI1753_DIO, 4, 0}, {0, 0, 0, 0}},
{0, 0, 0, 0},
+ {{0, 0, 0, 0}},
IO_8b},
{"pci1753e", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG,
TYPE_PCI1753E,
@@ -293,6 +320,7 @@
{{0, 0, 0, 0}, {0, 0, 0, 0}},
{{96, PCI1753_DIO, 4, 0}, {96, PCI1753E_DIO, 4, 0}},
{0, 0, 0, 0},
+ {{0, 0, 0, 0}},
IO_8b},
{"pci1754", PCI_VENDOR_ID_ADVANTECH, 0x1754, PCIDIO_MAINREG,
TYPE_PCI1754,
@@ -300,6 +328,7 @@
{{0, 0, 0, 0}, {0, 0, 0, 0}},
{{0, 0, 0, 0}, {0, 0, 0, 0}},
{4, PCI175x_BOARDID, 1, SDF_INTERNAL},
+ {{0, 0, 0, 0}},
IO_16b},
{"pci1756", PCI_VENDOR_ID_ADVANTECH, 0x1756, PCIDIO_MAINREG,
TYPE_PCI1756,
@@ -307,6 +336,7 @@
{{0, 0, 0, 0}, {32, PCI1756_IDO, 2, 0}},
{{0, 0, 0, 0}, {0, 0, 0, 0}},
{4, PCI175x_BOARDID, 1, SDF_INTERNAL},
+ {{0, 0, 0, 0}},
IO_16b},
{"pci1760", PCI_VENDOR_ID_ADVANTECH, 0x1760, 0,
TYPE_PCI1760,
@@ -314,6 +344,7 @@
{{0, 0, 0, 0}, {0, 0, 0, 0}},
{{0, 0, 0, 0}, {0, 0, 0, 0}},
{0, 0, 0, 0},
+ {{0, 0, 0, 0}},
IO_8b},
{"pci1762", PCI_VENDOR_ID_ADVANTECH, 0x1762, PCIDIO_MAINREG,
TYPE_PCI1762,
@@ -321,6 +352,7 @@
{{0, 0, 0, 0}, {16, PCI1762_RO, 1, 0}},
{{0, 0, 0, 0}, {0, 0, 0, 0}},
{4, PCI1762_BOARDID, 1, SDF_INTERNAL},
+ {{0, 0, 0, 0}},
IO_16b}
};
@@ -440,6 +472,83 @@
/*
==============================================================================
*/
+static int pci_8254_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
+{
+ const struct diosubd_data *d = (const struct diosubd_data *)s->private;
+ unsigned int chan, chip, chipchan;
+ unsigned long flags;
+
+ chan = CR_CHAN(insn->chanspec); /* channel on subdevice */
+ chip = chan / 3; /* chip on subdevice */
+ chipchan = chan - (3 * chip); /* channel on chip on subdevice */
+ spin_lock_irqsave(&s->spin_lock, flags);
+ data[0] = i8254_read(dev->iobase + d->addr + (SIZE_8254 * chip),
+ 0, chipchan);
+ spin_unlock_irqrestore(&s->spin_lock, flags);
+ return 1;
+}
+
+/*
+==============================================================================
+*/
+static int pci_8254_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
+{
+ const struct diosubd_data *d = (const struct diosubd_data *)s->private;
+ unsigned int chan, chip, chipchan;
+ unsigned long flags;
+
+ chan = CR_CHAN(insn->chanspec); /* channel on subdevice */
+ chip = chan / 3; /* chip on subdevice */
+ chipchan = chan - (3 * chip); /* channel on chip on subdevice */
+ spin_lock_irqsave(&s->spin_lock, flags);
+ i8254_write(dev->iobase + d->addr + (SIZE_8254 * chip),
+ 0, chipchan, data[0]);
+ spin_unlock_irqrestore(&s->spin_lock, flags);
+ return 1;
+}
+
+/*
+==============================================================================
+*/
+static int pci_8254_insn_config(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
+{
+ const struct diosubd_data *d = (const struct diosubd_data *)s->private;
+ unsigned int chan, chip, chipchan;
+ unsigned long iobase;
+ int ret = 0;
+ unsigned long flags;
+
+ chan = CR_CHAN(insn->chanspec); /* channel on subdevice */
+ chip = chan / 3; /* chip on subdevice */
+ chipchan = chan - (3 * chip); /* channel on chip on subdevice */
+ iobase = dev->iobase + d->addr + (SIZE_8254 * chip);
+ spin_lock_irqsave(&s->spin_lock, flags);
+ switch (data[0]) {
+ case INSN_CONFIG_SET_COUNTER_MODE:
+ ret = i8254_set_mode(iobase, 0, chipchan, data[1]);
+ if (ret < 0)
+ ret = -EINVAL;
+ break;
+ case INSN_CONFIG_8254_READ_STATUS:
+ data[1] = i8254_status(iobase, 0, chipchan);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ spin_unlock_irqrestore(&s->spin_lock, flags);
+ return ret < 0 ? ret : insn->n;
+}
+
+/*
+==============================================================================
+*/
static int pci1760_unchecked_mbxrequest(struct comedi_device *dev,
unsigned char *omb, unsigned char *imb,
int repeats)
@@ -708,6 +817,15 @@
outb(0, dev->iobase + PCI1734_IDO + 2);
outb(0, dev->iobase + PCI1734_IDO + 3);
break;
+ case TYPE_PCI1735:
+ outb(0, dev->iobase + PCI1735_DO); /* clear outputs */
+ outb(0, dev->iobase + PCI1735_DO + 1);
+ outb(0, dev->iobase + PCI1735_DO + 2);
+ outb(0, dev->iobase + PCI1735_DO + 3);
+ i8254_set_mode(dev->iobase + PCI1735_C8254, 0, 0, I8254_MODE0);
+ i8254_set_mode(dev->iobase + PCI1735_C8254, 0, 1, I8254_MODE0);
+ i8254_set_mode(dev->iobase + PCI1735_C8254, 0, 2, I8254_MODE0);
+ break;
case TYPE_PCI1736:
outb(0, dev->iobase + PCI1736_IDO);
@@ -877,6 +995,26 @@
/*
==============================================================================
*/
+static int pci_dio_add_8254(struct comedi_device *dev,
+ struct comedi_subdevice * s,
+ const struct diosubd_data *d, int subdev)
+{
+ s->type = COMEDI_SUBD_COUNTER;
+ s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
+ s->n_chan = d->chans;
+ s->maxdata = 65535;
+ s->len_chanlist = d->chans;
+ s->insn_read = pci_8254_insn_read;
+ s->insn_write = pci_8254_insn_write;
+ s->insn_config = pci_8254_insn_config;
+ s->private = (void *)d;
+
+ return 0;
+}
+
+/*
+==============================================================================
+*/
static int CheckAndAllocCard(struct comedi_device *dev,
struct comedi_devconfig *it,
struct pci_dev *pcidev)
@@ -979,6 +1117,9 @@
n_subdevices += this_board->sdio[i].regs;
if (this_board->boardid.chans)
n_subdevices++;
+ for (i = 0; i < MAX_8254_SUBDEVS; i++)
+ if (this_board->s8254[i].chans)
+ n_subdevices++;
}
ret = alloc_subdevices(dev, n_subdevices);
@@ -1022,6 +1163,13 @@
subdev++;
}
+ for (i = 0; i < MAX_8254_SUBDEVS; i++)
+ if (this_board->s8254[i].chans) {
+ s = dev->subdevices + subdev;
+ pci_dio_add_8254(dev, s, &this_board->s8254[i], subdev);
+ subdev++;
+ }
+
if (this_board->cardtype == TYPE_PCI1760)
pci1760_attach(dev, it);
@@ -1067,6 +1215,16 @@
}
}
+ if (this_board->boardid.chans) {
+ subdev++;
+ }
+
+ for (i = 0; i < MAX_8254_SUBDEVS; i++) {
+ if (this_board->s8254[i].chans) {
+ subdev++;
+ }
+ }
+
for (i = 0; i < dev->n_subdevices; i++) {
s = dev->subdevices + i;
s->private = NULL;
diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
index 8eb6765..bf27617 100644
--- a/drivers/staging/comedi/drivers/amplc_dio200.c
+++ b/drivers/staging/comedi/drivers/amplc_dio200.c
@@ -460,6 +460,7 @@
int has_clk_gat_sce;
unsigned clock_src[3]; /* Current clock sources */
unsigned gate_src[3]; /* Current gate sources */
+ spinlock_t spinlock;
};
struct dio200_subdev_intr {
@@ -1042,8 +1043,11 @@
{
struct dio200_subdev_8254 *subpriv = s->private;
int chan = CR_CHAN(insn->chanspec);
+ unsigned long flags;
+ spin_lock_irqsave(&subpriv->spinlock, flags);
data[0] = i8254_read(subpriv->iobase, 0, chan);
+ spin_unlock_irqrestore(&subpriv->spinlock, flags);
return 1;
}
@@ -1057,8 +1061,11 @@
{
struct dio200_subdev_8254 *subpriv = s->private;
int chan = CR_CHAN(insn->chanspec);
+ unsigned long flags;
+ spin_lock_irqsave(&subpriv->spinlock, flags);
i8254_write(subpriv->iobase, 0, chan, data[0]);
+ spin_unlock_irqrestore(&subpriv->spinlock, flags);
return 1;
}
@@ -1151,14 +1158,16 @@
struct comedi_insn *insn, unsigned int *data)
{
struct dio200_subdev_8254 *subpriv = s->private;
- int ret;
+ int ret = 0;
int chan = CR_CHAN(insn->chanspec);
+ unsigned long flags;
+ spin_lock_irqsave(&subpriv->spinlock, flags);
switch (data[0]) {
case INSN_CONFIG_SET_COUNTER_MODE:
ret = i8254_set_mode(subpriv->iobase, 0, chan, data[1]);
if (ret < 0)
- return -EINVAL;
+ ret = -EINVAL;
break;
case INSN_CONFIG_8254_READ_STATUS:
data[1] = i8254_status(subpriv->iobase, 0, chan);
@@ -1166,30 +1175,35 @@
case INSN_CONFIG_SET_GATE_SRC:
ret = dio200_set_gate_src(subpriv, chan, data[2]);
if (ret < 0)
- return -EINVAL;
+ ret = -EINVAL;
break;
case INSN_CONFIG_GET_GATE_SRC:
ret = dio200_get_gate_src(subpriv, chan);
- if (ret < 0)
- return -EINVAL;
+ if (ret < 0) {
+ ret = -EINVAL;
+ break;
+ }
data[2] = ret;
break;
case INSN_CONFIG_SET_CLOCK_SRC:
ret = dio200_set_clock_src(subpriv, chan, data[1]);
if (ret < 0)
- return -EINVAL;
+ ret = -EINVAL;
break;
case INSN_CONFIG_GET_CLOCK_SRC:
ret = dio200_get_clock_src(subpriv, chan, &data[2]);
- if (ret < 0)
- return -EINVAL;
+ if (ret < 0) {
+ ret = -EINVAL;
+ break;
+ }
data[1] = ret;
break;
default:
- return -EINVAL;
+ ret = -EINVAL;
break;
}
- return insn->n;
+ spin_unlock_irqrestore(&subpriv->spinlock, flags);
+ return ret < 0 ? ret : insn->n;
}
/*
@@ -1222,6 +1236,7 @@
s->insn_write = dio200_subdev_8254_write;
s->insn_config = dio200_subdev_8254_config;
+ spin_lock_init(&subpriv->spinlock);
subpriv->iobase = offset + iobase;
subpriv->has_clk_gat_sce = has_clk_gat_sce;
if (has_clk_gat_sce) {
diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
index 81829d6..c374bee 100644
--- a/drivers/staging/comedi/drivers/cb_pcidda.c
+++ b/drivers/staging/comedi/drivers/cb_pcidda.c
@@ -52,7 +52,6 @@
#include "8255.h"
#define PCI_VENDOR_ID_CB 0x1307 /* PCI vendor number of ComputerBoards */
-#define N_BOARDS 10 /* Number of boards in cb_pcidda_boards */
#define EEPROM_SIZE 128 /* number of entries in eeprom */
#define MAX_AO_CHANNELS 8 /* maximum number of ao channels for supported boards */
@@ -307,7 +306,7 @@
continue;
}
}
- for (index = 0; index < N_BOARDS; index++) {
+ for (index = 0; index < ARRAY_SIZE(cb_pcidda_boards); index++) {
if (cb_pcidda_boards[index].device_id ==
pcidev->device) {
goto found;
diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
index cedb02d..3a46f0c 100644
--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
+++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
@@ -123,7 +123,7 @@
.adbits = 12,
.ai_fifo_depth = 1024,
.alwaysdither = 0,
- .gainlkup = ai_gain_16,
+ .gainlkup = ai_gain_4,
.ai_speed = 5000,
.n_aochan = 2,
.aobits = 12,
diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
index 86f035d..27b4cb2 100644
--- a/drivers/staging/comedi/drivers/usbdux.c
+++ b/drivers/staging/comedi/drivers/usbdux.c
@@ -351,8 +351,7 @@
int ret = 0;
if (!this_usbduxsub) {
- dev_err(&this_usbduxsub->interface->dev,
- "comedi?: usbdux_ai_stop: this_usbduxsub=NULL!\n");
+ pr_err("comedi?: usbdux_ai_stop: this_usbduxsub=NULL!\n");
return -EFAULT;
}
dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_stop\n");
diff --git a/drivers/staging/dream/synaptics_i2c_rmi.c b/drivers/staging/dream/synaptics_i2c_rmi.c
index 1f020da..3320359 100644
--- a/drivers/staging/dream/synaptics_i2c_rmi.c
+++ b/drivers/staging/dream/synaptics_i2c_rmi.c
@@ -519,7 +519,6 @@
err_input_dev_alloc_failed:
err_detect_failed:
err_power_failed:
- i2c_set_clientdata(client, NULL);
kfree(ts);
err_alloc_data_failed:
err_check_functionality_failed:
@@ -537,7 +536,6 @@
else
hrtimer_cancel(&ts->timer);
input_unregister_device(ts->input_dev);
- i2c_set_clientdata(client, NULL);
kfree(ts);
return 0;
}
diff --git a/drivers/staging/dt3155/allocator.c b/drivers/staging/dt3155/allocator.c
index bd5adbc..d33947b 100644
--- a/drivers/staging/dt3155/allocator.c
+++ b/drivers/staging/dt3155/allocator.c
@@ -176,9 +176,7 @@
prev = ptr; ptr = ptr->next;
if (!ptr) {
- printk(KERN_ERR ALL_MSG
- "free_dma(0x%08lx) but add. not allocated\n",
- ptr->address);
+ pr_err(ALL_MSG "free_dma but add. not allocated\n");
return -EINVAL;
}
PDEBUGG("freeing: %08lx (%li) next %08lx\n", ptr->address, ptr->size,
diff --git a/drivers/staging/go7007/wis-saa7113.c b/drivers/staging/go7007/wis-saa7113.c
index bd92545..72f5c1f 100644
--- a/drivers/staging/go7007/wis-saa7113.c
+++ b/drivers/staging/go7007/wis-saa7113.c
@@ -289,7 +289,6 @@
if (write_regs(client, initial_registers) < 0) {
printk(KERN_ERR
"wis-saa7113: error initializing SAA7113\n");
- i2c_set_clientdata(client, NULL);
kfree(dec);
return -ENODEV;
}
@@ -301,7 +300,6 @@
{
struct wis_saa7113 *dec = i2c_get_clientdata(client);
- i2c_set_clientdata(client, NULL);
kfree(dec);
return 0;
}
diff --git a/drivers/staging/go7007/wis-saa7115.c b/drivers/staging/go7007/wis-saa7115.c
index b2eb804..cd950b6 100644
--- a/drivers/staging/go7007/wis-saa7115.c
+++ b/drivers/staging/go7007/wis-saa7115.c
@@ -422,7 +422,6 @@
if (write_regs(client, initial_registers) < 0) {
printk(KERN_ERR
"wis-saa7115: error initializing SAA7115\n");
- i2c_set_clientdata(client, NULL);
kfree(dec);
return -ENODEV;
}
@@ -434,7 +433,6 @@
{
struct wis_saa7115 *dec = i2c_get_clientdata(client);
- i2c_set_clientdata(client, NULL);
kfree(dec);
return 0;
}
diff --git a/drivers/staging/go7007/wis-sony-tuner.c b/drivers/staging/go7007/wis-sony-tuner.c
index b101329..981c9b3 100644
--- a/drivers/staging/go7007/wis-sony-tuner.c
+++ b/drivers/staging/go7007/wis-sony-tuner.c
@@ -684,7 +684,6 @@
{
struct wis_sony_tuner *t = i2c_get_clientdata(client);
- i2c_set_clientdata(client, NULL);
kfree(t);
return 0;
}
diff --git a/drivers/staging/go7007/wis-tw2804.c b/drivers/staging/go7007/wis-tw2804.c
index 315268d..ee28a99 100644
--- a/drivers/staging/go7007/wis-tw2804.c
+++ b/drivers/staging/go7007/wis-tw2804.c
@@ -323,7 +323,6 @@
{
struct wis_tw2804 *dec = i2c_get_clientdata(client);
- i2c_set_clientdata(client, NULL);
kfree(dec);
return 0;
}
diff --git a/drivers/staging/go7007/wis-tw9903.c b/drivers/staging/go7007/wis-tw9903.c
index 2afea09..80d4726 100644
--- a/drivers/staging/go7007/wis-tw9903.c
+++ b/drivers/staging/go7007/wis-tw9903.c
@@ -294,7 +294,6 @@
if (write_regs(client, initial_registers) < 0) {
printk(KERN_ERR "wis-tw9903: error initializing TW9903\n");
- i2c_set_clientdata(client, NULL);
kfree(dec);
return -ENODEV;
}
@@ -306,7 +305,6 @@
{
struct wis_tw9903 *dec = i2c_get_clientdata(client);
- i2c_set_clientdata(client, NULL);
kfree(dec);
return 0;
}
diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/staging/hv/channel_mgmt.c
index 3f53b4d..12db555 100644
--- a/drivers/staging/hv/channel_mgmt.c
+++ b/drivers/staging/hv/channel_mgmt.c
@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/completion.h>
#include "osd.h"
#include "logging.h"
#include "vmbus_private.h"
@@ -293,6 +294,25 @@
Channel);
}
+
+DECLARE_COMPLETION(hv_channel_ready);
+
+/*
+ * Count initialized channels, and ensure all channels are ready when hv_vmbus
+ * module loading completes.
+ */
+static void count_hv_channel(void)
+{
+ static int counter;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
+ if (++counter == MAX_MSG_TYPES)
+ complete(&hv_channel_ready);
+ spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
+}
+
+
/*
* VmbusChannelProcessOffer - Process the offer by creating a channel/device
* associated with this offer
@@ -373,22 +393,21 @@
* can cleanup properly
*/
newChannel->State = CHANNEL_OPEN_STATE;
- cnt = 0;
- while (cnt != MAX_MSG_TYPES) {
+ /* Open IC channels */
+ for (cnt = 0; cnt < MAX_MSG_TYPES; cnt++) {
if (memcmp(&newChannel->OfferMsg.Offer.InterfaceType,
&hv_cb_utils[cnt].data,
- sizeof(struct hv_guid)) == 0) {
+ sizeof(struct hv_guid)) == 0 &&
+ VmbusChannelOpen(newChannel, 2 * PAGE_SIZE,
+ 2 * PAGE_SIZE, NULL, 0,
+ hv_cb_utils[cnt].callback,
+ newChannel) == 0) {
+ hv_cb_utils[cnt].channel = newChannel;
DPRINT_INFO(VMBUS, "%s",
- hv_cb_utils[cnt].log_msg);
-
- if (VmbusChannelOpen(newChannel, 2 * PAGE_SIZE,
- 2 * PAGE_SIZE, NULL, 0,
- hv_cb_utils[cnt].callback,
- newChannel) == 0)
- hv_cb_utils[cnt].channel = newChannel;
+ hv_cb_utils[cnt].log_msg);
+ count_hv_channel();
}
- cnt++;
}
}
DPRINT_EXIT(VMBUS);
diff --git a/drivers/staging/hv/hv_utils.c b/drivers/staging/hv/hv_utils.c
index 8a49aaf..2adc9b4 100644
--- a/drivers/staging/hv/hv_utils.c
+++ b/drivers/staging/hv/hv_utils.c
@@ -24,6 +24,8 @@
#include <linux/slab.h>
#include <linux/sysctl.h>
#include <linux/reboot.h>
+#include <linux/dmi.h>
+#include <linux/pci.h>
#include "logging.h"
#include "osd.h"
@@ -251,10 +253,36 @@
DPRINT_EXIT(VMBUS);
}
+static const struct pci_device_id __initconst
+hv_utils_pci_table[] __maybe_unused = {
+ { PCI_DEVICE(0x1414, 0x5353) }, /* Hyper-V emulated VGA controller */
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, hv_utils_pci_table);
+
+
+static const struct dmi_system_id __initconst
+hv_utils_dmi_table[] __maybe_unused = {
+ {
+ .ident = "Hyper-V",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
+ DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"),
+ },
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(dmi, hv_utils_dmi_table);
+
+
static int __init init_hyperv_utils(void)
{
printk(KERN_INFO "Registering HyperV Utility Driver\n");
+ if (!dmi_check_system(hv_utils_dmi_table))
+ return -ENODEV;
+
hv_cb_utils[HV_SHUTDOWN_MSG].channel->OnChannelCallback =
&shutdown_onchannelcallback;
hv_cb_utils[HV_SHUTDOWN_MSG].callback = &shutdown_onchannelcallback;
diff --git a/drivers/staging/hv/vmbus.h b/drivers/staging/hv/vmbus.h
index 0c6ee0f..3c14b29 100644
--- a/drivers/staging/hv/vmbus.h
+++ b/drivers/staging/hv/vmbus.h
@@ -74,4 +74,6 @@
void vmbus_child_driver_unregister(struct driver_context *driver_ctx);
void vmbus_get_interface(struct vmbus_channel_interface *interface);
+extern struct completion hv_channel_ready;
+
#endif /* _VMBUS_H_ */
diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c
index c21731a..22c80ec 100644
--- a/drivers/staging/hv/vmbus_drv.c
+++ b/drivers/staging/hv/vmbus_drv.c
@@ -27,6 +27,7 @@
#include <linux/pci.h>
#include <linux/dmi.h>
#include <linux/slab.h>
+#include <linux/completion.h>
#include "version_info.h"
#include "osd.h"
#include "logging.h"
@@ -356,6 +357,8 @@
vmbus_drv_obj->GetChannelOffers();
+ wait_for_completion(&hv_channel_ready);
+
cleanup:
DPRINT_EXIT(VMBUS_DRV);
diff --git a/drivers/staging/iio/Documentation/iio_utils.h b/drivers/staging/iio/Documentation/iio_utils.h
index a4555e6..014f668 100644
--- a/drivers/staging/iio/Documentation/iio_utils.h
+++ b/drivers/staging/iio/Documentation/iio_utils.h
@@ -62,9 +62,8 @@
1) != 0) {
filename = malloc(strlen(iio_dir)
+ strlen(type)
- + 1
+ numstrlen
- + 1);
+ + 6);
if (filename == NULL)
return -ENOMEM;
sprintf(filename, "%s%s%d/name",
diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c
index 20e2674..905f856 100644
--- a/drivers/staging/iio/adc/max1363_core.c
+++ b/drivers/staging/iio/adc/max1363_core.c
@@ -1011,7 +1011,6 @@
if (!IS_ERR(st->reg))
regulator_put(st->reg);
error_free_st:
- i2c_set_clientdata(client, NULL);
kfree(st);
error_ret:
@@ -1030,7 +1029,6 @@
regulator_disable(st->reg);
regulator_put(st->reg);
}
- i2c_set_clientdata(client, NULL);
kfree(st);
return 0;
diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c
index 43aaacf..e4b0a5e 100644
--- a/drivers/staging/iio/light/tsl2563.c
+++ b/drivers/staging/iio/light/tsl2563.c
@@ -694,7 +694,6 @@
fail2:
iio_device_unregister(chip->indio_dev);
fail1:
- i2c_set_clientdata(client, NULL);
kfree(chip);
return err;
}
@@ -705,7 +704,6 @@
iio_device_unregister(chip->indio_dev);
- i2c_set_clientdata(client, NULL);
kfree(chip);
return 0;
}
diff --git a/drivers/staging/iio/ring_sw.c b/drivers/staging/iio/ring_sw.c
index 1f14cd4..294272d 100644
--- a/drivers/staging/iio/ring_sw.c
+++ b/drivers/staging/iio/ring_sw.c
@@ -20,7 +20,7 @@
if ((length == 0) || (bytes_per_datum == 0))
return -EINVAL;
__iio_update_ring_buffer(&ring->buf, bytes_per_datum, length);
- ring->data = kmalloc(length*ring->buf.bpd, GFP_KERNEL);
+ ring->data = kmalloc(length*ring->buf.bpd, GFP_ATOMIC);
ring->read_p = NULL;
ring->write_p = NULL;
ring->last_written_p = NULL;
diff --git a/drivers/staging/mrst-touchscreen/Kconfig b/drivers/staging/mrst-touchscreen/Kconfig
new file mode 100644
index 0000000..c2af492
--- /dev/null
+++ b/drivers/staging/mrst-touchscreen/Kconfig
@@ -0,0 +1,7 @@
+config TOUCHSCREEN_INTEL_MID
+ tristate "Intel MID platform resistive touchscreen"
+ depends on INTEL_SCU_IPC
+ default y
+ help
+ Say Y here if you have a Intel MID based touchscreen
+ If unsure, say N.
diff --git a/drivers/staging/mrst-touchscreen/Makefile b/drivers/staging/mrst-touchscreen/Makefile
new file mode 100644
index 0000000..2d638b0
--- /dev/null
+++ b/drivers/staging/mrst-touchscreen/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) := intel_mid_touch.o
+
+
diff --git a/drivers/staging/mrst-touchscreen/TODO b/drivers/staging/mrst-touchscreen/TODO
new file mode 100644
index 0000000..7157028
--- /dev/null
+++ b/drivers/staging/mrst-touchscreen/TODO
@@ -0,0 +1,2 @@
+- Move the driver to not think it is SPI (requires fixing some of the SFI
+ and firmware side)
diff --git a/drivers/staging/mrst-touchscreen/intel-mid-touch.c b/drivers/staging/mrst-touchscreen/intel-mid-touch.c
new file mode 100644
index 0000000..abba22f
--- /dev/null
+++ b/drivers/staging/mrst-touchscreen/intel-mid-touch.c
@@ -0,0 +1,864 @@
+/*
+ * intel_mid_touch.c - Intel MID Resistive Touch Screen Driver
+ *
+ * Copyright (C) 2008 Intel Corp
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * 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; version 2 of the License.
+ *
+ * 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; ifnot, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Questions/Comments/Bug fixes to Sreedhara (sreedhara.ds@intel.com)
+ * Ramesh Agarwal (ramesh.agarwal@intel.com)
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * TODO:
+ * kill off mrstouch_debug eventually
+ * review conversion of r/m/w sequences
+ * Replace interrupt mutex abuse
+ * Kill of mrstouchdevp pointer
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/param.h>
+#include <linux/spi/spi.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <asm/intel_scu_ipc.h>
+
+
+#if defined(MRSTOUCH_DEBUG)
+#define mrstouch_debug(fmt, args...)\
+ do { \
+ printk(KERN_DEBUG "\n[MRSTOUCH(%d)] - ", __LINE__); \
+ printk(KERN_DEBUG fmt, ##args); \
+ } while (0);
+#else
+#define mrstouch_debug(fmt, args...)
+#endif
+
+/* PMIC Interrupt registers */
+#define PMIC_REG_ID1 0x00 /*PMIC ID1 register */
+
+/* PMIC Interrupt registers */
+#define PMIC_REG_INT 0x04 /*PMIC interrupt register */
+#define PMIC_REG_MINT 0x05 /*PMIC interrupt mask register */
+
+/* ADC Interrupt registers */
+#define PMIC_REG_ADCINT 0x5F /*ADC interrupt register */
+#define PMIC_REG_MADCINT 0x60 /*ADC interrupt mask register */
+
+/* ADC Control registers */
+#define PMIC_REG_ADCCNTL1 0x61 /*ADC control register */
+
+/* ADC Channel Selection registers */
+#define PMICADDR0 0xA4
+#define END_OF_CHANNEL 0x1F
+
+/* ADC Result register */
+#define PMIC_REG_ADCSNS0H 0x64
+
+/* ADC channels for touch screen */
+#define MRST_TS_CHAN10 0xA /* Touch screen X+ connection */
+#define MRST_TS_CHAN11 0xB /* Touch screen X- connection */
+#define MRST_TS_CHAN12 0xC /* Touch screen Y+ connection */
+#define MRST_TS_CHAN13 0xD /* Touch screen Y- connection */
+
+/* Touch screen coordinate constants */
+#define TOUCH_PRESSURE 50
+#define TOUCH_PRESSURE_FS 100
+
+#define XMOVE_LIMIT 5
+#define YMOVE_LIMIT 5
+#define XYMOVE_CNT 3
+
+#define MAX_10BIT ((1<<10)-1)
+
+/* Touch screen channel BIAS constants */
+#define XBIAS 0x20
+#define YBIAS 0x40
+#define ZBIAS 0x80
+
+/* Touch screen coordinates */
+#define MIN_X 10
+#define MAX_X 1024
+#define MIN_Y 10
+#define MAX_Y 1024
+#define WAIT_ADC_COMPLETION 10
+
+/* PMIC ADC round robin delays */
+#define ADC_LOOP_DELAY0 0x0 /* Continuous loop */
+#define ADC_LOOP_DELAY1 0x1 /* 4.5 ms approximate */
+
+/* PMIC Vendor Identifiers */
+#define PMIC_VENDOR_FS 0 /* PMIC vendor FreeScale */
+#define PMIC_VENDOR_MAXIM 1 /* PMIC vendor MAXIM */
+#define PMIC_VENDOR_NEC 2 /* PMIC vendor NEC */
+#define MRSTOUCH_MAX_CHANNELS 32 /* Maximum ADC channels */
+
+/* Touch screen device structure */
+struct mrstouch_dev {
+ struct spi_device *spi; /* SPI device associated with touch screen */
+ struct input_dev *input; /* input device for touchscreen*/
+ char phys[32]; /* Device name */
+ struct task_struct *pendet_thrd; /* PENDET interrupt handler */
+ struct mutex lock; /* Sync between interrupt and PENDET handler */
+ bool busy; /* Busy flag */
+ u16 asr; /* Address selection register */
+ int irq; /* Touch screen IRQ # */
+ uint vendor; /* PMIC vendor */
+ uint rev; /* PMIC revision */
+ bool suspended; /* Device suspended status */
+ bool disabled; /* Device disabled status */
+ u16 x; /* X coordinate */
+ u16 y; /* Y coordinate */
+ bool pendown; /* PEN position */
+} ;
+
+
+/* Global Pointer to Touch screen device */
+static struct mrstouch_dev *mrstouchdevp;
+
+/* Utility to read PMIC ID */
+static int mrstouch_pmic_id(uint *vendor, uint *rev)
+{
+ int err;
+ u8 r;
+
+ err = intel_scu_ipc_ioread8(PMIC_REG_ID1, &r);
+ if (err)
+ return err;
+
+ *vendor = r & 0x7;
+ *rev = (r >> 3) & 0x7;
+
+ return 0;
+}
+
+/*
+ * Parse ADC channels to find end of the channel configured by other ADC user
+ * NEC and MAXIM requires 4 channels and FreeScale needs 18 channels
+ */
+static int mrstouch_chan_parse(struct mrstouch_dev *tsdev)
+{
+ int err, i, j, found;
+ u32 r32;
+
+ found = -1;
+
+ for (i = 0; i < MRSTOUCH_MAX_CHANNELS; i++) {
+ if (found >= 0)
+ break;
+
+ err = intel_scu_ipc_ioread32(PMICADDR0, &r32);
+ if (err)
+ return err;
+
+ for (j = 0; j < 32; j+= 8) {
+ if (((r32 >> j) & 0xFF) == END_OF_CHANNEL) {
+ found = i;
+ break;
+ }
+ }
+ }
+ if (found < 0)
+ return 0;
+
+ if (tsdev->vendor == PMIC_VENDOR_FS) {
+ if (found && found > (MRSTOUCH_MAX_CHANNELS - 18))
+ return -ENOSPC;
+ } else {
+ if (found && found > (MRSTOUCH_MAX_CHANNELS - 4))
+ return -ENOSPC;
+ }
+ return found;
+}
+
+/* Utility to enable/disable pendet.
+ * pendet set to true enables PENDET interrupt
+ * pendet set to false disables PENDET interrupt
+ * Also clears RND mask bit
+*/
+static int pendet_enable(struct mrstouch_dev *tsdev, bool pendet)
+{
+ u16 reg;
+ u8 r;
+ u8 pendet_enabled = 0;
+ int retry = 0;
+ int err;
+
+ err = intel_scu_ipc_ioread16(PMIC_REG_MADCINT, ®);
+ if (err)
+ return err;
+
+ if (pendet) {
+ reg &= ~0x0005;
+ reg |= 0x2000; /* Enable pendet */
+ } else
+ reg &= 0xDFFF; /* Disable pendet */
+
+ /* Set MADCINT and update ADCCNTL1 (next reg byte) */
+ err = intel_scu_ipc_iowrite16(PMIC_REG_MADCINT, reg);
+ if (!pendet || err)
+ return err;
+
+ /*
+ * Sometimes even after the register write succeeds
+ * the PMIC register value is not updated. Retry few iterations
+ * to enable pendet.
+ */
+
+ err = intel_scu_ipc_ioread8(PMIC_REG_ADCCNTL1, &r);
+ pendet_enabled = (r >> 5) & 0x01;
+
+ retry = 0;
+ while (!err && !pendet_enabled) {
+ retry++;
+ msleep(10);
+ err = intel_scu_ipc_iowrite8(PMIC_REG_ADCCNTL1, reg >> 8);
+ if (err)
+ break;
+ err = intel_scu_ipc_ioread8(PMIC_REG_ADCCNTL1, &r);
+ if (err == 0)
+ pendet_enabled = (r >> 5) & 0x01;
+ if (retry >= 10) {
+ dev_err(&tsdev->spi->dev, "Touch screen disabled.\n");
+ return -EIO;
+ }
+ }
+ return 0;
+}
+
+/* To read PMIC ADC touch screen result
+ * Reads ADC storage registers for higher 7 and lower 3 bits
+ * converts the two readings to single value and turns off gain bit
+ */
+static int mrstouch_ts_chan_read(u16 offset, u16 chan, u16 *vp, u16 *vm)
+{
+ int err;
+ u16 result;
+ u32 res;
+
+ result = PMIC_REG_ADCSNS0H + offset;
+
+ if (chan == MRST_TS_CHAN12)
+ result += 4;
+
+ err = intel_scu_ipc_ioread32(result, &res);
+ if (err)
+ return err;
+
+ /* Mash the bits up */
+
+ *vp = (res & 0xFF) << 3; /* Highest 7 bits */
+ *vp |= (res >> 8) & 0x07; /* Lower 3 bits */
+ *vp &= 0x3FF;
+
+ res >>= 16;
+
+ *vm = (res & 0xFF) << 3; /* Highest 7 bits */
+ *vm |= (res >> 8) & 0x07; /* Lower 3 bits */
+ *vm &= 0x3FF;
+
+ return 0;
+}
+
+/* To configure touch screen channels
+ * Writes touch screen channels to ADC address selection registers
+ */
+static int mrstouch_ts_chan_set(uint offset)
+{
+ int count;
+ u16 chan;
+ u16 reg[5];
+ u8 data[5];
+
+ chan = PMICADDR0 + offset;
+ for (count = 0; count <= 3; count++) {
+ reg[count] = chan++;
+ data[count] = MRST_TS_CHAN10 + count;
+ }
+ reg[count] = chan;
+ data[count] = END_OF_CHANNEL;
+
+ return intel_scu_ipc_writev(reg, data, 5);
+}
+
+/* Initialize ADC */
+static int mrstouch_adc_init(struct mrstouch_dev *tsdev)
+{
+ int err, start;
+ u8 ra, rm;
+
+ err = mrstouch_pmic_id(&tsdev->vendor, &tsdev->rev);
+ if (err) {
+ dev_err(&tsdev->spi->dev, "Unable to read PMIC id\n");
+ return err;
+ }
+
+ start = mrstouch_chan_parse(tsdev);
+ if (start < 0) {
+ dev_err(&tsdev->spi->dev, "Unable to parse channels\n");
+ return start;
+ }
+
+ tsdev->asr = start;
+
+ mrstouch_debug("Channel offset(%d): 0x%X\n", tsdev->asr, tsdev->vendor);
+
+ /* ADC power on, start, enable PENDET and set loop delay
+ * ADC loop delay is set to 4.5 ms approximately
+ * Loop delay more than this results in jitter in adc readings
+ * Setting loop delay to 0 (continous loop) in MAXIM stops PENDET
+ * interrupt generation sometimes.
+ */
+
+ if (tsdev->vendor == PMIC_VENDOR_FS) {
+ ra = 0xE0 | ADC_LOOP_DELAY0;
+ rm = 0x5;
+ } else {
+ /* NEC and MAXIm not consistent with loop delay 0 */
+ ra = 0xE0 | ADC_LOOP_DELAY1;
+ rm = 0x0;
+
+ /* configure touch screen channels */
+ err = mrstouch_ts_chan_set(tsdev->asr);
+ if (err)
+ return err;
+ }
+ err = intel_scu_ipc_update_register(PMIC_REG_ADCCNTL1, ra, 0xE7);
+ if (err == 0)
+ err = intel_scu_ipc_update_register(PMIC_REG_MADCINT, rm, 0x03);
+ return err;
+}
+
+/* Reports x,y coordinates to event subsystem */
+static void mrstouch_report_xy(struct mrstouch_dev *tsdev, u16 x, u16 y, u16 z)
+{
+ int xdiff, ydiff;
+
+ if (tsdev->pendown && z <= TOUCH_PRESSURE) {
+ /* Pen removed, report button release */
+ mrstouch_debug("BTN REL(%d)", z);
+ input_report_key(tsdev->input, BTN_TOUCH, 0);
+ tsdev->pendown = false;
+ }
+
+ xdiff = abs(x - tsdev->x);
+ ydiff = abs(y - tsdev->y);
+
+ /*
+ if x and y values changes for XYMOVE_CNT readings it is considered
+ as stylus is moving. This is required to differentiate between stylus
+ movement and jitter
+ */
+ if (x < MIN_X || x > MAX_X || y < MIN_Y || y > MAX_Y) {
+ /* Spurious values, release button if touched and return */
+ if (tsdev->pendown) {
+ mrstouch_debug("BTN REL(%d)", z);
+ input_report_key(tsdev->input, BTN_TOUCH, 0);
+ tsdev->pendown = false;
+ }
+ return;
+ } else if (xdiff >= XMOVE_LIMIT || ydiff >= YMOVE_LIMIT) {
+ tsdev->x = x;
+ tsdev->y = y;
+
+ input_report_abs(tsdev->input, ABS_X, x);
+ input_report_abs(tsdev->input, ABS_Y, y);
+ input_sync(tsdev->input);
+ }
+
+
+ if (!tsdev->pendown && z > TOUCH_PRESSURE) {
+ /* Pen touched, report button touch */
+ mrstouch_debug("BTN TCH(%d, %d, %d)", x, y, z);
+ input_report_key(tsdev->input, BTN_TOUCH, 1);
+ tsdev->pendown = true;
+ }
+}
+
+
+/* Utility to start ADC, used by freescale handler */
+static int pendet_mask(void)
+{
+ return intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0x02, 0x02);
+}
+
+/* Utility to stop ADC, used by freescale handler */
+static int pendet_umask(void)
+{
+ return intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0x00, 0x02);
+}
+
+/* Utility to read ADC, used by freescale handler */
+static int mrstouch_pmic_fs_adc_read(struct mrstouch_dev *tsdev)
+{
+ int err;
+ u16 x, y, z, result;
+ u16 reg[4];
+ u8 data[4];
+
+ result = PMIC_REG_ADCSNS0H + tsdev->asr;
+
+ reg[0] = result + 4;
+ reg[1] = result + 5;
+ reg[2] = result + 16;
+ reg[3] = result + 17;
+
+ err = intel_scu_ipc_readv(reg, data, 4);
+ if (err)
+ goto ipc_error;
+
+ x = data[0] << 3; /* Higher 7 bits */
+ x |= data[1] & 0x7; /* Lower 3 bits */
+ x &= 0x3FF;
+
+ y = data[2] << 3; /* Higher 7 bits */
+ y |= data[3] & 0x7; /* Lower 3 bits */
+ y &= 0x3FF;
+
+ /* Read Z value */
+ reg[0] = result + 28;
+ reg[1] = result + 29;
+
+ err = intel_scu_ipc_readv(reg, data, 4);
+ if (err)
+ goto ipc_error;
+
+ z = data[0] << 3; /* Higher 7 bits */
+ z |= data[1] & 0x7; /* Lower 3 bits */
+ z &= 0x3FF;
+
+#if defined(MRSTOUCH_PRINT_XYZP)
+ mrstouch_debug("X: %d, Y: %d, Z: %d", x, y, z);
+#endif
+
+ if (z >= TOUCH_PRESSURE_FS) {
+ mrstouch_report_xy(tsdev, x, y, TOUCH_PRESSURE - 1); /* Pen Removed */
+ return TOUCH_PRESSURE - 1;
+ } else {
+ mrstouch_report_xy(tsdev, x, y, TOUCH_PRESSURE + 1); /* Pen Touched */
+ return TOUCH_PRESSURE + 1;
+ }
+
+ return 0;
+
+ipc_error:
+ dev_err(&tsdev->spi->dev, "ipc error during fs_adc read\n");
+ return err;
+}
+
+/* To handle free scale pmic pendet interrupt */
+static int pmic0_pendet(void *dev_id)
+{
+ int err, count;
+ u16 chan;
+ unsigned int touched;
+ struct mrstouch_dev *tsdev = (struct mrstouch_dev *)dev_id;
+ u16 reg[5];
+ u8 data[5];
+
+ chan = PMICADDR0 + tsdev->asr;
+
+ /* Set X BIAS */
+ for (count = 0; count <= 3; count++) {
+ reg[count] = chan++;
+ data[count] = 0x2A;
+ }
+ reg[count] = chan++; /* Dummy */
+ data[count] = 0;
+
+ err = intel_scu_ipc_writev(reg, data, 5);
+ if (err)
+ goto ipc_error;
+
+ msleep(WAIT_ADC_COMPLETION);
+
+ /* Set Y BIAS */
+ for (count = 0; count <= 3; count++) {
+ reg[count] = chan++;
+ data[count] = 0x4A;
+ }
+ reg[count] = chan++; /* Dummy */
+ data[count] = 0;
+
+ err = intel_scu_ipc_writev(reg, data, 5);
+ if (err)
+ goto ipc_error;
+
+ msleep(WAIT_ADC_COMPLETION);
+
+ /* Set Z BIAS */
+ err = intel_scu_ipc_iowrite32(chan + 2, 0x8A8A8A8A);
+ if (err)
+ goto ipc_error;
+
+ msleep(WAIT_ADC_COMPLETION);
+
+ /*Read touch screen channels till pen removed
+ * Freescale reports constant value of z for all points
+ * z is high when screen is not touched and low when touched
+ * Map high z value to not touched and low z value to pen touched
+ */
+ touched = mrstouch_pmic_fs_adc_read(tsdev);
+ while (touched > TOUCH_PRESSURE) {
+ touched = mrstouch_pmic_fs_adc_read(tsdev);
+ msleep(WAIT_ADC_COMPLETION);
+ }
+
+ /* Clear all TS channels */
+ chan = PMICADDR0 + tsdev->asr;
+ for (count = 0; count <= 4; count++) {
+ reg[count] = chan++;
+ data[count] = 0;
+ }
+ err = intel_scu_ipc_writev(reg, data, 5);
+ if (err)
+ goto ipc_error;
+
+ for (count = 0; count <= 4; count++) {
+ reg[count] = chan++;
+ data[count] = 0;
+ }
+ err = intel_scu_ipc_writev(reg, data, 5);
+ if (err)
+ goto ipc_error;
+
+ err = intel_scu_ipc_iowrite32(chan + 2, 0x00000000);
+ if (err)
+ goto ipc_error;
+
+ return 0;
+
+ipc_error:
+ dev_err(&tsdev->spi->dev, "ipc error during pendet\n");
+ return err;
+}
+
+
+/* To enable X, Y and Z bias values
+ * Enables YPYM for X channels and XPXM for Y channels
+ */
+static int mrstouch_ts_bias_set(uint offset, uint bias)
+{
+ int count;
+ u16 chan, start;
+ u16 reg[4];
+ u8 data[4];
+
+ chan = PMICADDR0 + offset;
+ start = MRST_TS_CHAN10;
+
+ for (count = 0; count <= 3; count++) {
+ reg[count] = chan++;
+ data[count] = bias | (start + count);
+ }
+ return intel_scu_ipc_writev(reg, data, 4);
+}
+
+/* To read touch screen channel values */
+static int mrstouch_adc_read(struct mrstouch_dev *tsdev)
+{
+ int err;
+ u16 xp, xm, yp, ym, zp, zm;
+
+ /* configure Y bias for X channels */
+ err = mrstouch_ts_bias_set(tsdev->asr, YBIAS);
+ if (err)
+ goto ipc_error;
+
+ msleep(WAIT_ADC_COMPLETION);
+
+ /* read x+ and x- channels */
+ err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN10, &xp, &xm);
+ if (err)
+ goto ipc_error;
+
+ /* configure x bias for y channels */
+ err = mrstouch_ts_bias_set(tsdev->asr, XBIAS);
+ if (err)
+ goto ipc_error;
+
+ msleep(WAIT_ADC_COMPLETION);
+
+ /* read y+ and y- channels */
+ err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN12, &yp, &ym);
+ if (err)
+ goto ipc_error;
+
+ /* configure z bias for x and y channels */
+ err = mrstouch_ts_bias_set(tsdev->asr, ZBIAS);
+ if (err)
+ goto ipc_error;
+
+ msleep(WAIT_ADC_COMPLETION);
+
+ /* read z+ and z- channels */
+ err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN10, &zp, &zm);
+ if (err)
+ goto ipc_error;
+
+#if defined(MRSTOUCH_PRINT_XYZP)
+ printk(KERN_INFO "X+: %d, Y+: %d, Z+: %d\n", xp, yp, zp);
+#endif
+
+#if defined(MRSTOUCH_PRINT_XYZM)
+ printk(KERN_INFO "X-: %d, Y-: %d, Z-: %d\n", xm, ym, zm);
+#endif
+
+ mrstouch_report_xy(tsdev, xp, yp, zp); /* report x and y to eventX */
+
+ return zp;
+
+ipc_error:
+ dev_err(&tsdev->spi->dev, "ipc error during adc read\n");
+ return err;
+}
+
+/* PENDET interrupt handler function for NEC and MAXIM */
+static void pmic12_pendet(void *data)
+{
+ unsigned int touched;
+ struct mrstouch_dev *tsdev = (struct mrstouch_dev *)data;
+
+ /* read touch screen channels till pen removed */
+ do {
+ touched = mrstouch_adc_read(tsdev);
+ } while (touched > TOUCH_PRESSURE);
+}
+
+/* Handler to process PENDET interrupt */
+int mrstouch_pendet(void *data)
+{
+ struct mrstouch_dev *tsdev = (struct mrstouch_dev *)data;
+ while (1) {
+ /* Wait for PENDET interrupt */
+ if (mutex_lock_interruptible(&tsdev->lock)) {
+ msleep(WAIT_ADC_COMPLETION);
+ continue;
+ }
+
+ if (tsdev->busy)
+ return 0;
+
+ tsdev->busy = true;
+
+ if (tsdev->vendor == PMIC_VENDOR_NEC ||
+ tsdev->vendor == PMIC_VENDOR_MAXIM) {
+ /* PENDET must be disabled in NEC before reading ADC */
+ pendet_enable(tsdev,false); /* Disbale PENDET */
+ pmic12_pendet(tsdev);
+ pendet_enable(tsdev, true); /*Enable PENDET */
+ } else if (tsdev->vendor == PMIC_VENDOR_FS) {
+ pendet_umask(); /* Stop ADC */
+ pmic0_pendet(tsdev);
+ pendet_mask(); /* Stop ADC */
+ } else
+ dev_err(&tsdev->spi->dev, "Unsupported touchscreen: %d\n",
+ tsdev->vendor);
+
+ tsdev->busy = false;
+
+ }
+ return 0;
+}
+
+/* PENDET interrupt handler */
+static irqreturn_t pendet_intr_handler(int irq, void *handle)
+{
+ struct mrstouch_dev *tsdev = (struct mrstouch_dev *)handle;
+
+ mutex_unlock(&tsdev->lock);
+ return IRQ_HANDLED;
+}
+
+/* Intializes input device and registers with input subsystem */
+static int ts_input_dev_init(struct mrstouch_dev *tsdev, struct spi_device *spi)
+{
+ int err = 0;
+
+ mrstouch_debug("%s", __func__);
+
+ tsdev->input = input_allocate_device();
+ if (!tsdev->input) {
+ dev_err(&tsdev->spi->dev, "Unable to allocate input device.\n");
+ return -EINVAL;
+ }
+
+ tsdev->input->name = "mrst_touchscreen";
+ snprintf(tsdev->phys, sizeof(tsdev->phys),
+ "%s/input0", dev_name(&spi->dev));
+ tsdev->input->phys = tsdev->phys;
+ tsdev->input->dev.parent = &spi->dev;
+
+ tsdev->input->id.vendor = tsdev->vendor;
+ tsdev->input->id.version = tsdev->rev;
+
+ tsdev->input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ tsdev->input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+ input_set_abs_params(tsdev->input, ABS_X, MIN_X, MIN_Y, 0, 0);
+ input_set_abs_params(tsdev->input, ABS_Y, MIN_X, MIN_Y, 0, 0);
+
+ err = input_register_device(tsdev->input);
+ if (err) {
+ dev_err(&tsdev->spi->dev, "unable to register input device\n");
+ input_free_device(tsdev->input);
+ return err;
+ }
+
+ mrstouch_debug("%s", "mrstouch initialized");
+
+ return 0;
+
+}
+
+/* Probe function for touch screen driver */
+static int __devinit mrstouch_probe(struct spi_device *mrstouch_spi)
+{
+ int err;
+ unsigned int myirq;
+ struct mrstouch_dev *tsdev;
+
+ mrstouch_debug("%s(%p)", __func__, mrstouch_spi);
+
+ mrstouchdevp = NULL;
+ myirq = mrstouch_spi->irq;
+
+ if (!mrstouch_spi->irq) {
+ dev_err(&mrstouch_spi->dev, "no interrupt assigned\n");
+ return -EINVAL;
+ }
+
+ tsdev = kzalloc(sizeof(struct mrstouch_dev), GFP_KERNEL);
+ if (!tsdev) {
+ dev_err(&mrstouch_spi->dev, "unable to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ tsdev->irq = myirq;
+ mrstouchdevp = tsdev;
+
+ err = mrstouch_adc_init(tsdev);
+ if (err) {
+ dev_err(&mrstouch_spi->dev, "ADC init failed\n");
+ goto mrstouch_err_free_mem;
+ }
+
+ dev_set_drvdata(&mrstouch_spi->dev, tsdev);
+ tsdev->spi = mrstouch_spi;
+
+ err = ts_input_dev_init(tsdev, mrstouch_spi);
+ if (err) {
+ dev_err(&tsdev->spi->dev, "ts_input_dev_init failed");
+ goto mrstouch_err_free_mem;
+ }
+
+ mutex_init(&tsdev->lock);
+ mutex_lock(&tsdev->lock)
+
+ mrstouch_debug("Requesting IRQ-%d", myirq);
+ err = request_irq(myirq, pendet_intr_handler,
+ 0, "mrstouch", tsdev);
+ if (err) {
+ dev_err(&tsdev->spi->dev, "unable to allocate irq\n");
+ goto mrstouch_err_free_mem;
+ }
+
+ tsdev->pendet_thrd = kthread_run(mrstouch_pendet,
+ (void *)tsdev, "pendet handler");
+ if (IS_ERR(tsdev->pendet_thrd)) {
+ dev_err(&tsdev->spi->dev, "kthread_run failed\n");
+ err = PTR_ERR(tsdev->pendet_thrd);
+ goto mrstouch_err_free_mem;
+ }
+ mrstouch_debug("%s", "Driver initialized");
+ return 0;
+
+mrstouch_err_free_mem:
+ kfree(tsdev);
+ return err;
+}
+
+static int mrstouch_suspend(struct spi_device *spi, pm_message_t msg)
+{
+ mrstouch_debug("%s", __func__);
+ mrstouchdevp->suspended = 1;
+ return 0;
+}
+
+static int mrstouch_resume(struct spi_device *spi)
+{
+ mrstouch_debug("%s", __func__);
+ mrstouchdevp->suspended = 0;
+ return 0;
+}
+
+static int mrstouch_remove(struct spi_device *spi)
+{
+ mrstouch_debug("%s", __func__);
+ free_irq(mrstouchdevp->irq, mrstouchdevp);
+ input_unregister_device(mrstouchdevp->input);
+ input_free_device(mrstouchdevp->input);
+ if (mrstouchdevp->pendet_thrd)
+ kthread_stop(mrstouchdevp->pendet_thrd);
+ kfree(mrstouchdevp);
+ return 0;
+}
+
+static struct spi_driver mrstouch_driver = {
+ .driver = {
+ .name = "pmic_touch",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = mrstouch_probe,
+ .suspend = mrstouch_suspend,
+ .resume = mrstouch_resume,
+ .remove = mrstouch_remove,
+};
+
+static int __init mrstouch_module_init(void)
+{
+ int err;
+
+ mrstouch_debug("%s", __func__);
+ err = spi_register_driver(&mrstouch_driver);
+ if (err) {
+ mrstouch_debug("%s(%d)", "SPI PENDET failed", err);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void __exit mrstouch_module_exit(void)
+{
+ mrstouch_debug("%s", __func__);
+ spi_unregister_driver(&mrstouch_driver);
+ return;
+}
+
+module_init(mrstouch_module_init);
+module_exit(mrstouch_module_exit);
+
+MODULE_AUTHOR("Sreedhara Murthy. D.S, sreedhara.ds@intel.com");
+MODULE_DESCRIPTION("Intel Moorestown Resistive Touch Screen Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/msm/Kconfig b/drivers/staging/msm/Kconfig
new file mode 100644
index 0000000..c57039f
--- /dev/null
+++ b/drivers/staging/msm/Kconfig
@@ -0,0 +1,134 @@
+config MSM_STAGING
+ tristate "MSM Frame Buffer Support"
+ depends on FB && ARCH_MSM && !FB_MSM
+ select FB_BACKLIGHT if FB_MSM_BACKLIGHT
+ select NEW_LEDS
+ select LEDS_CLASS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ Support for MSM Framebuffer.
+
+if MSM_STAGING
+
+config FB_MSM_LCDC_HW
+ bool
+ default n
+
+choice
+ prompt "MDP HW version"
+ default FB_MSM_MDP31
+
+config FB_MSM_MDP31
+ select FB_MSM_LCDC_HW
+ bool "MDP HW ver3.1"
+ ---help---
+ Support for MSM MDP HW revision 3.1
+ Say Y here if this is msm8x50 variant platform.
+endchoice
+
+config FB_MSM_LCDC
+ bool
+ default n
+
+config FB_MSM_TVOUT
+ bool
+ default n
+
+config FB_MSM_LCDC_PANEL
+ bool
+ select FB_MSM_LCDC
+ default n
+
+config FB_MSM_LCDC_PRISM_WVGA
+ bool
+ select FB_MSM_LCDC_PANEL
+ default n
+
+config FB_MSM_LCDC_ST1_WXGA
+ bool
+ select FB_MSM_LCDC_PANEL
+ default n
+
+config FB_MSM_LCDC_ST15_WXGA
+ bool
+ select FB_MSM_LCDC_PANEL
+ default n
+
+config FB_MSM_LCDC_WXGA
+ bool
+ select FB_MSM_LCDC_PANEL
+ default n
+
+choice
+ prompt "LCD Panel"
+ default FB_MSM_LCDC_ST15_PANEL
+
+config FB_MSM_LCDC_PRISM_WVGA_PANEL
+ depends on FB_MSM_LCDC_HW
+ bool "LCDC Prism WVGA Panel"
+ select FB_MSM_LCDC_PRISM_WVGA
+ ---help---
+ Support for LCDC Prism WVGA (800x480) panel
+
+
+config FB_MSM_LCDC_ST15_PANEL
+ depends on FB_MSM_LCDC_HW
+ bool "LCDC ST1.5 Panel"
+ select FB_MSM_LCDC_ST15_WXGA
+ ---help---
+ Support for ST1.5 WXGA (1366x768) panel
+
+config FB_MSM_PANEL_NONE
+ bool "NONE"
+ ---help---
+ This will disable LCD panel
+endchoice
+
+choice
+ prompt "Secondary LCD Panel"
+ depends on FB_MSM_MDP31
+ default FB_MSM_SECONDARY_PANEL_NONE
+
+config FB_MSM_SECONDARY_PANEL_NONE
+ bool "NONE"
+ ---help---
+ No secondary panel
+endchoice
+
+config FB_MSM_TVOUT_NTSC
+ bool
+ select FB_MSM_TVOUT
+ default n
+
+config FB_MSM_TVOUT_PAL
+ bool
+ select FB_MSM_TVOUT
+ default n
+
+choice
+ depends on (FB_MSM_MDP22 || FB_MSM_MDP31)
+ prompt "TVOut Region"
+ default FB_MSM_TVOUT_NTSC_M
+
+config FB_MSM_TVOUT_NTSC_M
+ bool "NTSC M"
+ select FB_MSM_TVOUT_NTSC
+ ---help---
+ Support for NTSC M region (North American and Korea)
+
+config FB_MSM_TVOUT_NONE
+ bool "NONE"
+ ---help---
+ This will disable TV Out functionality.
+endchoice
+
+config PMEM_KERNEL_SIZE
+ int "PMEM for kernel components (in MB)"
+ default 2
+ depends on ARCH_QSD8X50
+ help
+ Configures the amount of PMEM for use by kernel components
+ (in MB; minimum 2MB)
+endif
diff --git a/drivers/staging/msm/Makefile b/drivers/staging/msm/Makefile
new file mode 100644
index 0000000..98a0ce1
--- /dev/null
+++ b/drivers/staging/msm/Makefile
@@ -0,0 +1,93 @@
+obj-y := msm_fb.o staging-devices.o memory.o
+
+obj-$(CONFIG_FB_MSM_LOGO) += logo.o
+obj-$(CONFIG_FB_BACKLIGHT) += msm_fb_bl.o
+
+# MDP
+obj-y += mdp.o
+
+ifeq ($(CONFIG_FB_MSM_MDP40),y)
+obj-y += mdp4_util.o
+obj-$(CONFIG_DEBUG_FS) += mdp4_debugfs.o
+else
+obj-y += mdp_hw_init.o
+obj-y += mdp_ppp.o
+ifeq ($(CONFIG_FB_MSM_MDP31),y)
+obj-y += mdp_ppp_v31.o
+obj-$(CONFIG_MDP_PPP_ASYNC_OP) += mdp_ppp_dq.o
+else
+obj-y += mdp_ppp_v20.o
+endif
+endif
+
+ifeq ($(CONFIG_FB_MSM_OVERLAY),y)
+obj-y += mdp4_overlay.o
+obj-y += mdp4_overlay_lcdc.o
+obj-y += mdp4_overlay_mddi.o
+else
+obj-y += mdp_dma_lcdc.o
+endif
+
+obj-y += mdp_dma.o
+obj-y += mdp_dma_s.o
+obj-y += mdp_vsync.o
+obj-y += mdp_cursor.o
+obj-y += mdp_dma_tv.o
+
+# EBI2
+obj-$(CONFIG_FB_MSM_EBI2) += ebi2_lcd.o
+
+# LCDC
+obj-$(CONFIG_FB_MSM_LCDC) += lcdc.o
+
+# MDDI
+msm_mddi-objs := mddi.o mddihost.o mddihosti.o
+obj-$(CONFIG_FB_MSM_MDDI) += msm_mddi.o
+
+# External MDDI
+msm_mddi_ext-objs := mddihost_e.o mddi_ext.o
+obj-$(CONFIG_FB_MSM_EXTMDDI) += msm_mddi_ext.o
+
+# TVEnc
+obj-$(CONFIG_FB_MSM_TVOUT) += tvenc.o
+
+# MSM FB Panel
+obj-y += msm_fb_panel.o
+obj-$(CONFIG_FB_MSM_EBI2_TMD_QVGA_EPSON_QCIF) += ebi2_tmd20.o
+obj-$(CONFIG_FB_MSM_EBI2_TMD_QVGA_EPSON_QCIF) += ebi2_l2f.o
+
+ifeq ($(CONFIG_FB_MSM_MDDI_AUTO_DETECT),y)
+obj-y += mddi_prism.o
+obj-y += mddi_toshiba.o
+obj-y += mddi_toshiba_vga.o
+obj-y += mddi_toshiba_wvga_pt.o
+obj-y += mddi_toshiba_wvga.o
+obj-y += mddi_sharp.o
+else
+obj-$(CONFIG_FB_MSM_MDDI_PRISM_WVGA) += mddi_prism.o
+obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_COMMON) += mddi_toshiba.o
+obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_COMMON_VGA) += mddi_toshiba_vga.o
+obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_WVGA_PORTRAIT) += mddi_toshiba_wvga_pt.o
+obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_WVGA) += mddi_toshiba_wvga.o
+obj-$(CONFIG_FB_MSM_MDDI_SHARP_QVGA_128x128) += mddi_sharp.o
+endif
+
+obj-$(CONFIG_FB_MSM_LCDC_PANEL) += lcdc_panel.o
+obj-$(CONFIG_FB_MSM_LCDC_PRISM_WVGA) += lcdc_prism.o
+obj-$(CONFIG_FB_MSM_LCDC_EXTERNAL_WXGA) += lcdc_external.o
+obj-$(CONFIG_FB_MSM_LCDC_GORDON_VGA) += lcdc_gordon.o
+obj-$(CONFIG_FB_MSM_LCDC_WXGA) += lcdc_wxga.o
+obj-$(CONFIG_FB_MSM_LCDC_TOSHIBA_WVGA_PT) += lcdc_toshiba_wvga_pt.o
+obj-$(CONFIG_FB_MSM_LCDC_SHARP_WVGA_PT) += lcdc_sharp_wvga_pt.o
+obj-$(CONFIG_FB_MSM_LCDC_GRAPEFRUIT_VGA) += lcdc_grapefruit.o
+obj-$(CONFIG_FB_MSM_LCDC_ST1_WXGA) += lcdc_st1_wxga.o
+obj-$(CONFIG_FB_MSM_LCDC_ST15_WXGA) += lcdc_st15.o
+obj-$(CONFIG_FB_MSM_HDMI_SII_EXTERNAL_720P) += hdmi_sii9022.o
+
+obj-$(CONFIG_FB_MSM_TVOUT_NTSC) += tv_ntsc.o
+obj-$(CONFIG_FB_MSM_TVOUT_PAL) += tv_pal.o
+
+obj-$(CONFIG_FB_MSM_EXTMDDI_SVGA) += mddi_ext_lcd.o
+
+clean:
+ rm *.o .*cmd
diff --git a/drivers/staging/msm/TODO b/drivers/staging/msm/TODO
new file mode 100644
index 0000000..05107a7
--- /dev/null
+++ b/drivers/staging/msm/TODO
@@ -0,0 +1,3 @@
+- Merge this code with the existing MSM framebuffer
+- General style clean ups.
+
diff --git a/drivers/staging/msm/ebi2_l2f.c b/drivers/staging/msm/ebi2_l2f.c
new file mode 100644
index 0000000..eea891d
--- /dev/null
+++ b/drivers/staging/msm/ebi2_l2f.c
@@ -0,0 +1,569 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+
+#include <linux/memory.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include "linux/proc_fs.h"
+
+#include <linux/delay.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+/* The following are for MSM5100 on Gator
+*/
+#ifdef FEATURE_PM1000
+#include "pm1000.h"
+#endif /* FEATURE_PM1000 */
+/* The following are for MSM6050 on Bambi
+*/
+#ifdef FEATURE_PMIC_LCDKBD_LED_DRIVER
+#include "pm.h"
+#endif /* FEATURE_PMIC_LCDKBD_LED_DRIVER */
+
+#ifdef DISP_DEVICE_18BPP
+#undef DISP_DEVICE_18BPP
+#define DISP_DEVICE_16BPP
+#endif
+
+#define QCIF_WIDTH 176
+#define QCIF_HEIGHT 220
+
+static void *DISP_CMD_PORT;
+static void *DISP_DATA_PORT;
+
+#define DISP_CMD_DISON 0xaf
+#define DISP_CMD_DISOFF 0xae
+#define DISP_CMD_DISNOR 0xa6
+#define DISP_CMD_DISINV 0xa7
+#define DISP_CMD_DISCTL 0xca
+#define DISP_CMD_GCP64 0xcb
+#define DISP_CMD_GCP16 0xcc
+#define DISP_CMD_GSSET 0xcd
+#define DISP_GS_2 0x02
+#define DISP_GS_16 0x01
+#define DISP_GS_64 0x00
+#define DISP_CMD_SLPIN 0x95
+#define DISP_CMD_SLPOUT 0x94
+#define DISP_CMD_SD_PSET 0x75
+#define DISP_CMD_MD_PSET 0x76
+#define DISP_CMD_SD_CSET 0x15
+#define DISP_CMD_MD_CSET 0x16
+#define DISP_CMD_DATCTL 0xbc
+#define DISP_DATCTL_666 0x08
+#define DISP_DATCTL_565 0x28
+#define DISP_DATCTL_444 0x38
+#define DISP_CMD_RAMWR 0x5c
+#define DISP_CMD_RAMRD 0x5d
+#define DISP_CMD_PTLIN 0xa8
+#define DISP_CMD_PTLOUT 0xa9
+#define DISP_CMD_ASCSET 0xaa
+#define DISP_CMD_SCSTART 0xab
+#define DISP_CMD_VOLCTL 0xc6
+#define DISP_VOLCTL_TONE 0x80
+#define DISP_CMD_NOp 0x25
+#define DISP_CMD_OSSEL 0xd0
+#define DISP_CMD_3500KSET 0xd1
+#define DISP_CMD_3500KEND 0xd2
+#define DISP_CMD_14MSET 0xd3
+#define DISP_CMD_14MEND 0xd4
+
+#define DISP_CMD_OUT(cmd) outpw(DISP_CMD_PORT, cmd);
+
+#define DISP_DATA_OUT(data) outpw(DISP_DATA_PORT, data);
+
+#define DISP_DATA_IN() inpw(DISP_DATA_PORT);
+
+/* Epson device column number starts at 2
+*/
+#define DISP_SET_RECT(ulhc_row, lrhc_row, ulhc_col, lrhc_col) \
+ DISP_CMD_OUT(DISP_CMD_SD_PSET) \
+ DISP_DATA_OUT((ulhc_row) & 0xFF) \
+ DISP_DATA_OUT((ulhc_row) >> 8) \
+ DISP_DATA_OUT((lrhc_row) & 0xFF) \
+ DISP_DATA_OUT((lrhc_row) >> 8) \
+ DISP_CMD_OUT(DISP_CMD_SD_CSET) \
+ DISP_DATA_OUT(((ulhc_col)+2) & 0xFF) \
+ DISP_DATA_OUT(((ulhc_col)+2) >> 8) \
+ DISP_DATA_OUT(((lrhc_col)+2) & 0xFF) \
+ DISP_DATA_OUT(((lrhc_col)+2) >> 8)
+
+#define DISP_MIN_CONTRAST 0
+#define DISP_MAX_CONTRAST 127
+#define DISP_DEFAULT_CONTRAST 80
+
+#define DISP_MIN_BACKLIGHT 0
+#define DISP_MAX_BACKLIGHT 15
+#define DISP_DEFAULT_BACKLIGHT 2
+
+#define WAIT_SEC(sec) mdelay((sec)/1000)
+
+static word disp_area_start_row;
+static word disp_area_end_row;
+static byte disp_contrast = DISP_DEFAULT_CONTRAST;
+static boolean disp_powered_up;
+static boolean disp_initialized = FALSE;
+/* For some reason the contrast set at init time is not good. Need to do
+ * it again
+ */
+static boolean display_on = FALSE;
+static void epsonQcif_disp_init(struct platform_device *pdev);
+static void epsonQcif_disp_set_contrast(word contrast);
+static void epsonQcif_disp_set_display_area(word start_row, word end_row);
+static int epsonQcif_disp_off(struct platform_device *pdev);
+static int epsonQcif_disp_on(struct platform_device *pdev);
+static void epsonQcif_disp_set_rect(int x, int y, int xres, int yres);
+
+volatile word databack;
+static void epsonQcif_disp_init(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+
+ int i;
+
+ if (disp_initialized)
+ return;
+
+ mfd = platform_get_drvdata(pdev);
+
+ DISP_CMD_PORT = mfd->cmd_port;
+ DISP_DATA_PORT = mfd->data_port;
+
+ /* Sleep in */
+ DISP_CMD_OUT(DISP_CMD_SLPIN);
+
+ /* Display off */
+ DISP_CMD_OUT(DISP_CMD_DISOFF);
+
+ /* Display normal */
+ DISP_CMD_OUT(DISP_CMD_DISNOR);
+
+ /* Set data mode */
+ DISP_CMD_OUT(DISP_CMD_DATCTL);
+ DISP_DATA_OUT(DISP_DATCTL_565);
+
+ /* Set display timing */
+ DISP_CMD_OUT(DISP_CMD_DISCTL);
+ DISP_DATA_OUT(0x1c); /* p1 */
+ DISP_DATA_OUT(0x02); /* p1 */
+ DISP_DATA_OUT(0x82); /* p2 */
+ DISP_DATA_OUT(0x00); /* p3 */
+ DISP_DATA_OUT(0x00); /* p4 */
+ DISP_DATA_OUT(0xe0); /* p5 */
+ DISP_DATA_OUT(0x00); /* p5 */
+ DISP_DATA_OUT(0xdc); /* p6 */
+ DISP_DATA_OUT(0x00); /* p6 */
+ DISP_DATA_OUT(0x02); /* p7 */
+ DISP_DATA_OUT(0x00); /* p8 */
+
+ /* Set 64 gray scale level */
+ DISP_CMD_OUT(DISP_CMD_GCP64);
+ DISP_DATA_OUT(0x08); /* p01 */
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x2a); /* p02 */
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x4e); /* p03 */
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x6b); /* p04 */
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x88); /* p05 */
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0xa3); /* p06 */
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0xba); /* p07 */
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0xd1); /* p08 */
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0xe5); /* p09 */
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0xf3); /* p10 */
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x03); /* p11 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x13); /* p12 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x22); /* p13 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x2f); /* p14 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x3b); /* p15 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x46); /* p16 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x51); /* p17 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x5b); /* p18 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x64); /* p19 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x6c); /* p20 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x74); /* p21 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x7c); /* p22 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x83); /* p23 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x8a); /* p24 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x91); /* p25 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x98); /* p26 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x9f); /* p27 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xa6); /* p28 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xac); /* p29 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xb2); /* p30 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xb7); /* p31 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xbc); /* p32 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xc1); /* p33 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xc6); /* p34 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xcb); /* p35 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xd0); /* p36 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xd4); /* p37 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xd8); /* p38 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xdc); /* p39 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xe0); /* p40 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xe4); /* p41 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xe8); /* p42 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xec); /* p43 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xf0); /* p44 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xf4); /* p45 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xf8); /* p46 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xfb); /* p47 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xfe); /* p48 */
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x01); /* p49 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x03); /* p50 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x05); /* p51 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x07); /* p52 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x09); /* p53 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x0b); /* p54 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x0d); /* p55 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x0f); /* p56 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x11); /* p57 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x13); /* p58 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x15); /* p59 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x17); /* p60 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x19); /* p61 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x1b); /* p62 */
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x1c); /* p63 */
+ DISP_DATA_OUT(0x02);
+
+ /* Set 16 gray scale level */
+ DISP_CMD_OUT(DISP_CMD_GCP16);
+ DISP_DATA_OUT(0x1a); /* p01 */
+ DISP_DATA_OUT(0x32); /* p02 */
+ DISP_DATA_OUT(0x42); /* p03 */
+ DISP_DATA_OUT(0x4c); /* p04 */
+ DISP_DATA_OUT(0x58); /* p05 */
+ DISP_DATA_OUT(0x5f); /* p06 */
+ DISP_DATA_OUT(0x66); /* p07 */
+ DISP_DATA_OUT(0x6b); /* p08 */
+ DISP_DATA_OUT(0x70); /* p09 */
+ DISP_DATA_OUT(0x74); /* p10 */
+ DISP_DATA_OUT(0x78); /* p11 */
+ DISP_DATA_OUT(0x7b); /* p12 */
+ DISP_DATA_OUT(0x7e); /* p13 */
+ DISP_DATA_OUT(0x80); /* p14 */
+ DISP_DATA_OUT(0x82); /* p15 */
+
+ /* Set DSP column */
+ DISP_CMD_OUT(DISP_CMD_MD_CSET);
+ DISP_DATA_OUT(0xff);
+ DISP_DATA_OUT(0x03);
+ DISP_DATA_OUT(0xff);
+ DISP_DATA_OUT(0x03);
+
+ /* Set DSP page */
+ DISP_CMD_OUT(DISP_CMD_MD_PSET);
+ DISP_DATA_OUT(0xff);
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0xff);
+ DISP_DATA_OUT(0x01);
+
+ /* Set ARM column */
+ DISP_CMD_OUT(DISP_CMD_SD_CSET);
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT((QCIF_WIDTH + 1) & 0xFF);
+ DISP_DATA_OUT((QCIF_WIDTH + 1) >> 8);
+
+ /* Set ARM page */
+ DISP_CMD_OUT(DISP_CMD_SD_PSET);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT((QCIF_HEIGHT - 1) & 0xFF);
+ DISP_DATA_OUT((QCIF_HEIGHT - 1) >> 8);
+
+ /* Set 64 gray scales */
+ DISP_CMD_OUT(DISP_CMD_GSSET);
+ DISP_DATA_OUT(DISP_GS_64);
+
+ DISP_CMD_OUT(DISP_CMD_OSSEL);
+ DISP_DATA_OUT(0);
+
+ /* Sleep out */
+ DISP_CMD_OUT(DISP_CMD_SLPOUT);
+
+ WAIT_SEC(40000);
+
+ /* Initialize power IC */
+ DISP_CMD_OUT(DISP_CMD_VOLCTL);
+ DISP_DATA_OUT(DISP_VOLCTL_TONE);
+
+ WAIT_SEC(40000);
+
+ /* Set electronic volume, d'xx */
+ DISP_CMD_OUT(DISP_CMD_VOLCTL);
+ DISP_DATA_OUT(DISP_DEFAULT_CONTRAST); /* value from 0 to 127 */
+
+ /* Initialize display data */
+ DISP_SET_RECT(0, (QCIF_HEIGHT - 1), 0, (QCIF_WIDTH - 1));
+ DISP_CMD_OUT(DISP_CMD_RAMWR);
+ for (i = 0; i < QCIF_HEIGHT * QCIF_WIDTH; i++)
+ DISP_DATA_OUT(0xffff);
+
+ DISP_CMD_OUT(DISP_CMD_RAMRD);
+ databack = DISP_DATA_IN();
+ databack = DISP_DATA_IN();
+ databack = DISP_DATA_IN();
+ databack = DISP_DATA_IN();
+
+ WAIT_SEC(80000);
+
+ DISP_CMD_OUT(DISP_CMD_DISON);
+
+ disp_area_start_row = 0;
+ disp_area_end_row = QCIF_HEIGHT - 1;
+ disp_powered_up = TRUE;
+ disp_initialized = TRUE;
+ epsonQcif_disp_set_display_area(0, QCIF_HEIGHT - 1);
+ display_on = TRUE;
+}
+
+static void epsonQcif_disp_set_rect(int x, int y, int xres, int yres)
+{
+ if (!disp_initialized)
+ return;
+
+ DISP_SET_RECT(y, y + yres - 1, x, x + xres - 1);
+ DISP_CMD_OUT(DISP_CMD_RAMWR);
+}
+
+static void epsonQcif_disp_set_display_area(word start_row, word end_row)
+{
+ if (!disp_initialized)
+ return;
+
+ if ((start_row == disp_area_start_row)
+ && (end_row == disp_area_end_row))
+ return;
+ disp_area_start_row = start_row;
+ disp_area_end_row = end_row;
+
+ /* Range checking
+ */
+ if (end_row >= QCIF_HEIGHT)
+ end_row = QCIF_HEIGHT - 1;
+ if (start_row > end_row)
+ start_row = end_row;
+
+ /* When display is not the full screen, gray scale is set to
+ ** 2; otherwise it is set to 64.
+ */
+ if ((start_row == 0) && (end_row == (QCIF_HEIGHT - 1))) {
+ /* The whole screen */
+ DISP_CMD_OUT(DISP_CMD_PTLOUT);
+ WAIT_SEC(10000);
+ DISP_CMD_OUT(DISP_CMD_DISOFF);
+ WAIT_SEC(100000);
+ DISP_CMD_OUT(DISP_CMD_GSSET);
+ DISP_DATA_OUT(DISP_GS_64);
+ WAIT_SEC(100000);
+ DISP_CMD_OUT(DISP_CMD_DISON);
+ } else {
+ /* partial screen */
+ DISP_CMD_OUT(DISP_CMD_PTLIN);
+ DISP_DATA_OUT(start_row);
+ DISP_DATA_OUT(start_row >> 8);
+ DISP_DATA_OUT(end_row);
+ DISP_DATA_OUT(end_row >> 8);
+ DISP_CMD_OUT(DISP_CMD_GSSET);
+ DISP_DATA_OUT(DISP_GS_2);
+ }
+}
+
+static int epsonQcif_disp_off(struct platform_device *pdev)
+{
+ if (!disp_initialized)
+ epsonQcif_disp_init(pdev);
+
+ if (display_on) {
+ DISP_CMD_OUT(DISP_CMD_DISOFF);
+ DISP_CMD_OUT(DISP_CMD_SLPIN);
+ display_on = FALSE;
+ }
+
+ return 0;
+}
+
+static int epsonQcif_disp_on(struct platform_device *pdev)
+{
+ if (!disp_initialized)
+ epsonQcif_disp_init(pdev);
+
+ if (!display_on) {
+ DISP_CMD_OUT(DISP_CMD_SLPOUT);
+ WAIT_SEC(40000);
+ DISP_CMD_OUT(DISP_CMD_DISON);
+ epsonQcif_disp_set_contrast(disp_contrast);
+ display_on = TRUE;
+ }
+
+ return 0;
+}
+
+static void epsonQcif_disp_set_contrast(word contrast)
+{
+ if (!disp_initialized)
+ return;
+
+ /* Initialize power IC, d'24 */
+ DISP_CMD_OUT(DISP_CMD_VOLCTL);
+ DISP_DATA_OUT(DISP_VOLCTL_TONE);
+
+ WAIT_SEC(40000);
+
+ /* Set electronic volume, d'xx */
+ DISP_CMD_OUT(DISP_CMD_VOLCTL);
+ if (contrast > 127)
+ contrast = 127;
+ DISP_DATA_OUT(contrast); /* value from 0 to 127 */
+ disp_contrast = (byte) contrast;
+} /* End disp_set_contrast */
+
+static void epsonQcif_disp_clear_screen_area(
+ word start_row, word end_row, word start_column, word end_column) {
+ int32 i;
+
+ /* Clear the display screen */
+ DISP_SET_RECT(start_row, end_row, start_column, end_column);
+ DISP_CMD_OUT(DISP_CMD_RAMWR);
+ i = (end_row - start_row + 1) * (end_column - start_column + 1);
+ for (; i > 0; i--)
+ DISP_DATA_OUT(0xffff);
+}
+
+static int __init epsonQcif_probe(struct platform_device *pdev)
+{
+ msm_fb_add_device(pdev);
+
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = epsonQcif_probe,
+ .driver = {
+ .name = "ebi2_epson_qcif",
+ },
+};
+
+static struct msm_fb_panel_data epsonQcif_panel_data = {
+ .on = epsonQcif_disp_on,
+ .off = epsonQcif_disp_off,
+ .set_rect = epsonQcif_disp_set_rect,
+};
+
+static struct platform_device this_device = {
+ .name = "ebi2_epson_qcif",
+ .id = 0,
+ .dev = {
+ .platform_data = &epsonQcif_panel_data,
+ }
+};
+
+static int __init epsonQcif_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+
+ ret = platform_driver_register(&this_driver);
+ if (!ret) {
+ pinfo = &epsonQcif_panel_data.panel_info;
+ pinfo->xres = QCIF_WIDTH;
+ pinfo->yres = QCIF_HEIGHT;
+ pinfo->type = EBI2_PANEL;
+ pinfo->pdest = DISPLAY_2;
+ pinfo->wait_cycle = 0x808000;
+ pinfo->bpp = 16;
+ pinfo->fb_num = 2;
+ pinfo->lcd.vsync_enable = FALSE;
+
+ ret = platform_device_register(&this_device);
+ if (ret)
+ platform_driver_unregister(&this_driver);
+ }
+
+ return ret;
+}
+
+module_init(epsonQcif_init);
diff --git a/drivers/staging/msm/ebi2_lcd.c b/drivers/staging/msm/ebi2_lcd.c
new file mode 100644
index 0000000..b41e123
--- /dev/null
+++ b/drivers/staging/msm/ebi2_lcd.c
@@ -0,0 +1,250 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+#include <linux/string.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+#include <linux/vmalloc.h>
+#include <linux/debugfs.h>
+
+#include "msm_fb.h"
+
+static int ebi2_lcd_probe(struct platform_device *pdev);
+static int ebi2_lcd_remove(struct platform_device *pdev);
+
+static struct platform_driver ebi2_lcd_driver = {
+ .probe = ebi2_lcd_probe,
+ .remove = ebi2_lcd_remove,
+ .suspend = NULL,
+ .suspend_late = NULL,
+ .resume_early = NULL,
+ .resume = NULL,
+ .shutdown = NULL,
+ .driver = {
+ .name = "ebi2_lcd",
+ },
+};
+
+static void *ebi2_base;
+static void *ebi2_lcd_cfg0;
+static void *ebi2_lcd_cfg1;
+static void __iomem *lcd01_base;
+static void __iomem *lcd02_base;
+static int ebi2_lcd_resource_initialized;
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+
+static int ebi2_lcd_probe(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ struct platform_device *mdp_dev = NULL;
+ struct msm_fb_panel_data *pdata = NULL;
+ int rc, i;
+
+ if (pdev->id == 0) {
+ for (i = 0; i < pdev->num_resources; i++) {
+ if (!strncmp(pdev->resource[i].name, "base", 4)) {
+ ebi2_base = ioremap(pdev->resource[i].start,
+ pdev->resource[i].end -
+ pdev->resource[i].start + 1);
+ if (!ebi2_base) {
+ printk(KERN_ERR
+ "ebi2_base ioremap failed!\n");
+ return -ENOMEM;
+ }
+ ebi2_lcd_cfg0 = (void *)(ebi2_base + 0x20);
+ ebi2_lcd_cfg1 = (void *)(ebi2_base + 0x24);
+ } else if (!strncmp(pdev->resource[i].name,
+ "lcd01", 5)) {
+ lcd01_base = ioremap(pdev->resource[i].start,
+ pdev->resource[i].end -
+ pdev->resource[i].start + 1);
+ if (!lcd01_base) {
+ printk(KERN_ERR
+ "lcd01_base ioremap failed!\n");
+ return -ENOMEM;
+ }
+ } else if (!strncmp(pdev->resource[i].name,
+ "lcd02", 5)) {
+ lcd02_base = ioremap(pdev->resource[i].start,
+ pdev->resource[i].end -
+ pdev->resource[i].start + 1);
+ if (!lcd02_base) {
+ printk(KERN_ERR
+ "lcd02_base ioremap failed!\n");
+ return -ENOMEM;
+ }
+ }
+ }
+ ebi2_lcd_resource_initialized = 1;
+ return 0;
+ }
+
+ if (!ebi2_lcd_resource_initialized)
+ return -EPERM;
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+ return -ENOMEM;
+
+ if (ebi2_base == NULL)
+ return -ENOMEM;
+
+ mdp_dev = platform_device_alloc("mdp", pdev->id);
+ if (!mdp_dev)
+ return -ENOMEM;
+
+ /* link to the latest pdev */
+ mfd->pdev = mdp_dev;
+ mfd->dest = DISPLAY_LCD;
+
+ /* add panel data */
+ if (platform_device_add_data
+ (mdp_dev, pdev->dev.platform_data,
+ sizeof(struct msm_fb_panel_data))) {
+ printk(KERN_ERR "ebi2_lcd_probe: platform_device_add_data failed!\n");
+ platform_device_put(mdp_dev);
+ return -ENOMEM;
+ }
+
+ /* data chain */
+ pdata = mdp_dev->dev.platform_data;
+ pdata->on = panel_next_on;
+ pdata->off = panel_next_off;
+ pdata->next = pdev;
+
+ /* get/set panel specific fb info */
+ mfd->panel_info = pdata->panel_info;
+
+ if (mfd->panel_info.bpp == 24)
+ mfd->fb_imgType = MDP_RGB_888;
+ else
+ mfd->fb_imgType = MDP_RGB_565;
+
+ /* config msm ebi2 lcd register */
+ if (mfd->panel_info.pdest == DISPLAY_1) {
+ outp32(ebi2_base,
+ (inp32(ebi2_base) & (~(EBI2_PRIM_LCD_CLR))) |
+ EBI2_PRIM_LCD_SEL);
+ /*
+ * current design has one set of cfg0/1 register to control
+ * both EBI2 channels. so, we're using the PRIM channel to
+ * configure both.
+ */
+ outp32(ebi2_lcd_cfg0, mfd->panel_info.wait_cycle);
+ if (mfd->panel_info.bpp == 18)
+ outp32(ebi2_lcd_cfg1, 0x01000000);
+ else
+ outp32(ebi2_lcd_cfg1, 0x0);
+ } else {
+#ifdef DEBUG_EBI2_LCD
+ /*
+ * confliting with QCOM SURF FPGA CS.
+ * OEM should enable below for their CS mapping
+ */
+ outp32(ebi2_base, (inp32(ebi2_base)&(~(EBI2_SECD_LCD_CLR)))
+ |EBI2_SECD_LCD_SEL);
+#endif
+ }
+
+ /*
+ * map cs (chip select) address
+ */
+ if (mfd->panel_info.pdest == DISPLAY_1) {
+ mfd->cmd_port = lcd01_base;
+ mfd->data_port =
+ (void *)((uint32) mfd->cmd_port + EBI2_PRIM_LCD_RS_PIN);
+ mfd->data_port_phys =
+ (void *)(LCD_PRIM_BASE_PHYS + EBI2_PRIM_LCD_RS_PIN);
+ } else {
+ mfd->cmd_port = lcd01_base;
+ mfd->data_port =
+ (void *)((uint32) mfd->cmd_port + EBI2_SECD_LCD_RS_PIN);
+ mfd->data_port_phys =
+ (void *)(LCD_SECD_BASE_PHYS + EBI2_SECD_LCD_RS_PIN);
+ }
+
+ /*
+ * set driver data
+ */
+ platform_set_drvdata(mdp_dev, mfd);
+
+ /*
+ * register in mdp driver
+ */
+ rc = platform_device_add(mdp_dev);
+ if (rc) {
+ goto ebi2_lcd_probe_err;
+ }
+
+ pdev_list[pdev_list_cnt++] = pdev;
+ return 0;
+
+ ebi2_lcd_probe_err:
+ platform_device_put(mdp_dev);
+ return rc;
+}
+
+static int ebi2_lcd_remove(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return 0;
+
+ if (mfd->key != MFD_KEY)
+ return 0;
+
+ iounmap(mfd->cmd_port);
+
+ return 0;
+}
+
+static int ebi2_lcd_register_driver(void)
+{
+ return platform_driver_register(&ebi2_lcd_driver);
+}
+
+static int __init ebi2_lcd_driver_init(void)
+{
+ return ebi2_lcd_register_driver();
+}
+
+module_init(ebi2_lcd_driver_init);
\ No newline at end of file
diff --git a/drivers/staging/msm/ebi2_tmd20.c b/drivers/staging/msm/ebi2_tmd20.c
new file mode 100644
index 0000000..d66d039
--- /dev/null
+++ b/drivers/staging/msm/ebi2_tmd20.c
@@ -0,0 +1,1122 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+
+#include <linux/memory.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include "linux/proc_fs.h"
+
+#include <linux/delay.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+/* #define TMD20QVGA_LCD_18BPP */
+#define QVGA_WIDTH 240
+#define QVGA_HEIGHT 320
+
+#ifdef TMD20QVGA_LCD_18BPP
+#define DISP_QVGA_18BPP(x) ((((x)<<2) & 0x3FC00)|(( (x)<<1)& 0x1FE))
+#define DISP_REG(name) uint32 register_##name;
+#define OUTPORT(x, y) outpdw(x, y)
+#define INPORT(x) inpdw(x)
+#else
+#define DISP_QVGA_18BPP(x) (x)
+#define DISP_REG(name) uint16 register_##name;
+#define OUTPORT(x, y) outpw(x, y)
+#define INPORT(x) intpw(x)
+#endif
+
+static void *DISP_CMD_PORT;
+static void *DISP_DATA_PORT;
+
+#define DISP_RNTI 0x10
+
+#define DISP_CMD_OUT(cmd) OUTPORT(DISP_CMD_PORT, DISP_QVGA_18BPP(cmd))
+#define DISP_DATA_OUT(data) OUTPORT(DISP_DATA_PORT, data)
+#define DISP_DATA_IN() INPORT(DISP_DATA_PORT)
+
+#if (defined(TMD20QVGA_LCD_18BPP))
+#define DISP_DATA_OUT_16TO18BPP(x) \
+ DISP_DATA_OUT((((x)&0xf800)<<2|((x)&0x80000)>>3) \
+ | (((x)&0x7e0)<<1) \
+ | (((x)&0x1F)<<1|((x)&0x10)>>4))
+#else
+#define DISP_DATA_OUT_16TO18BPP(x) \
+ DISP_DATA_OUT(x)
+#endif
+
+#define DISP_WRITE_OUT(addr, data) \
+ register_##addr = DISP_QVGA_18BPP(data); \
+ DISP_CMD_OUT(addr); \
+ DISP_DATA_OUT(register_##addr);
+
+#define DISP_UPDATE_VALUE(addr, bitmask, data) \
+ DISP_WRITE_OUT(##addr, (register_##addr & ~(bitmask)) | (data));
+
+#define DISP_VAL_IF(bitvalue, bitmask) \
+ ((bitvalue) ? (bitmask) : 0)
+
+/* QVGA = 256 x 320 */
+/* actual display is 240 x 320...offset by 0x10 */
+#define DISP_ROW_COL_TO_ADDR(row, col) ((row) * 0x100 + col)
+#define DISP_SET_RECT(ulhc_row, lrhc_row, ulhc_col, lrhc_col) \
+ { \
+ DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_1_ADDR, (ulhc_col) + tmd20qvga_panel_offset); \
+ DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_2_ADDR, (lrhc_col) + tmd20qvga_panel_offset); \
+ DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_1_ADDR, (ulhc_row)); \
+ DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_2_ADDR, (lrhc_row)); \
+ DISP_WRITE_OUT(DISP_RAM_ADDR_SET_1_ADDR, (ulhc_col) + tmd20qvga_panel_offset); \
+ DISP_WRITE_OUT(DISP_RAM_ADDR_SET_2_ADDR, (ulhc_row)); \
+ }
+
+#define WAIT_MSEC(msec) mdelay(msec)
+
+/*
+ * TMD QVGA Address
+ */
+/* Display Control */
+#define DISP_START_OSCILLATION_ADDR 0x000
+DISP_REG(DISP_START_OSCILLATION_ADDR)
+#define DISP_DRIVER_OUTPUT_CTL_ADDR 0x001
+ DISP_REG(DISP_DRIVER_OUTPUT_CTL_ADDR)
+#define DISP_LCD_DRIVING_SIG_ADDR 0x002
+ DISP_REG(DISP_LCD_DRIVING_SIG_ADDR)
+#define DISP_ENTRY_MODE_ADDR 0x003
+ DISP_REG(DISP_ENTRY_MODE_ADDR)
+#define DISP_DISPLAY_CTL_1_ADDR 0x007
+ DISP_REG(DISP_DISPLAY_CTL_1_ADDR)
+#define DISP_DISPLAY_CTL_2_ADDR 0x008
+ DISP_REG(DISP_DISPLAY_CTL_2_ADDR)
+
+/* DISPLAY MODE 0x009 partial display not supported */
+#define DISP_POWER_SUPPLY_INTF_ADDR 0x00A
+ DISP_REG(DISP_POWER_SUPPLY_INTF_ADDR)
+
+/* DISPLAY MODE 0x00B xZoom feature is not supported */
+#define DISP_EXT_DISPLAY_CTL_1_ADDR 0x00C
+ DISP_REG(DISP_EXT_DISPLAY_CTL_1_ADDR)
+
+#define DISP_FRAME_CYCLE_CTL_ADDR 0x00D
+ DISP_REG(DISP_FRAME_CYCLE_CTL_ADDR)
+
+#define DISP_EXT_DISPLAY_CTL_2_ADDR 0x00E
+ DISP_REG(DISP_EXT_DISPLAY_CTL_2_ADDR)
+
+#define DISP_EXT_DISPLAY_CTL_3_ADDR 0x00F
+ DISP_REG(DISP_EXT_DISPLAY_CTL_3_ADDR)
+
+#define DISP_LTPS_CTL_1_ADDR 0x012
+ DISP_REG(DISP_LTPS_CTL_1_ADDR)
+#define DISP_LTPS_CTL_2_ADDR 0x013
+ DISP_REG(DISP_LTPS_CTL_2_ADDR)
+#define DISP_LTPS_CTL_3_ADDR 0x014
+ DISP_REG(DISP_LTPS_CTL_3_ADDR)
+#define DISP_LTPS_CTL_4_ADDR 0x018
+ DISP_REG(DISP_LTPS_CTL_4_ADDR)
+#define DISP_LTPS_CTL_5_ADDR 0x019
+ DISP_REG(DISP_LTPS_CTL_5_ADDR)
+#define DISP_LTPS_CTL_6_ADDR 0x01A
+ DISP_REG(DISP_LTPS_CTL_6_ADDR)
+#define DISP_AMP_SETTING_ADDR 0x01C
+ DISP_REG(DISP_AMP_SETTING_ADDR)
+#define DISP_MODE_SETTING_ADDR 0x01D
+ DISP_REG(DISP_MODE_SETTING_ADDR)
+#define DISP_POFF_LN_SETTING_ADDR 0x01E
+ DISP_REG(DISP_POFF_LN_SETTING_ADDR)
+/* Power Contol */
+#define DISP_POWER_CTL_1_ADDR 0x100
+ DISP_REG(DISP_POWER_CTL_1_ADDR)
+#define DISP_POWER_CTL_2_ADDR 0x101
+ DISP_REG(DISP_POWER_CTL_2_ADDR)
+#define DISP_POWER_CTL_3_ADDR 0x102
+ DISP_REG(DISP_POWER_CTL_3_ADDR)
+#define DISP_POWER_CTL_4_ADDR 0x103
+ DISP_REG(DISP_POWER_CTL_4_ADDR)
+#define DISP_POWER_CTL_5_ADDR 0x104
+ DISP_REG(DISP_POWER_CTL_5_ADDR)
+#define DISP_POWER_CTL_6_ADDR 0x105
+ DISP_REG(DISP_POWER_CTL_6_ADDR)
+#define DISP_POWER_CTL_7_ADDR 0x106
+ DISP_REG(DISP_POWER_CTL_7_ADDR)
+/* RAM Access */
+#define DISP_RAM_ADDR_SET_1_ADDR 0x200
+ DISP_REG(DISP_RAM_ADDR_SET_1_ADDR)
+#define DISP_RAM_ADDR_SET_2_ADDR 0x201
+ DISP_REG(DISP_RAM_ADDR_SET_2_ADDR)
+#define DISP_CMD_RAMRD DISP_CMD_RAMWR
+#define DISP_CMD_RAMWR 0x202
+ DISP_REG(DISP_CMD_RAMWR)
+#define DISP_RAM_DATA_MASK_1_ADDR 0x203
+ DISP_REG(DISP_RAM_DATA_MASK_1_ADDR)
+#define DISP_RAM_DATA_MASK_2_ADDR 0x204
+ DISP_REG(DISP_RAM_DATA_MASK_2_ADDR)
+/* Gamma Control, Contrast, Gray Scale Setting */
+#define DISP_GAMMA_CONTROL_1_ADDR 0x300
+ DISP_REG(DISP_GAMMA_CONTROL_1_ADDR)
+#define DISP_GAMMA_CONTROL_2_ADDR 0x301
+ DISP_REG(DISP_GAMMA_CONTROL_2_ADDR)
+#define DISP_GAMMA_CONTROL_3_ADDR 0x302
+ DISP_REG(DISP_GAMMA_CONTROL_3_ADDR)
+#define DISP_GAMMA_CONTROL_4_ADDR 0x303
+ DISP_REG(DISP_GAMMA_CONTROL_4_ADDR)
+#define DISP_GAMMA_CONTROL_5_ADDR 0x304
+ DISP_REG(DISP_GAMMA_CONTROL_5_ADDR)
+/* Coordinate Control */
+#define DISP_VERT_SCROLL_CTL_1_ADDR 0x400
+ DISP_REG(DISP_VERT_SCROLL_CTL_1_ADDR)
+#define DISP_VERT_SCROLL_CTL_2_ADDR 0x401
+ DISP_REG(DISP_VERT_SCROLL_CTL_2_ADDR)
+#define DISP_SCREEN_1_DRV_POS_1_ADDR 0x402
+ DISP_REG(DISP_SCREEN_1_DRV_POS_1_ADDR)
+#define DISP_SCREEN_1_DRV_POS_2_ADDR 0x403
+ DISP_REG(DISP_SCREEN_1_DRV_POS_2_ADDR)
+#define DISP_SCREEN_2_DRV_POS_1_ADDR 0x404
+ DISP_REG(DISP_SCREEN_2_DRV_POS_1_ADDR)
+#define DISP_SCREEN_2_DRV_POS_2_ADDR 0x405
+ DISP_REG(DISP_SCREEN_2_DRV_POS_2_ADDR)
+#define DISP_HORZ_RAM_ADDR_POS_1_ADDR 0x406
+ DISP_REG(DISP_HORZ_RAM_ADDR_POS_1_ADDR)
+#define DISP_HORZ_RAM_ADDR_POS_2_ADDR 0x407
+ DISP_REG(DISP_HORZ_RAM_ADDR_POS_2_ADDR)
+#define DISP_VERT_RAM_ADDR_POS_1_ADDR 0x408
+ DISP_REG(DISP_VERT_RAM_ADDR_POS_1_ADDR)
+#define DISP_VERT_RAM_ADDR_POS_2_ADDR 0x409
+ DISP_REG(DISP_VERT_RAM_ADDR_POS_2_ADDR)
+#define DISP_TMD_700_ADDR 0x700 /* 0x700 */
+ DISP_REG(DISP_TMD_700_ADDR)
+#define DISP_TMD_015_ADDR 0x015 /* 0x700 */
+ DISP_REG(DISP_TMD_015_ADDR)
+#define DISP_TMD_305_ADDR 0x305 /* 0x700 */
+ DISP_REG(DISP_TMD_305_ADDR)
+
+/*
+ * TMD QVGA Bit Definations
+ */
+
+#define DISP_BIT_IB15 0x8000
+#define DISP_BIT_IB14 0x4000
+#define DISP_BIT_IB13 0x2000
+#define DISP_BIT_IB12 0x1000
+#define DISP_BIT_IB11 0x0800
+#define DISP_BIT_IB10 0x0400
+#define DISP_BIT_IB09 0x0200
+#define DISP_BIT_IB08 0x0100
+#define DISP_BIT_IB07 0x0080
+#define DISP_BIT_IB06 0x0040
+#define DISP_BIT_IB05 0x0020
+#define DISP_BIT_IB04 0x0010
+#define DISP_BIT_IB03 0x0008
+#define DISP_BIT_IB02 0x0004
+#define DISP_BIT_IB01 0x0002
+#define DISP_BIT_IB00 0x0001
+/*
+ * Display Control
+ * DISP_START_OSCILLATION_ADDR Start Oscillation
+ * DISP_DRIVER_OUTPUT_CTL_ADDR Driver Output Control
+ */
+#define DISP_BITMASK_SS DISP_BIT_IB08
+#define DISP_BITMASK_NL5 DISP_BIT_IB05
+#define DISP_BITMASK_NL4 DISP_BIT_IB04
+#define DISP_BITMASK_NL3 DISP_BIT_IB03
+#define DISP_BITMASK_NL2 DISP_BIT_IB02
+#define DISP_BITMASK_NL1 DISP_BIT_IB01
+#define DISP_BITMASK_NL0 DISP_BIT_IB00
+/* DISP_LCD_DRIVING_SIG_ADDR LCD Driving Signal Setting */
+#define DISP_BITMASK_BC DISP_BIT_IB09
+/* DISP_ENTRY_MODE_ADDR Entry Mode */
+#define DISP_BITMASK_TRI DISP_BIT_IB15
+#define DISP_BITMASK_DFM1 DISP_BIT_IB14
+#define DISP_BITMASK_DFM0 DISP_BIT_IB13
+#define DISP_BITMASK_BGR DISP_BIT_IB12
+#define DISP_BITMASK_HWM0 DISP_BIT_IB08
+#define DISP_BITMASK_ID1 DISP_BIT_IB05
+#define DISP_BITMASK_ID0 DISP_BIT_IB04
+#define DISP_BITMASK_AM DISP_BIT_IB03
+/* DISP_DISPLAY_CTL_1_ADDR Display Control (1) */
+#define DISP_BITMASK_COL1 DISP_BIT_IB15
+#define DISP_BITMASK_COL0 DISP_BIT_IB14
+#define DISP_BITMASK_VLE2 DISP_BIT_IB10
+#define DISP_BITMASK_VLE1 DISP_BIT_IB09
+#define DISP_BITMASK_SPT DISP_BIT_IB08
+#define DISP_BITMASK_PT1 DISP_BIT_IB07
+#define DISP_BITMASK_PT0 DISP_BIT_IB06
+#define DISP_BITMASK_REV DISP_BIT_IB02
+/* DISP_DISPLAY_CTL_2_ADDR Display Control (2) */
+#define DISP_BITMASK_FP3 DISP_BIT_IB11
+#define DISP_BITMASK_FP2 DISP_BIT_IB10
+#define DISP_BITMASK_FP1 DISP_BIT_IB09
+#define DISP_BITMASK_FP0 DISP_BIT_IB08
+#define DISP_BITMASK_BP3 DISP_BIT_IB03
+#define DISP_BITMASK_BP2 DISP_BIT_IB02
+#define DISP_BITMASK_BP1 DISP_BIT_IB01
+#define DISP_BITMASK_BP0 DISP_BIT_IB00
+/* DISP_POWER_SUPPLY_INTF_ADDR Power Supply IC Interface Control */
+#define DISP_BITMASK_CSE DISP_BIT_IB12
+#define DISP_BITMASK_TE DISP_BIT_IB08
+#define DISP_BITMASK_IX3 DISP_BIT_IB03
+#define DISP_BITMASK_IX2 DISP_BIT_IB02
+#define DISP_BITMASK_IX1 DISP_BIT_IB01
+#define DISP_BITMASK_IX0 DISP_BIT_IB00
+/* DISP_EXT_DISPLAY_CTL_1_ADDR External Display Interface Control (1) */
+#define DISP_BITMASK_RM DISP_BIT_IB08
+#define DISP_BITMASK_DM1 DISP_BIT_IB05
+#define DISP_BITMASK_DM0 DISP_BIT_IB04
+#define DISP_BITMASK_RIM1 DISP_BIT_IB01
+#define DISP_BITMASK_RIM0 DISP_BIT_IB00
+/* DISP_FRAME_CYCLE_CTL_ADDR Frame Frequency Adjustment Control */
+#define DISP_BITMASK_DIVI1 DISP_BIT_IB09
+#define DISP_BITMASK_DIVI0 DISP_BIT_IB08
+#define DISP_BITMASK_RTNI4 DISP_BIT_IB04
+#define DISP_BITMASK_RTNI3 DISP_BIT_IB03
+#define DISP_BITMASK_RTNI2 DISP_BIT_IB02
+#define DISP_BITMASK_RTNI1 DISP_BIT_IB01
+#define DISP_BITMASK_RTNI0 DISP_BIT_IB00
+/* DISP_EXT_DISPLAY_CTL_2_ADDR External Display Interface Control (2) */
+#define DISP_BITMASK_DIVE1 DISP_BIT_IB09
+#define DISP_BITMASK_DIVE0 DISP_BIT_IB08
+#define DISP_BITMASK_RTNE7 DISP_BIT_IB07
+#define DISP_BITMASK_RTNE6 DISP_BIT_IB06
+#define DISP_BITMASK_RTNE5 DISP_BIT_IB05
+#define DISP_BITMASK_RTNE4 DISP_BIT_IB04
+#define DISP_BITMASK_RTNE3 DISP_BIT_IB03
+#define DISP_BITMASK_RTNE2 DISP_BIT_IB02
+#define DISP_BITMASK_RTNE1 DISP_BIT_IB01
+#define DISP_BITMASK_RTNE0 DISP_BIT_IB00
+/* DISP_EXT_DISPLAY_CTL_3_ADDR External Display Interface Control (3) */
+#define DISP_BITMASK_VSPL DISP_BIT_IB04
+#define DISP_BITMASK_HSPL DISP_BIT_IB03
+#define DISP_BITMASK_VPL DISP_BIT_IB02
+#define DISP_BITMASK_EPL DISP_BIT_IB01
+#define DISP_BITMASK_DPL DISP_BIT_IB00
+/* DISP_LTPS_CTL_1_ADDR LTPS Interface Control (1) */
+#define DISP_BITMASK_CLWI3 DISP_BIT_IB11
+#define DISP_BITMASK_CLWI2 DISP_BIT_IB10
+#define DISP_BITMASK_CLWI1 DISP_BIT_IB09
+#define DISP_BITMASK_CLWI0 DISP_BIT_IB08
+#define DISP_BITMASK_CLTI1 DISP_BIT_IB01
+#define DISP_BITMASK_CLTI0 DISP_BIT_IB00
+/* DISP_LTPS_CTL_2_ADDR LTPS Interface Control (2) */
+#define DISP_BITMASK_OEVBI1 DISP_BIT_IB09
+#define DISP_BITMASK_OEVBI0 DISP_BIT_IB08
+#define DISP_BITMASK_OEVFI1 DISP_BIT_IB01
+#define DISP_BITMASK_OEVFI0 DISP_BIT_IB00
+/* DISP_LTPS_CTL_3_ADDR LTPS Interface Control (3) */
+#define DISP_BITMASK_SHI1 DISP_BIT_IB01
+#define DISP_BITMASK_SHI0 DISP_BIT_IB00
+/* DISP_LTPS_CTL_4_ADDR LTPS Interface Control (4) */
+#define DISP_BITMASK_CLWE5 DISP_BIT_IB13
+#define DISP_BITMASK_CLWE4 DISP_BIT_IB12
+#define DISP_BITMASK_CLWE3 DISP_BIT_IB11
+#define DISP_BITMASK_CLWE2 DISP_BIT_IB10
+#define DISP_BITMASK_CLWE1 DISP_BIT_IB09
+#define DISP_BITMASK_CLWE0 DISP_BIT_IB08
+#define DISP_BITMASK_CLTE3 DISP_BIT_IB03
+#define DISP_BITMASK_CLTE2 DISP_BIT_IB02
+#define DISP_BITMASK_CLTE1 DISP_BIT_IB01
+#define DISP_BITMASK_CLTE0 DISP_BIT_IB00
+/* DISP_LTPS_CTL_5_ADDR LTPS Interface Control (5) */
+#define DISP_BITMASK_OEVBE3 DISP_BIT_IB11
+#define DISP_BITMASK_OEVBE2 DISP_BIT_IB10
+#define DISP_BITMASK_OEVBE1 DISP_BIT_IB09
+#define DISP_BITMASK_OEVBE0 DISP_BIT_IB08
+#define DISP_BITMASK_OEVFE3 DISP_BIT_IB03
+#define DISP_BITMASK_OEVFE2 DISP_BIT_IB02
+#define DISP_BITMASK_OEVFE1 DISP_BIT_IB01
+#define DISP_BITMASK_OEVFE0 DISP_BIT_IB00
+/* DISP_LTPS_CTL_6_ADDR LTPS Interface Control (6) */
+#define DISP_BITMASK_SHE3 DISP_BIT_IB03
+#define DISP_BITMASK_SHE2 DISP_BIT_IB02
+#define DISP_BITMASK_SHE1 DISP_BIT_IB01
+#define DISP_BITMASK_SHE0 DISP_BIT_IB00
+/* DISP_AMP_SETTING_ADDR Amplify Setting */
+#define DISP_BITMASK_ABSW1 DISP_BIT_IB01
+#define DISP_BITMASK_ABSW0 DISP_BIT_IB00
+/* DISP_MODE_SETTING_ADDR Mode Setting */
+#define DISP_BITMASK_DSTB DISP_BIT_IB02
+#define DISP_BITMASK_STB DISP_BIT_IB00
+/* DISP_POFF_LN_SETTING_ADDR Power Off Line Setting */
+#define DISP_BITMASK_POFH3 DISP_BIT_IB03
+#define DISP_BITMASK_POFH2 DISP_BIT_IB02
+#define DISP_BITMASK_POFH1 DISP_BIT_IB01
+#define DISP_BITMASK_POFH0 DISP_BIT_IB00
+
+/* Power Contol */
+/* DISP_POWER_CTL_1_ADDR Power Control (1) */
+#define DISP_BITMASK_PO DISP_BIT_IB11
+#define DISP_BITMASK_VCD DISP_BIT_IB09
+#define DISP_BITMASK_VSC DISP_BIT_IB08
+#define DISP_BITMASK_CON DISP_BIT_IB07
+#define DISP_BITMASK_ASW1 DISP_BIT_IB06
+#define DISP_BITMASK_ASW0 DISP_BIT_IB05
+#define DISP_BITMASK_OEV DISP_BIT_IB04
+#define DISP_BITMASK_OEVE DISP_BIT_IB03
+#define DISP_BITMASK_FR DISP_BIT_IB02
+#define DISP_BITMASK_D1 DISP_BIT_IB01
+#define DISP_BITMASK_D0 DISP_BIT_IB00
+/* DISP_POWER_CTL_2_ADDR Power Control (2) */
+#define DISP_BITMASK_DC4 DISP_BIT_IB15
+#define DISP_BITMASK_DC3 DISP_BIT_IB14
+#define DISP_BITMASK_SAP2 DISP_BIT_IB13
+#define DISP_BITMASK_SAP1 DISP_BIT_IB12
+#define DISP_BITMASK_SAP0 DISP_BIT_IB11
+#define DISP_BITMASK_BT2 DISP_BIT_IB10
+#define DISP_BITMASK_BT1 DISP_BIT_IB09
+#define DISP_BITMASK_BT0 DISP_BIT_IB08
+#define DISP_BITMASK_DC2 DISP_BIT_IB07
+#define DISP_BITMASK_DC1 DISP_BIT_IB06
+#define DISP_BITMASK_DC0 DISP_BIT_IB05
+#define DISP_BITMASK_AP2 DISP_BIT_IB04
+#define DISP_BITMASK_AP1 DISP_BIT_IB03
+#define DISP_BITMASK_AP0 DISP_BIT_IB02
+/* DISP_POWER_CTL_3_ADDR Power Control (3) */
+#define DISP_BITMASK_VGL4 DISP_BIT_IB10
+#define DISP_BITMASK_VGL3 DISP_BIT_IB09
+#define DISP_BITMASK_VGL2 DISP_BIT_IB08
+#define DISP_BITMASK_VGL1 DISP_BIT_IB07
+#define DISP_BITMASK_VGL0 DISP_BIT_IB06
+#define DISP_BITMASK_VGH4 DISP_BIT_IB04
+#define DISP_BITMASK_VGH3 DISP_BIT_IB03
+#define DISP_BITMASK_VGH2 DISP_BIT_IB02
+#define DISP_BITMASK_VGH1 DISP_BIT_IB01
+#define DISP_BITMASK_VGH0 DISP_BIT_IB00
+/* DISP_POWER_CTL_4_ADDR Power Control (4) */
+#define DISP_BITMASK_VC2 DISP_BIT_IB02
+#define DISP_BITMASK_VC1 DISP_BIT_IB01
+#define DISP_BITMASK_VC0 DISP_BIT_IB00
+/* DISP_POWER_CTL_5_ADDR Power Control (5) */
+#define DISP_BITMASK_VRL3 DISP_BIT_IB11
+#define DISP_BITMASK_VRL2 DISP_BIT_IB10
+#define DISP_BITMASK_VRL1 DISP_BIT_IB09
+#define DISP_BITMASK_VRL0 DISP_BIT_IB08
+#define DISP_BITMASK_PON DISP_BIT_IB04
+#define DISP_BITMASK_VRH3 DISP_BIT_IB03
+#define DISP_BITMASK_VRH2 DISP_BIT_IB02
+#define DISP_BITMASK_VRH1 DISP_BIT_IB01
+#define DISP_BITMASK_VRH0 DISP_BIT_IB00
+/* DISP_POWER_CTL_6_ADDR Power Control (6) */
+#define DISP_BITMASK_VCOMG DISP_BIT_IB13
+#define DISP_BITMASK_VDV4 DISP_BIT_IB12
+#define DISP_BITMASK_VDV3 DISP_BIT_IB11
+#define DISP_BITMASK_VDV2 DISP_BIT_IB10
+#define DISP_BITMASK_VDV1 DISP_BIT_IB09
+#define DISP_BITMASK_VDV0 DISP_BIT_IB08
+#define DISP_BITMASK_VCM4 DISP_BIT_IB04
+#define DISP_BITMASK_VCM3 DISP_BIT_IB03
+#define DISP_BITMASK_VCM2 DISP_BIT_IB02
+#define DISP_BITMASK_VCM1 DISP_BIT_IB01
+#define DISP_BITMASK_VCM0 DISP_BIT_IB00
+/* RAM Access */
+/* DISP_RAM_ADDR_SET_1_ADDR RAM Address Set (1) */
+#define DISP_BITMASK_AD7 DISP_BIT_IB07
+#define DISP_BITMASK_AD6 DISP_BIT_IB06
+#define DISP_BITMASK_AD5 DISP_BIT_IB05
+#define DISP_BITMASK_AD4 DISP_BIT_IB04
+#define DISP_BITMASK_AD3 DISP_BIT_IB03
+#define DISP_BITMASK_AD2 DISP_BIT_IB02
+#define DISP_BITMASK_AD1 DISP_BIT_IB01
+#define DISP_BITMASK_AD0 DISP_BIT_IB00
+/* DISP_RAM_ADDR_SET_2_ADDR RAM Address Set (2) */
+#define DISP_BITMASK_AD16 DISP_BIT_IB08
+#define DISP_BITMASK_AD15 DISP_BIT_IB07
+#define DISP_BITMASK_AD14 DISP_BIT_IB06
+#define DISP_BITMASK_AD13 DISP_BIT_IB05
+#define DISP_BITMASK_AD12 DISP_BIT_IB04
+#define DISP_BITMASK_AD11 DISP_BIT_IB03
+#define DISP_BITMASK_AD10 DISP_BIT_IB02
+#define DISP_BITMASK_AD9 DISP_BIT_IB01
+#define DISP_BITMASK_AD8 DISP_BIT_IB00
+/*
+ * DISP_CMD_RAMWR RAM Data Read/Write
+ * Use Data Bit Configuration
+ */
+/* DISP_RAM_DATA_MASK_1_ADDR RAM Write Data Mask (1) */
+#define DISP_BITMASK_WM11 DISP_BIT_IB13
+#define DISP_BITMASK_WM10 DISP_BIT_IB12
+#define DISP_BITMASK_WM9 DISP_BIT_IB11
+#define DISP_BITMASK_WM8 DISP_BIT_IB10
+#define DISP_BITMASK_WM7 DISP_BIT_IB09
+#define DISP_BITMASK_WM6 DISP_BIT_IB08
+#define DISP_BITMASK_WM5 DISP_BIT_IB05
+#define DISP_BITMASK_WM4 DISP_BIT_IB04
+#define DISP_BITMASK_WM3 DISP_BIT_IB03
+#define DISP_BITMASK_WM2 DISP_BIT_IB02
+#define DISP_BITMASK_WM1 DISP_BIT_IB01
+#define DISP_BITMASK_WM0 DISP_BIT_IB00
+/* DISP_RAM_DATA_MASK_2_ADDR RAM Write Data Mask (2) */
+#define DISP_BITMASK_WM17 DISP_BIT_IB05
+#define DISP_BITMASK_WM16 DISP_BIT_IB04
+#define DISP_BITMASK_WM15 DISP_BIT_IB03
+#define DISP_BITMASK_WM14 DISP_BIT_IB02
+#define DISP_BITMASK_WM13 DISP_BIT_IB01
+#define DISP_BITMASK_WM12 DISP_BIT_IB00
+/*Gamma Control */
+/* DISP_GAMMA_CONTROL_1_ADDR Gamma Control (1) */
+#define DISP_BITMASK_PKP12 DISP_BIT_IB10
+#define DISP_BITMASK_PKP11 DISP_BIT_IB08
+#define DISP_BITMASK_PKP10 DISP_BIT_IB09
+#define DISP_BITMASK_PKP02 DISP_BIT_IB02
+#define DISP_BITMASK_PKP01 DISP_BIT_IB01
+#define DISP_BITMASK_PKP00 DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_2_ADDR Gamma Control (2) */
+#define DISP_BITMASK_PKP32 DISP_BIT_IB10
+#define DISP_BITMASK_PKP31 DISP_BIT_IB09
+#define DISP_BITMASK_PKP30 DISP_BIT_IB08
+#define DISP_BITMASK_PKP22 DISP_BIT_IB02
+#define DISP_BITMASK_PKP21 DISP_BIT_IB01
+#define DISP_BITMASK_PKP20 DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_3_ADDR Gamma Control (3) */
+#define DISP_BITMASK_PKP52 DISP_BIT_IB10
+#define DISP_BITMASK_PKP51 DISP_BIT_IB09
+#define DISP_BITMASK_PKP50 DISP_BIT_IB08
+#define DISP_BITMASK_PKP42 DISP_BIT_IB02
+#define DISP_BITMASK_PKP41 DISP_BIT_IB01
+#define DISP_BITMASK_PKP40 DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_4_ADDR Gamma Control (4) */
+#define DISP_BITMASK_PRP12 DISP_BIT_IB10
+#define DISP_BITMASK_PRP11 DISP_BIT_IB08
+#define DISP_BITMASK_PRP10 DISP_BIT_IB09
+#define DISP_BITMASK_PRP02 DISP_BIT_IB02
+#define DISP_BITMASK_PRP01 DISP_BIT_IB01
+#define DISP_BITMASK_PRP00 DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_5_ADDR Gamma Control (5) */
+#define DISP_BITMASK_VRP14 DISP_BIT_IB12
+#define DISP_BITMASK_VRP13 DISP_BIT_IB11
+#define DISP_BITMASK_VRP12 DISP_BIT_IB10
+#define DISP_BITMASK_VRP11 DISP_BIT_IB08
+#define DISP_BITMASK_VRP10 DISP_BIT_IB09
+#define DISP_BITMASK_VRP03 DISP_BIT_IB03
+#define DISP_BITMASK_VRP02 DISP_BIT_IB02
+#define DISP_BITMASK_VRP01 DISP_BIT_IB01
+#define DISP_BITMASK_VRP00 DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_6_ADDR Gamma Control (6) */
+#define DISP_BITMASK_PKN12 DISP_BIT_IB10
+#define DISP_BITMASK_PKN11 DISP_BIT_IB08
+#define DISP_BITMASK_PKN10 DISP_BIT_IB09
+#define DISP_BITMASK_PKN02 DISP_BIT_IB02
+#define DISP_BITMASK_PKN01 DISP_BIT_IB01
+#define DISP_BITMASK_PKN00 DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_7_ADDR Gamma Control (7) */
+#define DISP_BITMASK_PKN32 DISP_BIT_IB10
+#define DISP_BITMASK_PKN31 DISP_BIT_IB08
+#define DISP_BITMASK_PKN30 DISP_BIT_IB09
+#define DISP_BITMASK_PKN22 DISP_BIT_IB02
+#define DISP_BITMASK_PKN21 DISP_BIT_IB01
+#define DISP_BITMASK_PKN20 DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_8_ADDR Gamma Control (8) */
+#define DISP_BITMASK_PKN52 DISP_BIT_IB10
+#define DISP_BITMASK_PKN51 DISP_BIT_IB08
+#define DISP_BITMASK_PKN50 DISP_BIT_IB09
+#define DISP_BITMASK_PKN42 DISP_BIT_IB02
+#define DISP_BITMASK_PKN41 DISP_BIT_IB01
+#define DISP_BITMASK_PKN40 DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_9_ADDR Gamma Control (9) */
+#define DISP_BITMASK_PRN12 DISP_BIT_IB10
+#define DISP_BITMASK_PRN11 DISP_BIT_IB08
+#define DISP_BITMASK_PRN10 DISP_BIT_IB09
+#define DISP_BITMASK_PRN02 DISP_BIT_IB02
+#define DISP_BITMASK_PRN01 DISP_BIT_IB01
+#define DISP_BITMASK_PRN00 DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_10_ADDR Gamma Control (10) */
+#define DISP_BITMASK_VRN14 DISP_BIT_IB12
+#define DISP_BITMASK_VRN13 DISP_BIT_IB11
+#define DISP_BITMASK_VRN12 DISP_BIT_IB10
+#define DISP_BITMASK_VRN11 DISP_BIT_IB08
+#define DISP_BITMASK_VRN10 DISP_BIT_IB09
+#define DISP_BITMASK_VRN03 DISP_BIT_IB03
+#define DISP_BITMASK_VRN02 DISP_BIT_IB02
+#define DISP_BITMASK_VRN01 DISP_BIT_IB01
+#define DISP_BITMASK_VRN00 DISP_BIT_IB00
+/* Coordinate Control */
+/* DISP_VERT_SCROLL_CTL_1_ADDR Vertical Scroll Control (1) */
+#define DISP_BITMASK_VL18 DISP_BIT_IB08
+#define DISP_BITMASK_VL17 DISP_BIT_IB07
+#define DISP_BITMASK_VL16 DISP_BIT_IB06
+#define DISP_BITMASK_VL15 DISP_BIT_IB05
+#define DISP_BITMASK_VL14 DISP_BIT_IB04
+#define DISP_BITMASK_VL13 DISP_BIT_IB03
+#define DISP_BITMASK_VL12 DISP_BIT_IB02
+#define DISP_BITMASK_VL11 DISP_BIT_IB01
+#define DISP_BITMASK_VL10 DISP_BIT_IB00
+/* DISP_VERT_SCROLL_CTL_2_ADDR Vertical Scroll Control (2) */
+#define DISP_BITMASK_VL28 DISP_BIT_IB08
+#define DISP_BITMASK_VL27 DISP_BIT_IB07
+#define DISP_BITMASK_VL26 DISP_BIT_IB06
+#define DISP_BITMASK_VL25 DISP_BIT_IB05
+#define DISP_BITMASK_VL24 DISP_BIT_IB04
+#define DISP_BITMASK_VL23 DISP_BIT_IB03
+#define DISP_BITMASK_VL22 DISP_BIT_IB02
+#define DISP_BITMASK_VL21 DISP_BIT_IB01
+#define DISP_BITMASK_VL20 DISP_BIT_IB00
+/* DISP_SCREEN_1_DRV_POS_1_ADDR First Screen Driving Position (1) */
+#define DISP_BITMASK_SS18 DISP_BIT_IB08
+#define DISP_BITMASK_SS17 DISP_BIT_IB07
+#define DISP_BITMASK_SS16 DISP_BIT_IB06
+#define DISP_BITMASK_SS15 DISP_BIT_IB05
+#define DISP_BITMASK_SS14 DISP_BIT_IB04
+#define DISP_BITMASK_SS13 DISP_BIT_IB03
+#define DISP_BITMASK_SS12 DISP_BIT_IB02
+#define DISP_BITMASK_SS11 DISP_BIT_IB01
+#define DISP_BITMASK_SS10 DISP_BIT_IB00
+/* DISP_SCREEN_1_DRV_POS_2_ADDR First Screen Driving Position (2) */
+#define DISP_BITMASK_SE18 DISP_BIT_IB08
+#define DISP_BITMASK_SE17 DISP_BIT_IB07
+#define DISP_BITMASK_SE16 DISP_BIT_IB06
+#define DISP_BITMASK_SE15 DISP_BIT_IB05
+#define DISP_BITMASK_SE14 DISP_BIT_IB04
+#define DISP_BITMASK_SE13 DISP_BIT_IB03
+#define DISP_BITMASK_SE12 DISP_BIT_IB02
+#define DISP_BITMASK_SE11 DISP_BIT_IB01
+#define DISP_BITMASK_SE10 DISP_BIT_IB00
+/* DISP_SCREEN_2_DRV_POS_1_ADDR Second Screen Driving Position (1) */
+#define DISP_BITMASK_SS28 DISP_BIT_IB08
+#define DISP_BITMASK_SS27 DISP_BIT_IB07
+#define DISP_BITMASK_SS26 DISP_BIT_IB06
+#define DISP_BITMASK_SS25 DISP_BIT_IB05
+#define DISP_BITMASK_SS24 DISP_BIT_IB04
+#define DISP_BITMASK_SS23 DISP_BIT_IB03
+#define DISP_BITMASK_SS22 DISP_BIT_IB02
+#define DISP_BITMASK_SS21 DISP_BIT_IB01
+#define DISP_BITMASK_SS20 DISP_BIT_IB00
+/* DISP_SCREEN_3_DRV_POS_2_ADDR Second Screen Driving Position (2) */
+#define DISP_BITMASK_SE28 DISP_BIT_IB08
+#define DISP_BITMASK_SE27 DISP_BIT_IB07
+#define DISP_BITMASK_SE26 DISP_BIT_IB06
+#define DISP_BITMASK_SE25 DISP_BIT_IB05
+#define DISP_BITMASK_SE24 DISP_BIT_IB04
+#define DISP_BITMASK_SE23 DISP_BIT_IB03
+#define DISP_BITMASK_SE22 DISP_BIT_IB02
+#define DISP_BITMASK_SE21 DISP_BIT_IB01
+#define DISP_BITMASK_SE20 DISP_BIT_IB00
+/* DISP_HORZ_RAM_ADDR_POS_1_ADDR Horizontal RAM Address Position (1) */
+#define DISP_BITMASK_HSA7 DISP_BIT_IB07
+#define DISP_BITMASK_HSA6 DISP_BIT_IB06
+#define DISP_BITMASK_HSA5 DISP_BIT_IB05
+#define DISP_BITMASK_HSA4 DISP_BIT_IB04
+#define DISP_BITMASK_HSA3 DISP_BIT_IB03
+#define DISP_BITMASK_HSA2 DISP_BIT_IB02
+#define DISP_BITMASK_HSA1 DISP_BIT_IB01
+#define DISP_BITMASK_HSA0 DISP_BIT_IB00
+/* DISP_HORZ_RAM_ADDR_POS_2_ADDR Horizontal RAM Address Position (2) */
+#define DISP_BITMASK_HEA7 DISP_BIT_IB07
+#define DISP_BITMASK_HEA6 DISP_BIT_IB06
+#define DISP_BITMASK_HEA5 DISP_BIT_IB05
+#define DISP_BITMASK_HEA4 DISP_BIT_IB04
+#define DISP_BITMASK_HEA3 DISP_BIT_IB03
+#define DISP_BITMASK_HEA2 DISP_BIT_IB02
+#define DISP_BITMASK_HEA1 DISP_BIT_IB01
+#define DISP_BITMASK_HEA0 DISP_BIT_IB00
+/* DISP_VERT_RAM_ADDR_POS_1_ADDR Vertical RAM Address Position (1) */
+#define DISP_BITMASK_VSA8 DISP_BIT_IB08
+#define DISP_BITMASK_VSA7 DISP_BIT_IB07
+#define DISP_BITMASK_VSA6 DISP_BIT_IB06
+#define DISP_BITMASK_VSA5 DISP_BIT_IB05
+#define DISP_BITMASK_VSA4 DISP_BIT_IB04
+#define DISP_BITMASK_VSA3 DISP_BIT_IB03
+#define DISP_BITMASK_VSA2 DISP_BIT_IB02
+#define DISP_BITMASK_VSA1 DISP_BIT_IB01
+#define DISP_BITMASK_VSA0 DISP_BIT_IB00
+/* DISP_VERT_RAM_ADDR_POS_2_ADDR Vertical RAM Address Position (2) */
+#define DISP_BITMASK_VEA8 DISP_BIT_IB08
+#define DISP_BITMASK_VEA7 DISP_BIT_IB07
+#define DISP_BITMASK_VEA6 DISP_BIT_IB06
+#define DISP_BITMASK_VEA5 DISP_BIT_IB05
+#define DISP_BITMASK_VEA4 DISP_BIT_IB04
+#define DISP_BITMASK_VEA3 DISP_BIT_IB03
+#define DISP_BITMASK_VEA2 DISP_BIT_IB02
+#define DISP_BITMASK_VEA1 DISP_BIT_IB01
+#define DISP_BITMASK_VEA0 DISP_BIT_IB00
+static word disp_area_start_row;
+static word disp_area_end_row;
+static boolean disp_initialized = FALSE;
+/* For some reason the contrast set at init time is not good. Need to do
+* it again
+*/
+static boolean display_on = FALSE;
+
+static uint32 tmd20qvga_lcd_rev;
+uint16 tmd20qvga_panel_offset;
+
+#ifdef DISP_DEVICE_8BPP
+static word convert_8_to_16_tbl[256] = {
+ 0x0000, 0x2000, 0x4000, 0x6000, 0x8000, 0xA000, 0xC000, 0xE000,
+ 0x0100, 0x2100, 0x4100, 0x6100, 0x8100, 0xA100, 0xC100, 0xE100,
+ 0x0200, 0x2200, 0x4200, 0x6200, 0x8200, 0xA200, 0xC200, 0xE200,
+ 0x0300, 0x2300, 0x4300, 0x6300, 0x8300, 0xA300, 0xC300, 0xE300,
+ 0x0400, 0x2400, 0x4400, 0x6400, 0x8400, 0xA400, 0xC400, 0xE400,
+ 0x0500, 0x2500, 0x4500, 0x6500, 0x8500, 0xA500, 0xC500, 0xE500,
+ 0x0600, 0x2600, 0x4600, 0x6600, 0x8600, 0xA600, 0xC600, 0xE600,
+ 0x0700, 0x2700, 0x4700, 0x6700, 0x8700, 0xA700, 0xC700, 0xE700,
+ 0x0008, 0x2008, 0x4008, 0x6008, 0x8008, 0xA008, 0xC008, 0xE008,
+ 0x0108, 0x2108, 0x4108, 0x6108, 0x8108, 0xA108, 0xC108, 0xE108,
+ 0x0208, 0x2208, 0x4208, 0x6208, 0x8208, 0xA208, 0xC208, 0xE208,
+ 0x0308, 0x2308, 0x4308, 0x6308, 0x8308, 0xA308, 0xC308, 0xE308,
+ 0x0408, 0x2408, 0x4408, 0x6408, 0x8408, 0xA408, 0xC408, 0xE408,
+ 0x0508, 0x2508, 0x4508, 0x6508, 0x8508, 0xA508, 0xC508, 0xE508,
+ 0x0608, 0x2608, 0x4608, 0x6608, 0x8608, 0xA608, 0xC608, 0xE608,
+ 0x0708, 0x2708, 0x4708, 0x6708, 0x8708, 0xA708, 0xC708, 0xE708,
+ 0x0010, 0x2010, 0x4010, 0x6010, 0x8010, 0xA010, 0xC010, 0xE010,
+ 0x0110, 0x2110, 0x4110, 0x6110, 0x8110, 0xA110, 0xC110, 0xE110,
+ 0x0210, 0x2210, 0x4210, 0x6210, 0x8210, 0xA210, 0xC210, 0xE210,
+ 0x0310, 0x2310, 0x4310, 0x6310, 0x8310, 0xA310, 0xC310, 0xE310,
+ 0x0410, 0x2410, 0x4410, 0x6410, 0x8410, 0xA410, 0xC410, 0xE410,
+ 0x0510, 0x2510, 0x4510, 0x6510, 0x8510, 0xA510, 0xC510, 0xE510,
+ 0x0610, 0x2610, 0x4610, 0x6610, 0x8610, 0xA610, 0xC610, 0xE610,
+ 0x0710, 0x2710, 0x4710, 0x6710, 0x8710, 0xA710, 0xC710, 0xE710,
+ 0x0018, 0x2018, 0x4018, 0x6018, 0x8018, 0xA018, 0xC018, 0xE018,
+ 0x0118, 0x2118, 0x4118, 0x6118, 0x8118, 0xA118, 0xC118, 0xE118,
+ 0x0218, 0x2218, 0x4218, 0x6218, 0x8218, 0xA218, 0xC218, 0xE218,
+ 0x0318, 0x2318, 0x4318, 0x6318, 0x8318, 0xA318, 0xC318, 0xE318,
+ 0x0418, 0x2418, 0x4418, 0x6418, 0x8418, 0xA418, 0xC418, 0xE418,
+ 0x0518, 0x2518, 0x4518, 0x6518, 0x8518, 0xA518, 0xC518, 0xE518,
+ 0x0618, 0x2618, 0x4618, 0x6618, 0x8618, 0xA618, 0xC618, 0xE618,
+ 0x0718, 0x2718, 0x4718, 0x6718, 0x8718, 0xA718, 0xC718, 0xE718
+};
+#endif /* DISP_DEVICE_8BPP */
+
+static void tmd20qvga_disp_set_rect(int x, int y, int xres, int yres);
+static void tmd20qvga_disp_init(struct platform_device *pdev);
+static void tmd20qvga_disp_set_contrast(void);
+static void tmd20qvga_disp_set_display_area(word start_row, word end_row);
+static int tmd20qvga_disp_off(struct platform_device *pdev);
+static int tmd20qvga_disp_on(struct platform_device *pdev);
+static void tmd20qvga_set_revId(int);
+
+/* future use */
+void tmd20qvga_disp_clear_screen_area(word start_row, word end_row,
+ word start_column, word end_column);
+
+static void tmd20qvga_set_revId(int id)
+{
+
+ tmd20qvga_lcd_rev = id;
+
+ if (tmd20qvga_lcd_rev == 1)
+ tmd20qvga_panel_offset = 0x10;
+ else
+ tmd20qvga_panel_offset = 0;
+}
+
+static void tmd20qvga_disp_init(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+
+ if (disp_initialized)
+ return;
+
+ mfd = platform_get_drvdata(pdev);
+
+ DISP_CMD_PORT = mfd->cmd_port;
+ DISP_DATA_PORT = mfd->data_port;
+
+#ifdef TMD20QVGA_LCD_18BPP
+ tmd20qvga_set_revId(2);
+#else
+ tmd20qvga_set_revId(1);
+#endif
+
+ disp_initialized = TRUE;
+ tmd20qvga_disp_set_contrast();
+ tmd20qvga_disp_set_display_area(0, QVGA_HEIGHT - 1);
+}
+
+static void tmd20qvga_disp_set_rect(int x, int y, int xres, int yres)
+{
+ if (!disp_initialized)
+ return;
+
+ DISP_SET_RECT(y, y + yres - 1, x, x + xres - 1);
+
+ DISP_CMD_OUT(DISP_CMD_RAMWR);
+}
+
+static void tmd20qvga_disp_set_display_area(word start_row, word end_row)
+{
+ word start_driving = start_row;
+ word end_driving = end_row;
+
+ if (!disp_initialized)
+ return;
+
+ /* Range checking
+ */
+ if (end_driving >= QVGA_HEIGHT)
+ end_driving = QVGA_HEIGHT - 1;
+ if (start_driving > end_driving) {
+ /* Probably Backwards Switch */
+ start_driving = end_driving;
+ end_driving = start_row; /* Has not changed */
+ if (end_driving >= QVGA_HEIGHT)
+ end_driving = QVGA_HEIGHT - 1;
+ }
+
+ if ((start_driving == disp_area_start_row)
+ && (end_driving == disp_area_end_row))
+ return;
+
+ disp_area_start_row = start_driving;
+ disp_area_end_row = end_driving;
+
+ DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_1_ADDR,
+ DISP_VAL_IF(start_driving & 0x100,
+ DISP_BITMASK_SS18) |
+ DISP_VAL_IF(start_driving & 0x080,
+ DISP_BITMASK_SS17) |
+ DISP_VAL_IF(start_driving & 0x040,
+ DISP_BITMASK_SS16) |
+ DISP_VAL_IF(start_driving & 0x020,
+ DISP_BITMASK_SS15) |
+ DISP_VAL_IF(start_driving & 0x010,
+ DISP_BITMASK_SS14) |
+ DISP_VAL_IF(start_driving & 0x008,
+ DISP_BITMASK_SS13) |
+ DISP_VAL_IF(start_driving & 0x004,
+ DISP_BITMASK_SS12) |
+ DISP_VAL_IF(start_driving & 0x002,
+ DISP_BITMASK_SS11) |
+ DISP_VAL_IF(start_driving & 0x001, DISP_BITMASK_SS10));
+
+ DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_2_ADDR,
+ DISP_VAL_IF(end_driving & 0x100, DISP_BITMASK_SE18) |
+ DISP_VAL_IF(end_driving & 0x080, DISP_BITMASK_SE17) |
+ DISP_VAL_IF(end_driving & 0x040, DISP_BITMASK_SE16) |
+ DISP_VAL_IF(end_driving & 0x020, DISP_BITMASK_SE15) |
+ DISP_VAL_IF(end_driving & 0x010, DISP_BITMASK_SE14) |
+ DISP_VAL_IF(end_driving & 0x008, DISP_BITMASK_SE13) |
+ DISP_VAL_IF(end_driving & 0x004, DISP_BITMASK_SE12) |
+ DISP_VAL_IF(end_driving & 0x002, DISP_BITMASK_SE11) |
+ DISP_VAL_IF(end_driving & 0x001, DISP_BITMASK_SE10));
+}
+
+static int tmd20qvga_disp_off(struct platform_device *pdev)
+{
+ if (!disp_initialized)
+ tmd20qvga_disp_init(pdev);
+
+ if (display_on) {
+ if (tmd20qvga_lcd_rev == 2) {
+ DISP_WRITE_OUT(DISP_POFF_LN_SETTING_ADDR, 0x000A);
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xFFEE);
+ WAIT_MSEC(40);
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xF812);
+ WAIT_MSEC(40);
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xE811);
+ WAIT_MSEC(40);
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xC011);
+ WAIT_MSEC(40);
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x4011);
+ WAIT_MSEC(20);
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0010);
+
+ } else {
+ DISP_WRITE_OUT(DISP_POFF_LN_SETTING_ADDR, 0x000F);
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BFE);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+ WAIT_MSEC(40);
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BED);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+ WAIT_MSEC(40);
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x00CD);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+ WAIT_MSEC(20);
+ DISP_WRITE_OUT(DISP_START_OSCILLATION_ADDR, 0x0);
+ }
+
+ DISP_WRITE_OUT(DISP_MODE_SETTING_ADDR, 0x0004);
+ DISP_WRITE_OUT(DISP_MODE_SETTING_ADDR, 0x0000);
+
+ display_on = FALSE;
+ }
+
+ return 0;
+}
+
+static int tmd20qvga_disp_on(struct platform_device *pdev)
+{
+ if (!disp_initialized)
+ tmd20qvga_disp_init(pdev);
+
+ if (!display_on) {
+ /* Deep Stand-by -> Stand-by */
+ DISP_CMD_OUT(DISP_START_OSCILLATION_ADDR);
+ WAIT_MSEC(1);
+ DISP_CMD_OUT(DISP_START_OSCILLATION_ADDR);
+ WAIT_MSEC(1);
+ DISP_CMD_OUT(DISP_START_OSCILLATION_ADDR);
+ WAIT_MSEC(1);
+
+ /* OFF -> Deep Stan-By -> Stand-by */
+ /* let's change the state from "Stand-by" to "Sleep" */
+ DISP_WRITE_OUT(DISP_MODE_SETTING_ADDR, 0x0005);
+ WAIT_MSEC(1);
+
+ /* Sleep -> Displaying */
+ DISP_WRITE_OUT(DISP_START_OSCILLATION_ADDR, 0x0001);
+ DISP_WRITE_OUT(DISP_DRIVER_OUTPUT_CTL_ADDR, 0x0127);
+ DISP_WRITE_OUT(DISP_LCD_DRIVING_SIG_ADDR, 0x200);
+ /* fast write mode */
+ DISP_WRITE_OUT(DISP_ENTRY_MODE_ADDR, 0x0130);
+ if (tmd20qvga_lcd_rev == 2)
+ DISP_WRITE_OUT(DISP_TMD_700_ADDR, 0x0003);
+ /* back porch = 14 + front porch = 2 --> 16 lines */
+ if (tmd20qvga_lcd_rev == 2) {
+#ifdef TMD20QVGA_LCD_18BPP
+ /* 256k color */
+ DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x0000);
+#else
+ /* 65k color */
+ DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x4000);
+#endif
+ DISP_WRITE_OUT(DISP_DISPLAY_CTL_2_ADDR, 0x0302);
+ } else {
+#ifdef TMD20QVGA_LCD_18BPP
+ /* 256k color */
+ DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x0004);
+#else
+ /* 65k color */
+ DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x4004);
+#endif
+ DISP_WRITE_OUT(DISP_DISPLAY_CTL_2_ADDR, 0x020E);
+ }
+ /* 16 bit one transfer */
+ if (tmd20qvga_lcd_rev == 2) {
+ DISP_WRITE_OUT(DISP_EXT_DISPLAY_CTL_1_ADDR, 0x0000);
+ DISP_WRITE_OUT(DISP_FRAME_CYCLE_CTL_ADDR, 0x0010);
+ DISP_WRITE_OUT(DISP_LTPS_CTL_1_ADDR, 0x0302);
+ DISP_WRITE_OUT(DISP_LTPS_CTL_2_ADDR, 0x0102);
+ DISP_WRITE_OUT(DISP_LTPS_CTL_3_ADDR, 0x0000);
+ DISP_WRITE_OUT(DISP_TMD_015_ADDR, 0x2000);
+
+ DISP_WRITE_OUT(DISP_AMP_SETTING_ADDR, 0x0000);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0403);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, 0x0304);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, 0x0403);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0303);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0101);
+ DISP_WRITE_OUT(DISP_TMD_305_ADDR, 0);
+
+ DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_1_ADDR, 0x0000);
+ DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_2_ADDR, 0x013F);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_3_ADDR, 0x077D);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_4_ADDR, 0x0005);
+ DISP_WRITE_OUT(DISP_POWER_CTL_5_ADDR, 0x0000);
+ DISP_WRITE_OUT(DISP_POWER_CTL_6_ADDR, 0x0015);
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xC010);
+ WAIT_MSEC(1);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_2_ADDR, 0x0001);
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xFFFE);
+ WAIT_MSEC(60);
+ } else {
+ DISP_WRITE_OUT(DISP_EXT_DISPLAY_CTL_1_ADDR, 0x0001);
+ DISP_WRITE_OUT(DISP_FRAME_CYCLE_CTL_ADDR, 0x0010);
+ DISP_WRITE_OUT(DISP_LTPS_CTL_1_ADDR, 0x0301);
+ DISP_WRITE_OUT(DISP_LTPS_CTL_2_ADDR, 0x0001);
+ DISP_WRITE_OUT(DISP_LTPS_CTL_3_ADDR, 0x0000);
+ DISP_WRITE_OUT(DISP_AMP_SETTING_ADDR, 0x0000);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0507);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, 0x0405);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, 0x0607);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0502);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0301);
+ DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_1_ADDR, 0x0000);
+ DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_2_ADDR, 0x013F);
+ DISP_WRITE_OUT(DISP_POWER_CTL_3_ADDR, 0x0795);
+
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0102);
+ WAIT_MSEC(1);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_4_ADDR, 0x0450);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0103);
+ WAIT_MSEC(1);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_5_ADDR, 0x0008);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0104);
+ WAIT_MSEC(1);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_6_ADDR, 0x0C00);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0105);
+ WAIT_MSEC(1);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_7_ADDR, 0x0000);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0106);
+ WAIT_MSEC(1);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0801);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+ WAIT_MSEC(1);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_2_ADDR, 0x001F);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0101);
+ WAIT_MSEC(60);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_2_ADDR, 0x009F);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0101);
+ WAIT_MSEC(10);
+
+ DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_1_ADDR, 0x0010);
+ DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_2_ADDR, 0x00FF);
+ DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_1_ADDR, 0x0000);
+ DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_2_ADDR, 0x013F);
+ /* RAM starts at address 0x10 */
+ DISP_WRITE_OUT(DISP_RAM_ADDR_SET_1_ADDR, 0x0010);
+ DISP_WRITE_OUT(DISP_RAM_ADDR_SET_2_ADDR, 0x0000);
+
+ /* lcd controller uses internal clock, not ext. vsync */
+ DISP_CMD_OUT(DISP_CMD_RAMWR);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0881);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+ WAIT_MSEC(40);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BE1);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+ WAIT_MSEC(40);
+
+ DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BFF);
+ DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+ }
+ display_on = TRUE;
+ }
+
+ return 0;
+}
+
+static void tmd20qvga_disp_set_contrast(void)
+{
+#if (defined(TMD20QVGA_LCD_18BPP))
+
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0403);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, 0x0302);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, 0x0403);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0303);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0F07);
+
+#else
+ int newcontrast = 0x46;
+
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0403);
+
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR,
+ DISP_VAL_IF(newcontrast & 0x0001, DISP_BITMASK_PKP20) |
+ DISP_VAL_IF(newcontrast & 0x0002, DISP_BITMASK_PKP21) |
+ DISP_VAL_IF(newcontrast & 0x0004, DISP_BITMASK_PKP22) |
+ DISP_VAL_IF(newcontrast & 0x0010, DISP_BITMASK_PKP30) |
+ DISP_VAL_IF(newcontrast & 0x0020, DISP_BITMASK_PKP31) |
+ DISP_VAL_IF(newcontrast & 0x0040, DISP_BITMASK_PKP32));
+
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR,
+ DISP_VAL_IF(newcontrast & 0x0010, DISP_BITMASK_PKP40) |
+ DISP_VAL_IF(newcontrast & 0x0020, DISP_BITMASK_PKP41) |
+ DISP_VAL_IF(newcontrast & 0x0040, DISP_BITMASK_PKP42) |
+ DISP_VAL_IF(newcontrast & 0x0001, DISP_BITMASK_PKP50) |
+ DISP_VAL_IF(newcontrast & 0x0002, DISP_BITMASK_PKP51) |
+ DISP_VAL_IF(newcontrast & 0x0004, DISP_BITMASK_PKP52));
+
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0303);
+ DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0F07);
+
+#endif /* defined(TMD20QVGA_LCD_18BPP) */
+
+} /* End disp_set_contrast */
+
+void tmd20qvga_disp_clear_screen_area
+ (word start_row, word end_row, word start_column, word end_column) {
+ int32 i;
+
+ /* Clear the display screen */
+ DISP_SET_RECT(start_row, end_row, start_column, end_column);
+ DISP_CMD_OUT(DISP_CMD_RAMWR);
+ i = (end_row - start_row + 1) * (end_column - start_column + 1);
+ for (; i > 0; i--)
+ DISP_DATA_OUT_16TO18BPP(0x0);
+}
+
+static int __init tmd20qvga_probe(struct platform_device *pdev)
+{
+ msm_fb_add_device(pdev);
+
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = tmd20qvga_probe,
+ .driver = {
+ .name = "ebi2_tmd_qvga",
+ },
+};
+
+static struct msm_fb_panel_data tmd20qvga_panel_data = {
+ .on = tmd20qvga_disp_on,
+ .off = tmd20qvga_disp_off,
+ .set_rect = tmd20qvga_disp_set_rect,
+};
+
+static struct platform_device this_device = {
+ .name = "ebi2_tmd_qvga",
+ .id = 0,
+ .dev = {
+ .platform_data = &tmd20qvga_panel_data,
+ }
+};
+
+static int __init tmd20qvga_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+
+ ret = platform_driver_register(&this_driver);
+ if (!ret) {
+ pinfo = &tmd20qvga_panel_data.panel_info;
+ pinfo->xres = 240;
+ pinfo->yres = 320;
+ pinfo->type = EBI2_PANEL;
+ pinfo->pdest = DISPLAY_1;
+ pinfo->wait_cycle = 0x808000;
+#ifdef TMD20QVGA_LCD_18BPP
+ pinfo->bpp = 18;
+#else
+ pinfo->bpp = 16;
+#endif
+ pinfo->fb_num = 2;
+ pinfo->lcd.vsync_enable = TRUE;
+ pinfo->lcd.refx100 = 6000;
+ pinfo->lcd.v_back_porch = 16;
+ pinfo->lcd.v_front_porch = 4;
+ pinfo->lcd.v_pulse_width = 0;
+ pinfo->lcd.hw_vsync_mode = FALSE;
+ pinfo->lcd.vsync_notifier_period = 0;
+
+ ret = platform_device_register(&this_device);
+ if (ret)
+ platform_driver_unregister(&this_driver);
+ }
+
+ return ret;
+}
+
+module_init(tmd20qvga_init);
diff --git a/drivers/staging/msm/hdmi_sii9022.c b/drivers/staging/msm/hdmi_sii9022.c
new file mode 100644
index 0000000..6b82b56
--- /dev/null
+++ b/drivers/staging/msm/hdmi_sii9022.c
@@ -0,0 +1,248 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include "msm_fb.h"
+
+#define DEVICE_NAME "sii9022"
+#define SII9022_DEVICE_ID 0xB0
+
+struct sii9022_i2c_addr_data{
+ u8 addr;
+ u8 data;
+};
+
+/* video mode data */
+static u8 video_mode_data[] = {
+ 0x00,
+ 0xF9, 0x1C, 0x70, 0x17, 0x72, 0x06, 0xEE, 0x02,
+};
+
+static u8 avi_io_format[] = {
+ 0x09,
+ 0x00, 0x00,
+};
+
+/* power state */
+static struct sii9022_i2c_addr_data regset0[] = {
+ { 0x60, 0x04 },
+ { 0x63, 0x00 },
+ { 0x1E, 0x00 },
+};
+
+static u8 video_infoframe[] = {
+ 0x0C,
+ 0xF0, 0x00, 0x68, 0x00, 0x04, 0x00, 0x19, 0x00,
+ 0xE9, 0x02, 0x04, 0x01, 0x04, 0x06,
+};
+
+/* configure audio */
+static struct sii9022_i2c_addr_data regset1[] = {
+ { 0x26, 0x90 },
+ { 0x20, 0x90 },
+ { 0x1F, 0x80 },
+ { 0x26, 0x80 },
+ { 0x24, 0x02 },
+ { 0x25, 0x0B },
+ { 0xBC, 0x02 },
+ { 0xBD, 0x24 },
+ { 0xBE, 0x02 },
+};
+
+/* enable audio */
+static u8 misc_infoframe[] = {
+ 0xBF,
+ 0xC2, 0x84, 0x01, 0x0A, 0x6F, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+/* set HDMI, active */
+static struct sii9022_i2c_addr_data regset2[] = {
+ { 0x1A, 0x01 },
+ { 0x3D, 0x00 },
+};
+
+static int send_i2c_data(struct i2c_client *client,
+ struct sii9022_i2c_addr_data *regset,
+ int size)
+{
+ int i;
+ int rc = 0;
+
+ for (i = 0; i < size; i++) {
+ rc = i2c_smbus_write_byte_data(
+ client,
+ regset[i].addr, regset[i].data);
+ if (rc)
+ break;
+ }
+ return rc;
+}
+
+static int hdmi_sii_enable(struct i2c_client *client)
+{
+ int rc;
+ int retries = 10;
+ int count;
+
+ rc = i2c_smbus_write_byte_data(client, 0xC7, 0x00);
+ if (rc)
+ goto enable_exit;
+
+ do {
+ msleep(1);
+ rc = i2c_smbus_read_byte_data(client, 0x1B);
+ } while ((rc != SII9022_DEVICE_ID) && retries--);
+
+ if (rc != SII9022_DEVICE_ID)
+ return -ENODEV;
+
+ rc = i2c_smbus_write_byte_data(client, 0x1A, 0x11);
+ if (rc)
+ goto enable_exit;
+
+ count = ARRAY_SIZE(video_mode_data);
+ rc = i2c_master_send(client, video_mode_data, count);
+ if (rc != count) {
+ rc = -EIO;
+ goto enable_exit;
+ }
+
+ rc = i2c_smbus_write_byte_data(client, 0x08, 0x20);
+ if (rc)
+ goto enable_exit;
+ count = ARRAY_SIZE(avi_io_format);
+ rc = i2c_master_send(client, avi_io_format, count);
+ if (rc != count) {
+ rc = -EIO;
+ goto enable_exit;
+ }
+
+ rc = send_i2c_data(client, regset0, ARRAY_SIZE(regset0));
+ if (rc)
+ goto enable_exit;
+
+ count = ARRAY_SIZE(video_infoframe);
+ rc = i2c_master_send(client, video_infoframe, count);
+ if (rc != count) {
+ rc = -EIO;
+ goto enable_exit;
+ }
+
+ rc = send_i2c_data(client, regset1, ARRAY_SIZE(regset1));
+ if (rc)
+ goto enable_exit;
+
+ count = ARRAY_SIZE(misc_infoframe);
+ rc = i2c_master_send(client, misc_infoframe, count);
+ if (rc != count) {
+ rc = -EIO;
+ goto enable_exit;
+ }
+
+ rc = send_i2c_data(client, regset2, ARRAY_SIZE(regset2));
+ if (rc)
+ goto enable_exit;
+
+ return 0;
+enable_exit:
+ printk(KERN_ERR "%s: exited rc=%d\n", __func__, rc);
+ return rc;
+}
+
+static const struct i2c_device_id hmdi_sii_id[] = {
+ { DEVICE_NAME, 0 },
+ { }
+};
+
+static int hdmi_sii_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int rc;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C))
+ return -ENODEV;
+ rc = hdmi_sii_enable(client);
+ return rc;
+}
+
+
+static struct i2c_driver hdmi_sii_i2c_driver = {
+ .driver = {
+ .name = DEVICE_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = hdmi_sii_probe,
+ .remove = __exit_p(hdmi_sii_remove),
+ .id_table = hmdi_sii_id,
+};
+
+static int __init hdmi_sii_init(void)
+{
+ int ret;
+ struct msm_panel_info pinfo;
+
+ if (msm_fb_detect_client("hdmi_sii9022"))
+ return 0;
+
+ pinfo.xres = 1280;
+ pinfo.yres = 720;
+ pinfo.type = HDMI_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 24;
+ pinfo.fb_num = 2;
+ pinfo.clk_rate = 74250000;
+
+ pinfo.lcdc.h_back_porch = 124;
+ pinfo.lcdc.h_front_porch = 110;
+ pinfo.lcdc.h_pulse_width = 136;
+ pinfo.lcdc.v_back_porch = 19;
+ pinfo.lcdc.v_front_porch = 5;
+ pinfo.lcdc.v_pulse_width = 6;
+ pinfo.lcdc.border_clr = 0;
+ pinfo.lcdc.underflow_clr = 0xff;
+ pinfo.lcdc.hsync_skew = 0;
+
+ ret = lcdc_device_register(&pinfo);
+ if (ret) {
+ printk(KERN_ERR "%s: failed to register device\n", __func__);
+ goto init_exit;
+ }
+
+ ret = i2c_add_driver(&hdmi_sii_i2c_driver);
+ if (ret)
+ printk(KERN_ERR "%s: failed to add i2c driver\n", __func__);
+
+init_exit:
+ return ret;
+}
+
+static void __exit hdmi_sii_exit(void)
+{
+ i2c_del_driver(&hdmi_sii_i2c_driver);
+}
+
+module_init(hdmi_sii_init);
+module_exit(hdmi_sii_exit);
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION("0.1");
+MODULE_AUTHOR("Qualcomm Innovation Center, Inc.");
+MODULE_DESCRIPTION("SiI9022 HDMI driver");
+MODULE_ALIAS("platform:hdmi-sii9022");
diff --git a/drivers/staging/msm/lcdc.c b/drivers/staging/msm/lcdc.c
new file mode 100644
index 0000000..735280a
--- /dev/null
+++ b/drivers/staging/msm/lcdc.c
@@ -0,0 +1,239 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/pm_qos_params.h>
+
+#include "msm_fb.h"
+
+static int lcdc_probe(struct platform_device *pdev);
+static int lcdc_remove(struct platform_device *pdev);
+
+static int lcdc_off(struct platform_device *pdev);
+static int lcdc_on(struct platform_device *pdev);
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+
+static struct clk *mdp_lcdc_pclk_clk;
+static struct clk *mdp_lcdc_pad_pclk_clk;
+
+int mdp_lcdc_pclk_clk_rate;
+int mdp_lcdc_pad_pclk_clk_rate;
+
+static struct platform_driver lcdc_driver = {
+ .probe = lcdc_probe,
+ .remove = lcdc_remove,
+ .suspend = NULL,
+ .resume = NULL,
+ .shutdown = NULL,
+ .driver = {
+ .name = "lcdc",
+ },
+};
+
+static struct lcdc_platform_data *lcdc_pdata;
+
+static int lcdc_off(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ ret = panel_next_off(pdev);
+
+ clk_disable(mdp_lcdc_pclk_clk);
+ clk_disable(mdp_lcdc_pad_pclk_clk);
+
+ if (lcdc_pdata && lcdc_pdata->lcdc_power_save)
+ lcdc_pdata->lcdc_power_save(0);
+
+ if (lcdc_pdata && lcdc_pdata->lcdc_gpio_config)
+ ret = lcdc_pdata->lcdc_gpio_config(0);
+
+// pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc",
+// PM_QOS_DEFAULT_VALUE);
+
+ return ret;
+}
+
+static int lcdc_on(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct msm_fb_data_type *mfd;
+ unsigned long panel_pixclock_freq , pm_qos_freq;
+
+ mfd = platform_get_drvdata(pdev);
+ panel_pixclock_freq = mfd->fbi->var.pixclock;
+
+ if (panel_pixclock_freq > 58000000)
+ /* pm_qos_freq should be in Khz */
+ pm_qos_freq = panel_pixclock_freq / 1000 ;
+ else
+ pm_qos_freq = 58000;
+
+// pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc",
+// pm_qos_freq);
+ mfd = platform_get_drvdata(pdev);
+
+ clk_enable(mdp_lcdc_pclk_clk);
+ clk_enable(mdp_lcdc_pad_pclk_clk);
+
+ if (lcdc_pdata && lcdc_pdata->lcdc_power_save)
+ lcdc_pdata->lcdc_power_save(1);
+ if (lcdc_pdata && lcdc_pdata->lcdc_gpio_config)
+ ret = lcdc_pdata->lcdc_gpio_config(1);
+
+ clk_set_rate(mdp_lcdc_pclk_clk, mfd->fbi->var.pixclock);
+ clk_set_rate(mdp_lcdc_pad_pclk_clk, mfd->fbi->var.pixclock);
+ mdp_lcdc_pclk_clk_rate = clk_get_rate(mdp_lcdc_pclk_clk);
+ mdp_lcdc_pad_pclk_clk_rate = clk_get_rate(mdp_lcdc_pad_pclk_clk);
+
+ ret = panel_next_on(pdev);
+ return ret;
+}
+
+static int lcdc_probe(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ struct fb_info *fbi;
+ struct platform_device *mdp_dev = NULL;
+ struct msm_fb_panel_data *pdata = NULL;
+ int rc;
+
+ if (pdev->id == 0) {
+ lcdc_pdata = pdev->dev.platform_data;
+ return 0;
+ }
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+ return -ENOMEM;
+
+ mdp_dev = platform_device_alloc("mdp", pdev->id);
+ if (!mdp_dev)
+ return -ENOMEM;
+
+ /*
+ * link to the latest pdev
+ */
+ mfd->pdev = mdp_dev;
+ mfd->dest = DISPLAY_LCDC;
+
+ /*
+ * alloc panel device data
+ */
+ if (platform_device_add_data
+ (mdp_dev, pdev->dev.platform_data,
+ sizeof(struct msm_fb_panel_data))) {
+ printk(KERN_ERR "lcdc_probe: platform_device_add_data failed!\n");
+ platform_device_put(mdp_dev);
+ return -ENOMEM;
+ }
+ /*
+ * data chain
+ */
+ pdata = (struct msm_fb_panel_data *)mdp_dev->dev.platform_data;
+ pdata->on = lcdc_on;
+ pdata->off = lcdc_off;
+ pdata->next = pdev;
+
+ /*
+ * get/set panel specific fb info
+ */
+ mfd->panel_info = pdata->panel_info;
+ mfd->fb_imgType = MDP_RGB_565;
+
+ fbi = mfd->fbi;
+ fbi->var.pixclock = mfd->panel_info.clk_rate;
+ fbi->var.left_margin = mfd->panel_info.lcdc.h_back_porch;
+ fbi->var.right_margin = mfd->panel_info.lcdc.h_front_porch;
+ fbi->var.upper_margin = mfd->panel_info.lcdc.v_back_porch;
+ fbi->var.lower_margin = mfd->panel_info.lcdc.v_front_porch;
+ fbi->var.hsync_len = mfd->panel_info.lcdc.h_pulse_width;
+ fbi->var.vsync_len = mfd->panel_info.lcdc.v_pulse_width;
+
+ /*
+ * set driver data
+ */
+ platform_set_drvdata(mdp_dev, mfd);
+
+ /*
+ * register in mdp driver
+ */
+ rc = platform_device_add(mdp_dev);
+ if (rc)
+ goto lcdc_probe_err;
+
+ pdev_list[pdev_list_cnt++] = pdev;
+ return 0;
+
+lcdc_probe_err:
+ platform_device_put(mdp_dev);
+ return rc;
+}
+
+static int lcdc_remove(struct platform_device *pdev)
+{
+// pm_qos_remove_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc");
+ return 0;
+}
+
+static int lcdc_register_driver(void)
+{
+ return platform_driver_register(&lcdc_driver);
+}
+
+static int __init lcdc_driver_init(void)
+{
+ mdp_lcdc_pclk_clk = clk_get(NULL, "mdp_lcdc_pclk_clk");
+ if (IS_ERR(mdp_lcdc_pclk_clk)) {
+ printk(KERN_ERR "error: can't get mdp_lcdc_pclk_clk!\n");
+ return IS_ERR(mdp_lcdc_pclk_clk);
+ }
+ mdp_lcdc_pad_pclk_clk = clk_get(NULL, "mdp_lcdc_pad_pclk_clk");
+ if (IS_ERR(mdp_lcdc_pad_pclk_clk)) {
+ printk(KERN_ERR "error: can't get mdp_lcdc_pad_pclk_clk!\n");
+ return IS_ERR(mdp_lcdc_pad_pclk_clk);
+ }
+// pm_qos_add_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc",
+// PM_QOS_DEFAULT_VALUE);
+ return lcdc_register_driver();
+}
+
+module_init(lcdc_driver_init);
diff --git a/drivers/staging/msm/lcdc_external.c b/drivers/staging/msm/lcdc_external.c
new file mode 100644
index 0000000..45ff785
--- /dev/null
+++ b/drivers/staging/msm/lcdc_external.c
@@ -0,0 +1,54 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+
+static int __init lcdc_external_init(void)
+{
+ int ret;
+ struct msm_panel_info pinfo;
+
+ if (msm_fb_detect_client("lcdc_external"))
+ return 0;
+
+ pinfo.xres = 1280;
+ pinfo.yres = 720;
+ pinfo.type = LCDC_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 24;
+ pinfo.fb_num = 2;
+ pinfo.clk_rate = 74250000;
+
+ pinfo.lcdc.h_back_porch = 124;
+ pinfo.lcdc.h_front_porch = 110;
+ pinfo.lcdc.h_pulse_width = 136;
+ pinfo.lcdc.v_back_porch = 19;
+ pinfo.lcdc.v_front_porch = 5;
+ pinfo.lcdc.v_pulse_width = 6;
+ pinfo.lcdc.border_clr = 0; /* blk */
+ pinfo.lcdc.underflow_clr = 0xff; /* blue */
+ pinfo.lcdc.hsync_skew = 0;
+
+ ret = lcdc_device_register(&pinfo);
+ if (ret)
+ printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(lcdc_external_init);
diff --git a/drivers/staging/msm/lcdc_gordon.c b/drivers/staging/msm/lcdc_gordon.c
new file mode 100644
index 0000000..399ec8c
--- /dev/null
+++ b/drivers/staging/msm/lcdc_gordon.c
@@ -0,0 +1,446 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/delay.h>
+#include <mach/gpio.h>
+#include "msm_fb.h"
+
+/* registers */
+#define GORDON_REG_NOP 0x00
+#define GORDON_REG_IMGCTL1 0x10
+#define GORDON_REG_IMGCTL2 0x11
+#define GORDON_REG_IMGSET1 0x12
+#define GORDON_REG_IMGSET2 0x13
+#define GORDON_REG_IVBP1 0x14
+#define GORDON_REG_IHBP1 0x15
+#define GORDON_REG_IVNUM1 0x16
+#define GORDON_REG_IHNUM1 0x17
+#define GORDON_REG_IVBP2 0x18
+#define GORDON_REG_IHBP2 0x19
+#define GORDON_REG_IVNUM2 0x1A
+#define GORDON_REG_IHNUM2 0x1B
+#define GORDON_REG_LCDIFCTL1 0x30
+#define GORDON_REG_VALTRAN 0x31
+#define GORDON_REG_AVCTL 0x33
+#define GORDON_REG_LCDIFCTL2 0x34
+#define GORDON_REG_LCDIFCTL3 0x35
+#define GORDON_REG_LCDIFSET1 0x36
+#define GORDON_REG_PCCTL 0x3C
+#define GORDON_REG_TPARAM1 0x40
+#define GORDON_REG_TLCDIF1 0x41
+#define GORDON_REG_TSSPB_ST1 0x42
+#define GORDON_REG_TSSPB_ED1 0x43
+#define GORDON_REG_TSCK_ST1 0x44
+#define GORDON_REG_TSCK_WD1 0x45
+#define GORDON_REG_TGSPB_VST1 0x46
+#define GORDON_REG_TGSPB_VED1 0x47
+#define GORDON_REG_TGSPB_CH1 0x48
+#define GORDON_REG_TGCK_ST1 0x49
+#define GORDON_REG_TGCK_ED1 0x4A
+#define GORDON_REG_TPCTL_ST1 0x4B
+#define GORDON_REG_TPCTL_ED1 0x4C
+#define GORDON_REG_TPCHG_ED1 0x4D
+#define GORDON_REG_TCOM_CH1 0x4E
+#define GORDON_REG_THBP1 0x4F
+#define GORDON_REG_TPHCTL1 0x50
+#define GORDON_REG_EVPH1 0x51
+#define GORDON_REG_EVPL1 0x52
+#define GORDON_REG_EVNH1 0x53
+#define GORDON_REG_EVNL1 0x54
+#define GORDON_REG_TBIAS1 0x55
+#define GORDON_REG_TPARAM2 0x56
+#define GORDON_REG_TLCDIF2 0x57
+#define GORDON_REG_TSSPB_ST2 0x58
+#define GORDON_REG_TSSPB_ED2 0x59
+#define GORDON_REG_TSCK_ST2 0x5A
+#define GORDON_REG_TSCK_WD2 0x5B
+#define GORDON_REG_TGSPB_VST2 0x5C
+#define GORDON_REG_TGSPB_VED2 0x5D
+#define GORDON_REG_TGSPB_CH2 0x5E
+#define GORDON_REG_TGCK_ST2 0x5F
+#define GORDON_REG_TGCK_ED2 0x60
+#define GORDON_REG_TPCTL_ST2 0x61
+#define GORDON_REG_TPCTL_ED2 0x62
+#define GORDON_REG_TPCHG_ED2 0x63
+#define GORDON_REG_TCOM_CH2 0x64
+#define GORDON_REG_THBP2 0x65
+#define GORDON_REG_TPHCTL2 0x66
+#define GORDON_REG_POWCTL 0x80
+
+static int lcdc_gordon_panel_off(struct platform_device *pdev);
+
+static int spi_cs;
+static int spi_sclk;
+static int spi_sdo;
+static int spi_sdi;
+static int spi_dac;
+static unsigned char bit_shift[8] = { (1 << 7), /* MSB */
+ (1 << 6),
+ (1 << 5),
+ (1 << 4),
+ (1 << 3),
+ (1 << 2),
+ (1 << 1),
+ (1 << 0) /* LSB */
+};
+
+struct gordon_state_type{
+ boolean disp_initialized;
+ boolean display_on;
+ boolean disp_powered_up;
+};
+
+static struct gordon_state_type gordon_state = { 0 };
+static struct msm_panel_common_pdata *lcdc_gordon_pdata;
+
+static void serigo(uint16 reg, uint8 data)
+{
+ unsigned int tx_val = ((0x00FF & reg) << 8) | data;
+ unsigned char i, val = 0;
+
+ /* Enable the Chip Select */
+ gpio_set_value(spi_cs, 1);
+ udelay(33);
+
+ /* Transmit it in two parts, Higher Byte first, then Lower Byte */
+ val = (unsigned char)((tx_val & 0xFF00) >> 8);
+
+ /* Clock should be Low before entering ! */
+ for (i = 0; i < 8; i++) {
+ /* #1: Drive the Data (High or Low) */
+ if (val & bit_shift[i])
+ gpio_set_value(spi_sdi, 1);
+ else
+ gpio_set_value(spi_sdi, 0);
+
+ /* #2: Drive the Clk High and then Low */
+ udelay(33);
+ gpio_set_value(spi_sclk, 1);
+ udelay(33);
+ gpio_set_value(spi_sclk, 0);
+ }
+
+ /* Idle state of SDO (MOSI) is Low */
+ gpio_set_value(spi_sdi, 0);
+ /* ..then Lower Byte */
+ val = (uint8) (tx_val & 0x00FF);
+ /* Before we enter here the Clock should be Low ! */
+
+ for (i = 0; i < 8; i++) {
+ /* #1: Drive the Data (High or Low) */
+ if (val & bit_shift[i])
+ gpio_set_value(spi_sdi, 1);
+ else
+ gpio_set_value(spi_sdi, 0);
+
+ /* #2: Drive the Clk High and then Low */
+ udelay(33);
+
+ gpio_set_value(spi_sclk, 1);
+ udelay(33);
+ gpio_set_value(spi_sclk, 0);
+ }
+
+ /* Idle state of SDO (MOSI) is Low */
+ gpio_set_value(spi_sdi, 0);
+
+ /* Now Disable the Chip Select */
+ udelay(33);
+ gpio_set_value(spi_cs, 0);
+}
+
+static void spi_init(void)
+{
+ /* Setting the Default GPIO's */
+ spi_sclk = *(lcdc_gordon_pdata->gpio_num);
+ spi_cs = *(lcdc_gordon_pdata->gpio_num + 1);
+ spi_sdi = *(lcdc_gordon_pdata->gpio_num + 2);
+ spi_sdo = *(lcdc_gordon_pdata->gpio_num + 3);
+
+ /* Set the output so that we dont disturb the slave device */
+ gpio_set_value(spi_sclk, 0);
+ gpio_set_value(spi_sdi, 0);
+
+ /* Set the Chip Select De-asserted */
+ gpio_set_value(spi_cs, 0);
+
+}
+
+static void gordon_disp_powerup(void)
+{
+ if (!gordon_state.disp_powered_up && !gordon_state.display_on) {
+ /* Reset the hardware first */
+ /* Include DAC power up implementation here */
+ gordon_state.disp_powered_up = TRUE;
+ }
+}
+
+static void gordon_init(void)
+{
+ /* Image interface settings */
+ serigo(GORDON_REG_IMGCTL2, 0x00);
+ serigo(GORDON_REG_IMGSET1, 0x00);
+
+ /* Exchange the RGB signal for J510(Softbank mobile) */
+ serigo(GORDON_REG_IMGSET2, 0x12);
+ serigo(GORDON_REG_LCDIFSET1, 0x00);
+
+ /* Pre-charge settings */
+ serigo(GORDON_REG_PCCTL, 0x09);
+ serigo(GORDON_REG_LCDIFCTL2, 0x7B);
+
+ mdelay(1);
+}
+
+static void gordon_disp_on(void)
+{
+ if (gordon_state.disp_powered_up && !gordon_state.display_on) {
+ gordon_init();
+ mdelay(20);
+ /* gordon_dispmode setting */
+ serigo(GORDON_REG_TPARAM1, 0x30);
+ serigo(GORDON_REG_TLCDIF1, 0x00);
+ serigo(GORDON_REG_TSSPB_ST1, 0x8B);
+ serigo(GORDON_REG_TSSPB_ED1, 0x93);
+ serigo(GORDON_REG_TSCK_ST1, 0x88);
+ serigo(GORDON_REG_TSCK_WD1, 0x00);
+ serigo(GORDON_REG_TGSPB_VST1, 0x01);
+ serigo(GORDON_REG_TGSPB_VED1, 0x02);
+ serigo(GORDON_REG_TGSPB_CH1, 0x5E);
+ serigo(GORDON_REG_TGCK_ST1, 0x80);
+ serigo(GORDON_REG_TGCK_ED1, 0x3C);
+ serigo(GORDON_REG_TPCTL_ST1, 0x50);
+ serigo(GORDON_REG_TPCTL_ED1, 0x74);
+ serigo(GORDON_REG_TPCHG_ED1, 0x78);
+ serigo(GORDON_REG_TCOM_CH1, 0x50);
+ serigo(GORDON_REG_THBP1, 0x84);
+ serigo(GORDON_REG_TPHCTL1, 0x00);
+ serigo(GORDON_REG_EVPH1, 0x70);
+ serigo(GORDON_REG_EVPL1, 0x64);
+ serigo(GORDON_REG_EVNH1, 0x56);
+ serigo(GORDON_REG_EVNL1, 0x48);
+ serigo(GORDON_REG_TBIAS1, 0x88);
+
+ /* QVGA settings */
+ serigo(GORDON_REG_TPARAM2, 0x28);
+ serigo(GORDON_REG_TLCDIF2, 0x14);
+ serigo(GORDON_REG_TSSPB_ST2, 0x49);
+ serigo(GORDON_REG_TSSPB_ED2, 0x4B);
+ serigo(GORDON_REG_TSCK_ST2, 0x4A);
+ serigo(GORDON_REG_TSCK_WD2, 0x02);
+ serigo(GORDON_REG_TGSPB_VST2, 0x02);
+ serigo(GORDON_REG_TGSPB_VED2, 0x03);
+ serigo(GORDON_REG_TGSPB_CH2, 0x2F);
+ serigo(GORDON_REG_TGCK_ST2, 0x40);
+ serigo(GORDON_REG_TGCK_ED2, 0x1E);
+ serigo(GORDON_REG_TPCTL_ST2, 0x2C);
+ serigo(GORDON_REG_TPCTL_ED2, 0x3A);
+ serigo(GORDON_REG_TPCHG_ED2, 0x3C);
+ serigo(GORDON_REG_TCOM_CH2, 0x28);
+ serigo(GORDON_REG_THBP2, 0x4D);
+ serigo(GORDON_REG_TPHCTL2, 0x1A);
+
+ /* VGA settings */
+ serigo(GORDON_REG_IVBP1, 0x02);
+ serigo(GORDON_REG_IHBP1, 0x90);
+ serigo(GORDON_REG_IVNUM1, 0xA0);
+ serigo(GORDON_REG_IHNUM1, 0x78);
+
+ /* QVGA settings */
+ serigo(GORDON_REG_IVBP2, 0x02);
+ serigo(GORDON_REG_IHBP2, 0x48);
+ serigo(GORDON_REG_IVNUM2, 0x50);
+ serigo(GORDON_REG_IHNUM2, 0x3C);
+
+ /* Gordon Charge pump settings and ON */
+ serigo(GORDON_REG_POWCTL, 0x03);
+ mdelay(15);
+ serigo(GORDON_REG_POWCTL, 0x07);
+ mdelay(15);
+
+ serigo(GORDON_REG_POWCTL, 0x0F);
+ mdelay(15);
+
+ serigo(GORDON_REG_AVCTL, 0x03);
+ mdelay(15);
+
+ serigo(GORDON_REG_POWCTL, 0x1F);
+ mdelay(15);
+
+ serigo(GORDON_REG_POWCTL, 0x5F);
+ mdelay(15);
+
+ serigo(GORDON_REG_POWCTL, 0x7F);
+ mdelay(15);
+
+ serigo(GORDON_REG_LCDIFCTL1, 0x02);
+ mdelay(15);
+
+ serigo(GORDON_REG_IMGCTL1, 0x00);
+ mdelay(15);
+
+ serigo(GORDON_REG_LCDIFCTL3, 0x00);
+ mdelay(15);
+
+ serigo(GORDON_REG_VALTRAN, 0x01);
+ mdelay(15);
+
+ serigo(GORDON_REG_LCDIFCTL1, 0x03);
+ mdelay(1);
+ gordon_state.display_on = TRUE;
+ }
+}
+
+static int lcdc_gordon_panel_on(struct platform_device *pdev)
+{
+ if (!gordon_state.disp_initialized) {
+ /* Configure reset GPIO that drives DAC */
+ lcdc_gordon_pdata->panel_config_gpio(1);
+ spi_dac = *(lcdc_gordon_pdata->gpio_num + 4);
+ gpio_set_value(spi_dac, 0);
+ udelay(15);
+ gpio_set_value(spi_dac, 1);
+ spi_init(); /* LCD needs SPI */
+ gordon_disp_powerup();
+ gordon_disp_on();
+ gordon_state.disp_initialized = TRUE;
+ }
+ return 0;
+}
+
+static int lcdc_gordon_panel_off(struct platform_device *pdev)
+{
+ if (gordon_state.disp_powered_up && gordon_state.display_on) {
+ serigo(GORDON_REG_LCDIFCTL2, 0x7B);
+ serigo(GORDON_REG_VALTRAN, 0x01);
+ serigo(GORDON_REG_LCDIFCTL1, 0x02);
+ serigo(GORDON_REG_LCDIFCTL3, 0x01);
+ mdelay(20);
+ serigo(GORDON_REG_VALTRAN, 0x01);
+ serigo(GORDON_REG_IMGCTL1, 0x01);
+ serigo(GORDON_REG_LCDIFCTL1, 0x00);
+ mdelay(20);
+
+ serigo(GORDON_REG_POWCTL, 0x1F);
+ mdelay(40);
+
+ serigo(GORDON_REG_POWCTL, 0x07);
+ mdelay(40);
+
+ serigo(GORDON_REG_POWCTL, 0x03);
+ mdelay(40);
+
+ serigo(GORDON_REG_POWCTL, 0x00);
+ mdelay(40);
+ lcdc_gordon_pdata->panel_config_gpio(0);
+ gordon_state.display_on = FALSE;
+ gordon_state.disp_initialized = FALSE;
+ }
+ return 0;
+}
+
+static void lcdc_gordon_set_backlight(struct msm_fb_data_type *mfd)
+{
+ int bl_level = mfd->bl_level;
+
+ if (bl_level <= 1) {
+ /* keep back light OFF */
+ serigo(GORDON_REG_LCDIFCTL2, 0x0B);
+ udelay(15);
+ serigo(GORDON_REG_VALTRAN, 0x01);
+ } else {
+ /* keep back light ON */
+ serigo(GORDON_REG_LCDIFCTL2, 0x7B);
+ udelay(15);
+ serigo(GORDON_REG_VALTRAN, 0x01);
+ }
+}
+
+static int __init gordon_probe(struct platform_device *pdev)
+{
+ if (pdev->id == 0) {
+ lcdc_gordon_pdata = pdev->dev.platform_data;
+ return 0;
+ }
+ msm_fb_add_device(pdev);
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = gordon_probe,
+ .driver = {
+ .name = "lcdc_gordon_vga",
+ },
+};
+
+static struct msm_fb_panel_data gordon_panel_data = {
+ .on = lcdc_gordon_panel_on,
+ .off = lcdc_gordon_panel_off,
+ .set_backlight = lcdc_gordon_set_backlight,
+};
+
+static struct platform_device this_device = {
+ .name = "lcdc_gordon_vga",
+ .id = 1,
+ .dev = {
+ .platform_data = &gordon_panel_data,
+ }
+};
+
+static int __init lcdc_gordon_panel_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+ if (msm_fb_detect_client("lcdc_gordon_vga"))
+ return 0;
+#endif
+ ret = platform_driver_register(&this_driver);
+ if (ret)
+ return ret;
+
+ pinfo = &gordon_panel_data.panel_info;
+ pinfo->xres = 480;
+ pinfo->yres = 640;
+ pinfo->type = LCDC_PANEL;
+ pinfo->pdest = DISPLAY_1;
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 24;
+ pinfo->fb_num = 2;
+ pinfo->clk_rate = 24500000;
+ pinfo->bl_max = 4;
+ pinfo->bl_min = 1;
+
+ pinfo->lcdc.h_back_porch = 84;
+ pinfo->lcdc.h_front_porch = 33;
+ pinfo->lcdc.h_pulse_width = 60;
+ pinfo->lcdc.v_back_porch = 0;
+ pinfo->lcdc.v_front_porch = 2;
+ pinfo->lcdc.v_pulse_width = 2;
+ pinfo->lcdc.border_clr = 0; /* blk */
+ pinfo->lcdc.underflow_clr = 0xff; /* blue */
+ pinfo->lcdc.hsync_skew = 0;
+
+ ret = platform_device_register(&this_device);
+ if (ret)
+ platform_driver_unregister(&this_driver);
+
+ return ret;
+}
+
+module_init(lcdc_gordon_panel_init);
diff --git a/drivers/staging/msm/lcdc_grapefruit.c b/drivers/staging/msm/lcdc_grapefruit.c
new file mode 100644
index 0000000..7284649
--- /dev/null
+++ b/drivers/staging/msm/lcdc_grapefruit.c
@@ -0,0 +1,60 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+#include "mddihosti.h"
+#endif
+
+static int __init lcdc_grapefruit_init(void)
+{
+ int ret;
+ struct msm_panel_info pinfo;
+
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+ if (msm_fb_detect_client("lcdc_grapefruit_vga"))
+ return 0;
+#endif
+
+ pinfo.xres = 1024;
+ pinfo.yres = 600;
+ pinfo.type = LCDC_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 18;
+ pinfo.fb_num = 2;
+ pinfo.clk_rate = 40000000;
+
+ pinfo.lcdc.h_back_porch = 88;
+ pinfo.lcdc.h_front_porch = 40;
+ pinfo.lcdc.h_pulse_width = 128;
+ pinfo.lcdc.v_back_porch = 23;
+ pinfo.lcdc.v_front_porch = 1;
+ pinfo.lcdc.v_pulse_width = 4;
+ pinfo.lcdc.border_clr = 0; /* blk */
+ pinfo.lcdc.underflow_clr = 0xff; /* blue */
+ pinfo.lcdc.hsync_skew = 0;
+
+ ret = lcdc_device_register(&pinfo);
+ if (ret)
+ printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(lcdc_grapefruit_init);
diff --git a/drivers/staging/msm/lcdc_panel.c b/drivers/staging/msm/lcdc_panel.c
new file mode 100644
index 0000000..b40974e
--- /dev/null
+++ b/drivers/staging/msm/lcdc_panel.c
@@ -0,0 +1,88 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+
+static int lcdc_panel_on(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static int lcdc_panel_off(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static int __init lcdc_panel_probe(struct platform_device *pdev)
+{
+ msm_fb_add_device(pdev);
+
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = lcdc_panel_probe,
+ .driver = {
+ .name = "lcdc_panel",
+ },
+};
+
+static struct msm_fb_panel_data lcdc_panel_data = {
+ .on = lcdc_panel_on,
+ .off = lcdc_panel_off,
+};
+
+static int lcdc_dev_id;
+
+int lcdc_device_register(struct msm_panel_info *pinfo)
+{
+ struct platform_device *pdev = NULL;
+ int ret;
+
+ pdev = platform_device_alloc("lcdc_panel", ++lcdc_dev_id);
+ if (!pdev)
+ return -ENOMEM;
+
+ lcdc_panel_data.panel_info = *pinfo;
+ ret = platform_device_add_data(pdev, &lcdc_panel_data,
+ sizeof(lcdc_panel_data));
+ if (ret) {
+ printk(KERN_ERR
+ "%s: platform_device_add_data failed!\n", __func__);
+ goto err_device_put;
+ }
+
+ ret = platform_device_add(pdev);
+ if (ret) {
+ printk(KERN_ERR
+ "%s: platform_device_register failed!\n", __func__);
+ goto err_device_put;
+ }
+
+ return 0;
+
+err_device_put:
+ platform_device_put(pdev);
+ return ret;
+}
+
+static int __init lcdc_panel_init(void)
+{
+ return platform_driver_register(&this_driver);
+}
+
+module_init(lcdc_panel_init);
diff --git a/drivers/staging/msm/lcdc_prism.c b/drivers/staging/msm/lcdc_prism.c
new file mode 100644
index 0000000..d102c98
--- /dev/null
+++ b/drivers/staging/msm/lcdc_prism.c
@@ -0,0 +1,64 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+#include "mddihosti.h"
+#endif
+
+static int __init lcdc_prism_init(void)
+{
+ int ret;
+ struct msm_panel_info pinfo;
+
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+ ret = msm_fb_detect_client("lcdc_prism_wvga");
+ if (ret == -ENODEV)
+ return 0;
+
+ if (ret && (mddi_get_client_id() != 0))
+ return 0;
+#endif
+
+ pinfo.xres = 800;
+ pinfo.yres = 480;
+ pinfo.type = LCDC_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 24;
+ pinfo.fb_num = 2;
+ pinfo.clk_rate = 38460000;
+
+ pinfo.lcdc.h_back_porch = 21;
+ pinfo.lcdc.h_front_porch = 81;
+ pinfo.lcdc.h_pulse_width = 60;
+ pinfo.lcdc.v_back_porch = 18;
+ pinfo.lcdc.v_front_porch = 27;
+ pinfo.lcdc.v_pulse_width = 2;
+ pinfo.lcdc.border_clr = 0; /* blk */
+ pinfo.lcdc.underflow_clr = 0xff; /* blue */
+ pinfo.lcdc.hsync_skew = 0;
+
+ ret = lcdc_device_register(&pinfo);
+ if (ret)
+ printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(lcdc_prism_init);
diff --git a/drivers/staging/msm/lcdc_sharp_wvga_pt.c b/drivers/staging/msm/lcdc_sharp_wvga_pt.c
new file mode 100644
index 0000000..1f08cf9
--- /dev/null
+++ b/drivers/staging/msm/lcdc_sharp_wvga_pt.c
@@ -0,0 +1,290 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/delay.h>
+#ifdef CONFIG_ARCH_MSM7X30
+#include <linux/mfd/pmic8058.h>
+#endif
+#include <mach/gpio.h>
+#include "msm_fb.h"
+
+static int lcdc_sharp_panel_off(struct platform_device *pdev);
+
+static int spi_cs;
+static int spi_sclk;
+static int spi_mosi;
+static int spi_miso;
+static unsigned char bit_shift[8] = { (1 << 7), /* MSB */
+ (1 << 6),
+ (1 << 5),
+ (1 << 4),
+ (1 << 3),
+ (1 << 2),
+ (1 << 1),
+ (1 << 0) /* LSB */
+};
+
+struct sharp_state_type {
+ boolean disp_initialized;
+ boolean display_on;
+ boolean disp_powered_up;
+};
+
+struct sharp_spi_data {
+ u8 addr;
+ u8 data;
+};
+
+static struct sharp_spi_data init_sequence[] = {
+ { 15, 0x01 },
+ { 5, 0x01 },
+ { 7, 0x10 },
+ { 9, 0x1E },
+ { 10, 0x04 },
+ { 17, 0xFF },
+ { 21, 0x8A },
+ { 22, 0x00 },
+ { 23, 0x82 },
+ { 24, 0x24 },
+ { 25, 0x22 },
+ { 26, 0x6D },
+ { 27, 0xEB },
+ { 28, 0xB9 },
+ { 29, 0x3A },
+ { 49, 0x1A },
+ { 50, 0x16 },
+ { 51, 0x05 },
+ { 55, 0x7F },
+ { 56, 0x15 },
+ { 57, 0x7B },
+ { 60, 0x05 },
+ { 61, 0x0C },
+ { 62, 0x80 },
+ { 63, 0x00 },
+ { 92, 0x90 },
+ { 97, 0x01 },
+ { 98, 0xFF },
+ { 113, 0x11 },
+ { 114, 0x02 },
+ { 115, 0x08 },
+ { 123, 0xAB },
+ { 124, 0x04 },
+ { 6, 0x02 },
+ { 133, 0x00 },
+ { 134, 0xFE },
+ { 135, 0x22 },
+ { 136, 0x0B },
+ { 137, 0xFF },
+ { 138, 0x0F },
+ { 139, 0x00 },
+ { 140, 0xFE },
+ { 141, 0x22 },
+ { 142, 0x0B },
+ { 143, 0xFF },
+ { 144, 0x0F },
+ { 145, 0x00 },
+ { 146, 0xFE },
+ { 147, 0x22 },
+ { 148, 0x0B },
+ { 149, 0xFF },
+ { 150, 0x0F },
+ { 202, 0x30 },
+ { 30, 0x01 },
+ { 4, 0x01 },
+ { 31, 0x41 },
+};
+
+static struct sharp_state_type sharp_state = { 0 };
+static struct msm_panel_common_pdata *lcdc_sharp_pdata;
+
+static void sharp_spi_write_byte(u8 val)
+{
+ int i;
+
+ /* Clock should be Low before entering */
+ for (i = 0; i < 8; i++) {
+ /* #1: Drive the Data (High or Low) */
+ if (val & bit_shift[i])
+ gpio_set_value(spi_mosi, 1);
+ else
+ gpio_set_value(spi_mosi, 0);
+
+ /* #2: Drive the Clk High and then Low */
+ gpio_set_value(spi_sclk, 1);
+ gpio_set_value(spi_sclk, 0);
+ }
+}
+
+static void serigo(u8 reg, u8 data)
+{
+ /* Enable the Chip Select - low */
+ gpio_set_value(spi_cs, 0);
+ udelay(1);
+
+ /* Transmit register address first, then data */
+ sharp_spi_write_byte(reg);
+
+ /* Idle state of MOSI is Low */
+ gpio_set_value(spi_mosi, 0);
+ udelay(1);
+ sharp_spi_write_byte(data);
+
+ gpio_set_value(spi_mosi, 0);
+ gpio_set_value(spi_cs, 1);
+}
+
+static void sharp_spi_init(void)
+{
+ spi_sclk = *(lcdc_sharp_pdata->gpio_num);
+ spi_cs = *(lcdc_sharp_pdata->gpio_num + 1);
+ spi_mosi = *(lcdc_sharp_pdata->gpio_num + 2);
+ spi_miso = *(lcdc_sharp_pdata->gpio_num + 3);
+
+ /* Set the output so that we don't disturb the slave device */
+ gpio_set_value(spi_sclk, 0);
+ gpio_set_value(spi_mosi, 0);
+
+ /* Set the Chip Select deasserted (active low) */
+ gpio_set_value(spi_cs, 1);
+}
+
+static void sharp_disp_powerup(void)
+{
+ if (!sharp_state.disp_powered_up && !sharp_state.display_on)
+ sharp_state.disp_powered_up = TRUE;
+}
+
+static void sharp_disp_on(void)
+{
+ int i;
+
+ if (sharp_state.disp_powered_up && !sharp_state.display_on) {
+ for (i = 0; i < ARRAY_SIZE(init_sequence); i++) {
+ serigo(init_sequence[i].addr,
+ init_sequence[i].data);
+ }
+ mdelay(10);
+ serigo(31, 0xC1);
+ mdelay(10);
+ serigo(31, 0xD9);
+ serigo(31, 0xDF);
+
+ sharp_state.display_on = TRUE;
+ }
+}
+
+static int lcdc_sharp_panel_on(struct platform_device *pdev)
+{
+ if (!sharp_state.disp_initialized) {
+ lcdc_sharp_pdata->panel_config_gpio(1);
+ sharp_spi_init();
+ sharp_disp_powerup();
+ sharp_disp_on();
+ sharp_state.disp_initialized = TRUE;
+ }
+ return 0;
+}
+
+static int lcdc_sharp_panel_off(struct platform_device *pdev)
+{
+ if (sharp_state.disp_powered_up && sharp_state.display_on) {
+ serigo(4, 0x00);
+ mdelay(40);
+ serigo(31, 0xC1);
+ mdelay(40);
+ serigo(31, 0x00);
+ mdelay(100);
+ sharp_state.display_on = FALSE;
+ sharp_state.disp_initialized = FALSE;
+ }
+ return 0;
+}
+
+static int __init sharp_probe(struct platform_device *pdev)
+{
+ if (pdev->id == 0) {
+ lcdc_sharp_pdata = pdev->dev.platform_data;
+ return 0;
+ }
+ msm_fb_add_device(pdev);
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = sharp_probe,
+ .driver = {
+ .name = "lcdc_sharp_wvga",
+ },
+};
+
+static struct msm_fb_panel_data sharp_panel_data = {
+ .on = lcdc_sharp_panel_on,
+ .off = lcdc_sharp_panel_off,
+};
+
+static struct platform_device this_device = {
+ .name = "lcdc_sharp_wvga",
+ .id = 1,
+ .dev = {
+ .platform_data = &sharp_panel_data,
+ }
+};
+
+static int __init lcdc_sharp_panel_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+ if (msm_fb_detect_client("lcdc_sharp_wvga_pt"))
+ return 0;
+#endif
+
+ ret = platform_driver_register(&this_driver);
+ if (ret)
+ return ret;
+
+ pinfo = &sharp_panel_data.panel_info;
+ pinfo->xres = 480;
+ pinfo->yres = 800;
+ pinfo->type = LCDC_PANEL;
+ pinfo->pdest = DISPLAY_1;
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 18;
+ pinfo->fb_num = 2;
+ pinfo->clk_rate = 24500000;
+ pinfo->bl_max = 4;
+ pinfo->bl_min = 1;
+
+ pinfo->lcdc.h_back_porch = 20;
+ pinfo->lcdc.h_front_porch = 10;
+ pinfo->lcdc.h_pulse_width = 10;
+ pinfo->lcdc.v_back_porch = 2;
+ pinfo->lcdc.v_front_porch = 2;
+ pinfo->lcdc.v_pulse_width = 2;
+ pinfo->lcdc.border_clr = 0;
+ pinfo->lcdc.underflow_clr = 0xff;
+ pinfo->lcdc.hsync_skew = 0;
+
+ ret = platform_device_register(&this_device);
+ if (ret)
+ platform_driver_unregister(&this_driver);
+
+ return ret;
+}
+
+module_init(lcdc_sharp_panel_init);
diff --git a/drivers/staging/msm/lcdc_st15.c b/drivers/staging/msm/lcdc_st15.c
new file mode 100644
index 0000000..fed8278
--- /dev/null
+++ b/drivers/staging/msm/lcdc_st15.c
@@ -0,0 +1,237 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include "msm_fb.h"
+
+#define DEVICE_NAME "sii9022"
+#define SII9022_DEVICE_ID 0xB0
+
+struct sii9022_i2c_addr_data{
+ u8 addr;
+ u8 data;
+};
+
+/* video mode data */
+static u8 video_mode_data[] = {
+ 0x00,
+ 0xF9, 0x1C, 0x70, 0x17, 0x72, 0x06, 0xEE, 0x02,
+};
+
+static u8 avi_io_format[] = {
+ 0x09,
+ 0x00, 0x00,
+};
+
+/* power state */
+static struct sii9022_i2c_addr_data regset0[] = {
+ { 0x60, 0x04 },
+ { 0x63, 0x00 },
+ { 0x1E, 0x00 },
+};
+
+static u8 video_infoframe[] = {
+ 0x0C,
+ 0xF0, 0x00, 0x68, 0x00, 0x04, 0x00, 0x19, 0x00,
+ 0xE9, 0x02, 0x04, 0x01, 0x04, 0x06,
+};
+
+/* configure audio */
+static struct sii9022_i2c_addr_data regset1[] = {
+ { 0x26, 0x90 },
+ { 0x20, 0x90 },
+ { 0x1F, 0x80 },
+ { 0x26, 0x80 },
+ { 0x24, 0x02 },
+ { 0x25, 0x0B },
+ { 0xBC, 0x02 },
+ { 0xBD, 0x24 },
+ { 0xBE, 0x02 },
+};
+
+/* enable audio */
+static u8 misc_infoframe[] = {
+ 0xBF,
+ 0xC2, 0x84, 0x01, 0x0A, 0x6F, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+/* set HDMI, active */
+static struct sii9022_i2c_addr_data regset2[] = {
+ { 0x1A, 0x01 },
+ { 0x3D, 0x00 },
+};
+
+static int send_i2c_data(struct i2c_client *client,
+ struct sii9022_i2c_addr_data *regset,
+ int size)
+{
+ int i;
+ int rc = 0;
+
+ for (i = 0; i < size; i++) {
+ rc = i2c_smbus_write_byte_data(
+ client,
+ regset[i].addr, regset[i].data);
+ if (rc)
+ break;
+ }
+ return rc;
+}
+
+static int hdmi_sii_enable(struct i2c_client *client)
+{
+ int rc;
+ int retries = 10;
+ int count;
+
+ rc = i2c_smbus_write_byte_data(client, 0xC7, 0x00);
+ if (rc)
+ goto enable_exit;
+
+ do {
+ msleep(1);
+ rc = i2c_smbus_read_byte_data(client, 0x1B);
+ } while ((rc != SII9022_DEVICE_ID) && retries--);
+
+ if (rc != SII9022_DEVICE_ID)
+ return -ENODEV;
+
+ rc = i2c_smbus_write_byte_data(client, 0x1A, 0x11);
+ if (rc)
+ goto enable_exit;
+
+ count = ARRAY_SIZE(video_mode_data);
+ rc = i2c_master_send(client, video_mode_data, count);
+ if (rc != count) {
+ rc = -EIO;
+ goto enable_exit;
+ }
+
+ rc = i2c_smbus_write_byte_data(client, 0x08, 0x20);
+ if (rc)
+ goto enable_exit;
+ count = ARRAY_SIZE(avi_io_format);
+ rc = i2c_master_send(client, avi_io_format, count);
+ if (rc != count) {
+ rc = -EIO;
+ goto enable_exit;
+ }
+
+ rc = send_i2c_data(client, regset0, ARRAY_SIZE(regset0));
+ if (rc)
+ goto enable_exit;
+
+ count = ARRAY_SIZE(video_infoframe);
+ rc = i2c_master_send(client, video_infoframe, count);
+ if (rc != count) {
+ rc = -EIO;
+ goto enable_exit;
+ }
+
+ rc = send_i2c_data(client, regset1, ARRAY_SIZE(regset1));
+ if (rc)
+ goto enable_exit;
+
+ count = ARRAY_SIZE(misc_infoframe);
+ rc = i2c_master_send(client, misc_infoframe, count);
+ if (rc != count) {
+ rc = -EIO;
+ goto enable_exit;
+ }
+
+ rc = send_i2c_data(client, regset2, ARRAY_SIZE(regset2));
+ if (rc)
+ goto enable_exit;
+
+ return 0;
+enable_exit:
+ printk(KERN_ERR "%s: exited rc=%d\n", __func__, rc);
+ return rc;
+}
+
+static const struct i2c_device_id hmdi_sii_id[] = {
+ { DEVICE_NAME, 0 },
+ { }
+};
+
+static int hdmi_sii_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int rc;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C))
+ return -ENODEV;
+ rc = hdmi_sii_enable(client);
+ return rc;
+}
+
+
+static struct i2c_driver hdmi_sii_i2c_driver = {
+ .driver = {
+ .name = DEVICE_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = hdmi_sii_probe,
+ .remove = __exit_p(hdmi_sii_remove),
+ .id_table = hmdi_sii_id,
+};
+
+static int __init lcdc_st15_init(void)
+{
+ int ret;
+ struct msm_panel_info pinfo;
+
+ if (msm_fb_detect_client("lcdc_st15"))
+ return 0;
+
+ pinfo.xres = 1366;
+ pinfo.yres = 768;
+ pinfo.type = LCDC_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 24;
+ pinfo.fb_num = 2;
+ pinfo.clk_rate = 74250000;
+
+ pinfo.lcdc.h_back_porch = 120;
+ pinfo.lcdc.h_front_porch = 20;
+ pinfo.lcdc.h_pulse_width = 40;
+ pinfo.lcdc.v_back_porch = 25;
+ pinfo.lcdc.v_front_porch = 1;
+ pinfo.lcdc.v_pulse_width = 7;
+ pinfo.lcdc.border_clr = 0; /* blk */
+ pinfo.lcdc.underflow_clr = 0xff; /* blue */
+ pinfo.lcdc.hsync_skew = 0;
+
+ ret = lcdc_device_register(&pinfo);
+ if (ret) {
+ printk(KERN_ERR "%s: failed to register device!\n", __func__);
+ goto init_exit;
+ }
+
+ ret = i2c_add_driver(&hdmi_sii_i2c_driver);
+ if (ret)
+ printk(KERN_ERR "%s: failed to add i2c driver\n", __func__);
+
+init_exit:
+ return ret;
+}
+
+module_init(lcdc_st15_init);
diff --git a/drivers/staging/msm/lcdc_st1_wxga.c b/drivers/staging/msm/lcdc_st1_wxga.c
new file mode 100644
index 0000000..7376001
--- /dev/null
+++ b/drivers/staging/msm/lcdc_st1_wxga.c
@@ -0,0 +1,54 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+
+static int __init lcdc_st1_wxga_init(void)
+{
+ int ret;
+ struct msm_panel_info pinfo;
+
+ if (msm_fb_detect_client("lcdc_st1_wxga"))
+ return 0;
+
+ pinfo.xres = 1280;
+ pinfo.yres = 720;
+ pinfo.type = LCDC_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 18;
+ pinfo.fb_num = 2;
+ pinfo.clk_rate = 74250000;
+
+ pinfo.lcdc.h_back_porch = 124;
+ pinfo.lcdc.h_front_porch = 110;
+ pinfo.lcdc.h_pulse_width = 136;
+ pinfo.lcdc.v_back_porch = 19;
+ pinfo.lcdc.v_front_porch = 5;
+ pinfo.lcdc.v_pulse_width = 6;
+ pinfo.lcdc.border_clr = 0; /* blk */
+ pinfo.lcdc.underflow_clr = 0xff; /* blue */
+ pinfo.lcdc.hsync_skew = 0;
+
+ ret = lcdc_device_register(&pinfo);
+ if (ret)
+ printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(lcdc_st1_wxga_init);
diff --git a/drivers/staging/msm/lcdc_toshiba_wvga_pt.c b/drivers/staging/msm/lcdc_toshiba_wvga_pt.c
new file mode 100644
index 0000000..864d7c1
--- /dev/null
+++ b/drivers/staging/msm/lcdc_toshiba_wvga_pt.c
@@ -0,0 +1,374 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <mach/gpio.h>
+#include <mach/pmic.h>
+#include "msm_fb.h"
+
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+#include "mddihosti.h"
+#endif
+
+static int spi_cs;
+static int spi_sclk;
+static int spi_mosi;
+static int spi_miso;
+
+struct toshiba_state_type{
+ boolean disp_initialized;
+ boolean display_on;
+ boolean disp_powered_up;
+};
+
+static struct toshiba_state_type toshiba_state = { 0 };
+static struct msm_panel_common_pdata *lcdc_toshiba_pdata;
+
+static void toshiba_spi_write_byte(char dc, uint8 data)
+{
+ uint32 bit;
+ int bnum;
+
+ gpio_set_value(spi_sclk, 0); /* clk low */
+ /* dc: 0 for command, 1 for parameter */
+ gpio_set_value(spi_mosi, dc);
+ udelay(1); /* at least 20 ns */
+ gpio_set_value(spi_sclk, 1); /* clk high */
+ udelay(1); /* at least 20 ns */
+ bnum = 8; /* 8 data bits */
+ bit = 0x80;
+ while (bnum) {
+ gpio_set_value(spi_sclk, 0); /* clk low */
+ if (data & bit)
+ gpio_set_value(spi_mosi, 1);
+ else
+ gpio_set_value(spi_mosi, 0);
+ udelay(1);
+ gpio_set_value(spi_sclk, 1); /* clk high */
+ udelay(1);
+ bit >>= 1;
+ bnum--;
+ }
+}
+
+static void toshiba_spi_write(char cmd, uint32 data, int num)
+{
+ char *bp;
+
+ gpio_set_value(spi_cs, 1); /* cs high */
+
+ /* command byte first */
+ toshiba_spi_write_byte(0, cmd);
+
+ /* followed by parameter bytes */
+ if (num) {
+ bp = (char *)&data;;
+ bp += (num - 1);
+ while (num) {
+ toshiba_spi_write_byte(1, *bp);
+ num--;
+ bp--;
+ }
+ }
+
+ gpio_set_value(spi_cs, 0); /* cs low */
+ udelay(1);
+}
+
+void toshiba_spi_read_bytes(char cmd, uint32 *data, int num)
+{
+ uint32 dbit, bits;
+ int bnum;
+
+ gpio_set_value(spi_cs, 1); /* cs high */
+
+ /* command byte first */
+ toshiba_spi_write_byte(0, cmd);
+
+ if (num > 1) {
+ /* extra dc bit */
+ gpio_set_value(spi_sclk, 0); /* clk low */
+ udelay(1);
+ dbit = gpio_get_value(spi_miso);/* dc bit */
+ udelay(1);
+ gpio_set_value(spi_sclk, 1); /* clk high */
+ }
+
+ /* followed by data bytes */
+ bnum = num * 8; /* number of bits */
+ bits = 0;
+ while (bnum) {
+ bits <<= 1;
+ gpio_set_value(spi_sclk, 0); /* clk low */
+ udelay(1);
+ dbit = gpio_get_value(spi_miso);
+ udelay(1);
+ gpio_set_value(spi_sclk, 1); /* clk high */
+ bits |= dbit;
+ bnum--;
+ }
+
+ *data = bits;
+
+ udelay(1);
+ gpio_set_value(spi_cs, 0); /* cs low */
+ udelay(1);
+}
+
+static void spi_pin_assign(void)
+{
+ /* Setting the Default GPIO's */
+ spi_sclk = *(lcdc_toshiba_pdata->gpio_num);
+ spi_cs = *(lcdc_toshiba_pdata->gpio_num + 1);
+ spi_mosi = *(lcdc_toshiba_pdata->gpio_num + 2);
+ spi_miso = *(lcdc_toshiba_pdata->gpio_num + 3);
+}
+
+static void toshiba_disp_powerup(void)
+{
+ if (!toshiba_state.disp_powered_up && !toshiba_state.display_on) {
+ /* Reset the hardware first */
+ /* Include DAC power up implementation here */
+ toshiba_state.disp_powered_up = TRUE;
+ }
+}
+
+static void toshiba_disp_on(void)
+{
+ uint32 data;
+
+ gpio_set_value(spi_cs, 0); /* low */
+ gpio_set_value(spi_sclk, 1); /* high */
+ gpio_set_value(spi_mosi, 0);
+ gpio_set_value(spi_miso, 0);
+
+ if (toshiba_state.disp_powered_up && !toshiba_state.display_on) {
+ toshiba_spi_write(0, 0, 0);
+ mdelay(7);
+ toshiba_spi_write(0, 0, 0);
+ mdelay(7);
+ toshiba_spi_write(0, 0, 0);
+ mdelay(7);
+ toshiba_spi_write(0xba, 0x11, 1);
+ toshiba_spi_write(0x36, 0x00, 1);
+ mdelay(1);
+ toshiba_spi_write(0x3a, 0x60, 1);
+ toshiba_spi_write(0xb1, 0x5d, 1);
+ mdelay(1);
+ toshiba_spi_write(0xb2, 0x33, 1);
+ toshiba_spi_write(0xb3, 0x22, 1);
+ mdelay(1);
+ toshiba_spi_write(0xb4, 0x02, 1);
+ toshiba_spi_write(0xb5, 0x1e, 1); /* vcs -- adjust brightness */
+ mdelay(1);
+ toshiba_spi_write(0xb6, 0x27, 1);
+ toshiba_spi_write(0xb7, 0x03, 1);
+ mdelay(1);
+ toshiba_spi_write(0xb9, 0x24, 1);
+ toshiba_spi_write(0xbd, 0xa1, 1);
+ mdelay(1);
+ toshiba_spi_write(0xbb, 0x00, 1);
+ toshiba_spi_write(0xbf, 0x01, 1);
+ mdelay(1);
+ toshiba_spi_write(0xbe, 0x00, 1);
+ toshiba_spi_write(0xc0, 0x11, 1);
+ mdelay(1);
+ toshiba_spi_write(0xc1, 0x11, 1);
+ toshiba_spi_write(0xc2, 0x11, 1);
+ mdelay(1);
+ toshiba_spi_write(0xc3, 0x3232, 2);
+ mdelay(1);
+ toshiba_spi_write(0xc4, 0x3232, 2);
+ mdelay(1);
+ toshiba_spi_write(0xc5, 0x3232, 2);
+ mdelay(1);
+ toshiba_spi_write(0xc6, 0x3232, 2);
+ mdelay(1);
+ toshiba_spi_write(0xc7, 0x6445, 2);
+ mdelay(1);
+ toshiba_spi_write(0xc8, 0x44, 1);
+ toshiba_spi_write(0xc9, 0x52, 1);
+ mdelay(1);
+ toshiba_spi_write(0xca, 0x00, 1);
+ mdelay(1);
+ toshiba_spi_write(0xec, 0x02a4, 2); /* 0x02a4 */
+ mdelay(1);
+ toshiba_spi_write(0xcf, 0x01, 1);
+ mdelay(1);
+ toshiba_spi_write(0xd0, 0xc003, 2); /* c003 */
+ mdelay(1);
+ toshiba_spi_write(0xd1, 0x01, 1);
+ mdelay(1);
+ toshiba_spi_write(0xd2, 0x0028, 2);
+ mdelay(1);
+ toshiba_spi_write(0xd3, 0x0028, 2);
+ mdelay(1);
+ toshiba_spi_write(0xd4, 0x26a4, 2);
+ mdelay(1);
+ toshiba_spi_write(0xd5, 0x20, 1);
+ mdelay(1);
+ toshiba_spi_write(0xef, 0x3200, 2);
+ mdelay(32);
+ toshiba_spi_write(0xbc, 0x80, 1); /* wvga pass through */
+ toshiba_spi_write(0x3b, 0x00, 1);
+ mdelay(1);
+ toshiba_spi_write(0xb0, 0x16, 1);
+ mdelay(1);
+ toshiba_spi_write(0xb8, 0xfff5, 2);
+ mdelay(1);
+ toshiba_spi_write(0x11, 0, 0);
+ mdelay(5);
+ toshiba_spi_write(0x29, 0, 0);
+ mdelay(5);
+ toshiba_state.display_on = TRUE;
+ }
+
+ data = 0;
+ toshiba_spi_read_bytes(0x04, &data, 3);
+ printk(KERN_INFO "toshiba_disp_on: id=%x\n", data);
+
+}
+
+static int lcdc_toshiba_panel_on(struct platform_device *pdev)
+{
+ if (!toshiba_state.disp_initialized) {
+ /* Configure reset GPIO that drives DAC */
+ if (lcdc_toshiba_pdata->panel_config_gpio)
+ lcdc_toshiba_pdata->panel_config_gpio(1);
+ toshiba_disp_powerup();
+ toshiba_disp_on();
+ toshiba_state.disp_initialized = TRUE;
+ }
+ return 0;
+}
+
+static int lcdc_toshiba_panel_off(struct platform_device *pdev)
+{
+ if (toshiba_state.disp_powered_up && toshiba_state.display_on) {
+ /* Main panel power off (Deep standby in) */
+
+ toshiba_spi_write(0x28, 0, 0); /* display off */
+ mdelay(1);
+ toshiba_spi_write(0xb8, 0x8002, 2); /* output control */
+ mdelay(1);
+ toshiba_spi_write(0x10, 0x00, 1); /* sleep mode in */
+ mdelay(85); /* wait 85 msec */
+ toshiba_spi_write(0xb0, 0x00, 1); /* deep standby in */
+ mdelay(1);
+ if (lcdc_toshiba_pdata->panel_config_gpio)
+ lcdc_toshiba_pdata->panel_config_gpio(0);
+ toshiba_state.display_on = FALSE;
+ toshiba_state.disp_initialized = FALSE;
+ }
+ return 0;
+}
+
+static void lcdc_toshiba_set_backlight(struct msm_fb_data_type *mfd)
+{
+ int bl_level;
+ int ret = -EPERM;
+
+ bl_level = mfd->bl_level;
+ ret = pmic_set_led_intensity(LED_LCD, bl_level);
+
+ if (ret)
+ printk(KERN_WARNING "%s: can't set lcd backlight!\n",
+ __func__);
+}
+
+static int __init toshiba_probe(struct platform_device *pdev)
+{
+ if (pdev->id == 0) {
+ lcdc_toshiba_pdata = pdev->dev.platform_data;
+ spi_pin_assign();
+ return 0;
+ }
+ msm_fb_add_device(pdev);
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = toshiba_probe,
+ .driver = {
+ .name = "lcdc_toshiba_wvga",
+ },
+};
+
+static struct msm_fb_panel_data toshiba_panel_data = {
+ .on = lcdc_toshiba_panel_on,
+ .off = lcdc_toshiba_panel_off,
+ .set_backlight = lcdc_toshiba_set_backlight,
+};
+
+static struct platform_device this_device = {
+ .name = "lcdc_toshiba_wvga",
+ .id = 1,
+ .dev = {
+ .platform_data = &toshiba_panel_data,
+ }
+};
+
+static int __init lcdc_toshiba_panel_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+ if (mddi_get_client_id() != 0)
+ return 0;
+
+ ret = msm_fb_detect_client("lcdc_toshiba_wvga_pt");
+ if (ret)
+ return 0;
+
+#endif
+
+ ret = platform_driver_register(&this_driver);
+ if (ret)
+ return ret;
+
+ pinfo = &toshiba_panel_data.panel_info;
+ pinfo->xres = 480;
+ pinfo->yres = 800;
+ pinfo->type = LCDC_PANEL;
+ pinfo->pdest = DISPLAY_1;
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 18;
+ pinfo->fb_num = 2;
+ /* 30Mhz mdp_lcdc_pclk and mdp_lcdc_pad_pcl */
+ pinfo->clk_rate = 27648000;
+ pinfo->bl_max = 15;
+ pinfo->bl_min = 1;
+
+ pinfo->lcdc.h_back_porch = 184; /* hsw = 8 + hbp=184 */
+ pinfo->lcdc.h_front_porch = 4;
+ pinfo->lcdc.h_pulse_width = 8;
+ pinfo->lcdc.v_back_porch = 2; /* vsw=1 + vbp = 2 */
+ pinfo->lcdc.v_front_porch = 3;
+ pinfo->lcdc.v_pulse_width = 1;
+ pinfo->lcdc.border_clr = 0; /* blk */
+ pinfo->lcdc.underflow_clr = 0xff; /* blue */
+ pinfo->lcdc.hsync_skew = 0;
+
+ ret = platform_device_register(&this_device);
+ if (ret)
+ platform_driver_unregister(&this_driver);
+
+ return ret;
+}
+
+device_initcall(lcdc_toshiba_panel_init);
diff --git a/drivers/staging/msm/lcdc_wxga.c b/drivers/staging/msm/lcdc_wxga.c
new file mode 100644
index 0000000..202c92c
--- /dev/null
+++ b/drivers/staging/msm/lcdc_wxga.c
@@ -0,0 +1,56 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+
+static int __init lcdc_wxga_init(void)
+{
+ int ret;
+ struct msm_panel_info pinfo;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+ if (msm_fb_detect_client("lcdc_wxga"))
+ return 0;
+#endif
+
+ pinfo.xres = 1280;
+ pinfo.yres = 720;
+ pinfo.type = LCDC_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 24;
+ pinfo.fb_num = 2;
+ pinfo.clk_rate = 74250000;
+
+ pinfo.lcdc.h_back_porch = 124;
+ pinfo.lcdc.h_front_porch = 110;
+ pinfo.lcdc.h_pulse_width = 136;
+ pinfo.lcdc.v_back_porch = 19;
+ pinfo.lcdc.v_front_porch = 5;
+ pinfo.lcdc.v_pulse_width = 6;
+ pinfo.lcdc.border_clr = 0; /* blk */
+ pinfo.lcdc.underflow_clr = 0xff; /* blue */
+ pinfo.lcdc.hsync_skew = 0;
+
+ ret = lcdc_device_register(&pinfo);
+ if (ret)
+ printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(lcdc_wxga_init);
diff --git a/drivers/staging/msm/logo.c b/drivers/staging/msm/logo.c
new file mode 100644
index 0000000..7272765
--- /dev/null
+++ b/drivers/staging/msm/logo.c
@@ -0,0 +1,98 @@
+/* drivers/video/msm/logo.c
+ *
+ * Show Logo in RLE 565 format
+ *
+ * Copyright (C) 2008 Google Incorporated
+ *
+ * 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/module.h>
+#include <linux/types.h>
+#include <linux/fb.h>
+#include <linux/vt_kern.h>
+#include <linux/unistd.h>
+#include <linux/syscalls.h>
+
+#include <linux/irq.h>
+#include <asm/system.h>
+
+#define fb_width(fb) ((fb)->var.xres)
+#define fb_height(fb) ((fb)->var.yres)
+#define fb_size(fb) ((fb)->var.xres * (fb)->var.yres * 2)
+
+static void memset16(void *_ptr, unsigned short val, unsigned count)
+{
+ unsigned short *ptr = _ptr;
+ count >>= 1;
+ while (count--)
+ *ptr++ = val;
+}
+
+/* 565RLE image format: [count(2 bytes), rle(2 bytes)] */
+int load_565rle_image(char *filename)
+{
+ struct fb_info *info;
+ int fd, err = 0;
+ unsigned count, max;
+ unsigned short *data, *bits, *ptr;
+
+ info = registered_fb[0];
+ if (!info) {
+ printk(KERN_WARNING "%s: Can not access framebuffer\n",
+ __func__);
+ return -ENODEV;
+ }
+
+ fd = sys_open(filename, O_RDONLY, 0);
+ if (fd < 0) {
+ printk(KERN_WARNING "%s: Can not open %s\n",
+ __func__, filename);
+ return -ENOENT;
+ }
+ count = (unsigned)sys_lseek(fd, (off_t)0, 2);
+ if (count == 0) {
+ sys_close(fd);
+ err = -EIO;
+ goto err_logo_close_file;
+ }
+ sys_lseek(fd, (off_t)0, 0);
+ data = kmalloc(count, GFP_KERNEL);
+ if (!data) {
+ printk(KERN_WARNING "%s: Can not alloc data\n", __func__);
+ err = -ENOMEM;
+ goto err_logo_close_file;
+ }
+ if ((unsigned)sys_read(fd, (char *)data, count) != count) {
+ err = -EIO;
+ goto err_logo_free_data;
+ }
+
+ max = fb_width(info) * fb_height(info);
+ ptr = data;
+ bits = (unsigned short *)(info->screen_base);
+ while (count > 3) {
+ unsigned n = ptr[0];
+ if (n > max)
+ break;
+ memset16(bits, ptr[1], n << 1);
+ bits += n;
+ max -= n;
+ ptr += 2;
+ count -= 4;
+ }
+
+err_logo_free_data:
+ kfree(data);
+err_logo_close_file:
+ sys_close(fd);
+ return err;
+}
+EXPORT_SYMBOL(load_565rle_image);
diff --git a/drivers/staging/msm/mddi.c b/drivers/staging/msm/mddi.c
new file mode 100644
index 0000000..132eb1a
--- /dev/null
+++ b/drivers/staging/msm/mddi.c
@@ -0,0 +1,375 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <asm/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+#include "msm_fb.h"
+#include "mddihosti.h"
+#include "mddihost.h"
+#include <mach/gpio.h>
+#include <mach/clk.h>
+
+static int mddi_probe(struct platform_device *pdev);
+static int mddi_remove(struct platform_device *pdev);
+
+static int mddi_off(struct platform_device *pdev);
+static int mddi_on(struct platform_device *pdev);
+
+static int mddi_suspend(struct platform_device *pdev, pm_message_t state);
+static int mddi_resume(struct platform_device *pdev);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mddi_early_suspend(struct early_suspend *h);
+static void mddi_early_resume(struct early_suspend *h);
+#endif
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+static struct clk *mddi_clk;
+static struct clk *mddi_pclk;
+static struct mddi_platform_data *mddi_pdata;
+
+static struct platform_driver mddi_driver = {
+ .probe = mddi_probe,
+ .remove = mddi_remove,
+#ifndef CONFIG_HAS_EARLYSUSPEND
+#ifdef CONFIG_PM
+ .suspend = mddi_suspend,
+ .resume = mddi_resume,
+#endif
+#endif
+ .suspend_late = NULL,
+ .resume_early = NULL,
+ .shutdown = NULL,
+ .driver = {
+ .name = "mddi",
+ },
+};
+
+extern int int_mddi_pri_flag;
+
+static int mddi_off(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ ret = panel_next_off(pdev);
+
+ if (mddi_pdata && mddi_pdata->mddi_power_save)
+ mddi_pdata->mddi_power_save(0);
+
+ return ret;
+}
+
+static int mddi_on(struct platform_device *pdev)
+{
+ int ret = 0;
+ u32 clk_rate;
+ struct msm_fb_data_type *mfd;
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (mddi_pdata && mddi_pdata->mddi_power_save)
+ mddi_pdata->mddi_power_save(1);
+
+ clk_rate = mfd->fbi->var.pixclock;
+ clk_rate = min(clk_rate, mfd->panel_info.clk_max);
+
+ if (mddi_pdata &&
+ mddi_pdata->mddi_sel_clk &&
+ mddi_pdata->mddi_sel_clk(&clk_rate))
+ printk(KERN_ERR
+ "%s: can't select mddi io clk targate rate = %d\n",
+ __func__, clk_rate);
+
+ if (clk_set_min_rate(mddi_clk, clk_rate) < 0)
+ printk(KERN_ERR "%s: clk_set_min_rate failed\n",
+ __func__);
+
+ ret = panel_next_on(pdev);
+
+ return ret;
+}
+
+static int mddi_resource_initialized;
+
+static int mddi_probe(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ struct platform_device *mdp_dev = NULL;
+ struct msm_fb_panel_data *pdata = NULL;
+ int rc;
+ resource_size_t size ;
+ u32 clk_rate;
+
+ if ((pdev->id == 0) && (pdev->num_resources >= 0)) {
+ mddi_pdata = pdev->dev.platform_data;
+
+ size = resource_size(&pdev->resource[0]);
+ msm_pmdh_base = ioremap(pdev->resource[0].start, size);
+
+ MSM_FB_INFO("primary mddi base phy_addr = 0x%x virt = 0x%x\n",
+ pdev->resource[0].start, (int) msm_pmdh_base);
+
+ if (unlikely(!msm_pmdh_base))
+ return -ENOMEM;
+
+ if (mddi_pdata && mddi_pdata->mddi_power_save)
+ mddi_pdata->mddi_power_save(1);
+
+ mddi_resource_initialized = 1;
+ return 0;
+ }
+
+ if (!mddi_resource_initialized)
+ return -EPERM;
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+ return -ENOMEM;
+
+ mdp_dev = platform_device_alloc("mdp", pdev->id);
+ if (!mdp_dev)
+ return -ENOMEM;
+
+ /*
+ * link to the latest pdev
+ */
+ mfd->pdev = mdp_dev;
+ mfd->dest = DISPLAY_LCD;
+
+ /*
+ * alloc panel device data
+ */
+ if (platform_device_add_data
+ (mdp_dev, pdev->dev.platform_data,
+ sizeof(struct msm_fb_panel_data))) {
+ printk(KERN_ERR "mddi_probe: platform_device_add_data failed!\n");
+ platform_device_put(mdp_dev);
+ return -ENOMEM;
+ }
+ /*
+ * data chain
+ */
+ pdata = mdp_dev->dev.platform_data;
+ pdata->on = mddi_on;
+ pdata->off = mddi_off;
+ pdata->next = pdev;
+
+ /*
+ * get/set panel specific fb info
+ */
+ mfd->panel_info = pdata->panel_info;
+ mfd->fb_imgType = MDP_RGB_565;
+
+ clk_rate = mfd->panel_info.clk_max;
+ if (mddi_pdata &&
+ mddi_pdata->mddi_sel_clk &&
+ mddi_pdata->mddi_sel_clk(&clk_rate))
+ printk(KERN_ERR
+ "%s: can't select mddi io clk targate rate = %d\n",
+ __func__, clk_rate);
+
+ if (clk_set_max_rate(mddi_clk, clk_rate) < 0)
+ printk(KERN_ERR "%s: clk_set_max_rate failed\n", __func__);
+ mfd->panel_info.clk_rate = mfd->panel_info.clk_min;
+
+ /*
+ * set driver data
+ */
+ platform_set_drvdata(mdp_dev, mfd);
+
+ /*
+ * register in mdp driver
+ */
+ rc = platform_device_add(mdp_dev);
+ if (rc)
+ goto mddi_probe_err;
+
+ pdev_list[pdev_list_cnt++] = pdev;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ mfd->mddi_early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
+ mfd->mddi_early_suspend.suspend = mddi_early_suspend;
+ mfd->mddi_early_suspend.resume = mddi_early_resume;
+ register_early_suspend(&mfd->mddi_early_suspend);
+#endif
+
+ return 0;
+
+mddi_probe_err:
+ platform_device_put(mdp_dev);
+ return rc;
+}
+
+static int mddi_pad_ctrl;
+static int mddi_power_locked;
+static int mddi_is_in_suspend;
+
+void mddi_disable(int lock)
+{
+ mddi_host_type host_idx = MDDI_HOST_PRIM;
+
+ if (mddi_power_locked)
+ return;
+
+ if (lock)
+ mddi_power_locked = 1;
+
+ if (mddi_host_timer.function)
+ del_timer_sync(&mddi_host_timer);
+
+ mddi_pad_ctrl = mddi_host_reg_in(PAD_CTL);
+ mddi_host_reg_out(PAD_CTL, 0x0);
+
+ if (clk_set_min_rate(mddi_clk, 0) < 0)
+ printk(KERN_ERR "%s: clk_set_min_rate failed\n", __func__);
+
+ clk_disable(mddi_clk);
+ if (mddi_pclk)
+ clk_disable(mddi_pclk);
+ disable_irq(INT_MDDI_PRI);
+
+ if (mddi_pdata && mddi_pdata->mddi_power_save)
+ mddi_pdata->mddi_power_save(0);
+}
+
+static int mddi_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ if (mddi_is_in_suspend)
+ return 0;
+
+ mddi_is_in_suspend = 1;
+ mddi_disable(0);
+ return 0;
+}
+
+static int mddi_resume(struct platform_device *pdev)
+{
+ mddi_host_type host_idx = MDDI_HOST_PRIM;
+
+ if (!mddi_is_in_suspend)
+ return 0;
+
+ mddi_is_in_suspend = 0;
+
+ if (mddi_power_locked)
+ return 0;
+
+ enable_irq(INT_MDDI_PRI);
+ clk_enable(mddi_clk);
+ if (mddi_pclk)
+ clk_enable(mddi_pclk);
+ mddi_host_reg_out(PAD_CTL, mddi_pad_ctrl);
+
+ if (mddi_host_timer.function)
+ mddi_host_timer_service(0);
+
+ return 0;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mddi_early_suspend(struct early_suspend *h)
+{
+ pm_message_t state;
+ struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
+ mddi_early_suspend);
+
+ state.event = PM_EVENT_SUSPEND;
+ mddi_suspend(mfd->pdev, state);
+}
+
+static void mddi_early_resume(struct early_suspend *h)
+{
+ struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
+ mddi_early_suspend);
+ mddi_resume(mfd->pdev);
+}
+#endif
+
+static int mddi_remove(struct platform_device *pdev)
+{
+ if (mddi_host_timer.function)
+ del_timer_sync(&mddi_host_timer);
+
+ iounmap(msm_pmdh_base);
+
+ return 0;
+}
+
+static int mddi_register_driver(void)
+{
+ return platform_driver_register(&mddi_driver);
+}
+
+static int __init mddi_driver_init(void)
+{
+ int ret;
+
+ mddi_clk = clk_get(NULL, "mddi_clk");
+ if (IS_ERR(mddi_clk)) {
+ printk(KERN_ERR "can't find mddi_clk \n");
+ return PTR_ERR(mddi_clk);
+ }
+ clk_enable(mddi_clk);
+
+ mddi_pclk = clk_get(NULL, "mddi_pclk");
+ if (IS_ERR(mddi_pclk))
+ mddi_pclk = NULL;
+ else
+ clk_enable(mddi_pclk);
+
+ ret = mddi_register_driver();
+ if (ret) {
+ clk_disable(mddi_clk);
+ clk_put(mddi_clk);
+ if (mddi_pclk) {
+ clk_disable(mddi_pclk);
+ clk_put(mddi_pclk);
+ }
+ printk(KERN_ERR "mddi_register_driver() failed!\n");
+ return ret;
+ }
+
+ mddi_init();
+
+ return ret;
+}
+
+module_init(mddi_driver_init);
diff --git a/drivers/staging/msm/mddi_ext.c b/drivers/staging/msm/mddi_ext.c
new file mode 100644
index 0000000..c0c168c7
--- /dev/null
+++ b/drivers/staging/msm/mddi_ext.c
@@ -0,0 +1,320 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <asm/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+#include <mach/clk.h>
+#include <linux/platform_device.h>
+
+#include "msm_fb.h"
+#include "mddihosti.h"
+
+static int mddi_ext_probe(struct platform_device *pdev);
+static int mddi_ext_remove(struct platform_device *pdev);
+
+static int mddi_ext_off(struct platform_device *pdev);
+static int mddi_ext_on(struct platform_device *pdev);
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+
+static int mddi_ext_suspend(struct platform_device *pdev, pm_message_t state);
+static int mddi_ext_resume(struct platform_device *pdev);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mddi_ext_early_suspend(struct early_suspend *h);
+static void mddi_ext_early_resume(struct early_suspend *h);
+#endif
+
+static struct platform_driver mddi_ext_driver = {
+ .probe = mddi_ext_probe,
+ .remove = mddi_ext_remove,
+#ifndef CONFIG_HAS_EARLYSUSPEND
+#ifdef CONFIG_PM
+ .suspend = mddi_ext_suspend,
+ .resume = mddi_ext_resume,
+#endif
+#endif
+ .resume_early = NULL,
+ .resume = NULL,
+ .shutdown = NULL,
+ .driver = {
+ .name = "mddi_ext",
+ },
+};
+
+static struct clk *mddi_ext_clk;
+static struct mddi_platform_data *mddi_ext_pdata;
+
+extern int int_mddi_ext_flag;
+
+static int mddi_ext_off(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ ret = panel_next_off(pdev);
+ mddi_host_stop_ext_display();
+
+ return ret;
+}
+
+static int mddi_ext_on(struct platform_device *pdev)
+{
+ int ret = 0;
+ u32 clk_rate;
+ struct msm_fb_data_type *mfd;
+
+ mfd = platform_get_drvdata(pdev);
+
+ clk_rate = mfd->fbi->var.pixclock;
+ clk_rate = min(clk_rate, mfd->panel_info.clk_max);
+
+ if (mddi_ext_pdata &&
+ mddi_ext_pdata->mddi_sel_clk &&
+ mddi_ext_pdata->mddi_sel_clk(&clk_rate))
+ printk(KERN_ERR
+ "%s: can't select mddi io clk targate rate = %d\n",
+ __func__, clk_rate);
+
+ if (clk_set_min_rate(mddi_ext_clk, clk_rate) < 0)
+ printk(KERN_ERR "%s: clk_set_min_rate failed\n",
+ __func__);
+
+ mddi_host_start_ext_display();
+ ret = panel_next_on(pdev);
+
+ return ret;
+}
+
+static int mddi_ext_resource_initialized;
+
+static int mddi_ext_probe(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ struct platform_device *mdp_dev = NULL;
+ struct msm_fb_panel_data *pdata = NULL;
+ int rc;
+ resource_size_t size ;
+ u32 clk_rate;
+
+ if ((pdev->id == 0) && (pdev->num_resources >= 0)) {
+ mddi_ext_pdata = pdev->dev.platform_data;
+
+ size = resource_size(&pdev->resource[0]);
+ msm_emdh_base = ioremap(pdev->resource[0].start, size);
+
+ MSM_FB_INFO("external mddi base address = 0x%x\n",
+ pdev->resource[0].start);
+
+ if (unlikely(!msm_emdh_base))
+ return -ENOMEM;
+
+ mddi_ext_resource_initialized = 1;
+ return 0;
+ }
+
+ if (!mddi_ext_resource_initialized)
+ return -EPERM;
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+ return -ENOMEM;
+
+ mdp_dev = platform_device_alloc("mdp", pdev->id);
+ if (!mdp_dev)
+ return -ENOMEM;
+
+ /*
+ * link to the latest pdev
+ */
+ mfd->pdev = mdp_dev;
+ mfd->dest = DISPLAY_EXT_MDDI;
+
+ /*
+ * alloc panel device data
+ */
+ if (platform_device_add_data
+ (mdp_dev, pdev->dev.platform_data,
+ sizeof(struct msm_fb_panel_data))) {
+ printk(KERN_ERR "mddi_ext_probe: platform_device_add_data failed!\n");
+ platform_device_put(mdp_dev);
+ return -ENOMEM;
+ }
+ /*
+ * data chain
+ */
+ pdata = mdp_dev->dev.platform_data;
+ pdata->on = mddi_ext_on;
+ pdata->off = mddi_ext_off;
+ pdata->next = pdev;
+
+ /*
+ * get/set panel specific fb info
+ */
+ mfd->panel_info = pdata->panel_info;
+ mfd->fb_imgType = MDP_RGB_565;
+
+ clk_rate = mfd->panel_info.clk_max;
+ if (mddi_ext_pdata &&
+ mddi_ext_pdata->mddi_sel_clk &&
+ mddi_ext_pdata->mddi_sel_clk(&clk_rate))
+ printk(KERN_ERR
+ "%s: can't select mddi io clk targate rate = %d\n",
+ __func__, clk_rate);
+
+ if (clk_set_max_rate(mddi_ext_clk, clk_rate) < 0)
+ printk(KERN_ERR "%s: clk_set_max_rate failed\n", __func__);
+ mfd->panel_info.clk_rate = mfd->panel_info.clk_min;
+
+ /*
+ * set driver data
+ */
+ platform_set_drvdata(mdp_dev, mfd);
+
+ /*
+ * register in mdp driver
+ */
+ rc = platform_device_add(mdp_dev);
+ if (rc)
+ goto mddi_ext_probe_err;
+
+ pdev_list[pdev_list_cnt++] = pdev;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ mfd->mddi_ext_early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
+ mfd->mddi_ext_early_suspend.suspend = mddi_ext_early_suspend;
+ mfd->mddi_ext_early_suspend.resume = mddi_ext_early_resume;
+ register_early_suspend(&mfd->mddi_ext_early_suspend);
+#endif
+
+ return 0;
+
+mddi_ext_probe_err:
+ platform_device_put(mdp_dev);
+ return rc;
+}
+
+static int mddi_ext_is_in_suspend;
+
+static int mddi_ext_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ if (mddi_ext_is_in_suspend)
+ return 0;
+
+ mddi_ext_is_in_suspend = 1;
+
+ if (clk_set_min_rate(mddi_ext_clk, 0) < 0)
+ printk(KERN_ERR "%s: clk_set_min_rate failed\n", __func__);
+
+ clk_disable(mddi_ext_clk);
+ disable_irq(INT_MDDI_EXT);
+
+ return 0;
+}
+
+static int mddi_ext_resume(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mddi_ext_is_in_suspend)
+ return 0;
+
+ mddi_ext_is_in_suspend = 0;
+ enable_irq(INT_MDDI_EXT);
+
+ clk_enable(mddi_ext_clk);
+
+ return 0;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mddi_ext_early_suspend(struct early_suspend *h)
+{
+ pm_message_t state;
+ struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
+ mddi_ext_early_suspend);
+
+ state.event = PM_EVENT_SUSPEND;
+ mddi_ext_suspend(mfd->pdev, state);
+}
+
+static void mddi_ext_early_resume(struct early_suspend *h)
+{
+ struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
+ mddi_ext_early_suspend);
+ mddi_ext_resume(mfd->pdev);
+}
+#endif
+
+static int mddi_ext_remove(struct platform_device *pdev)
+{
+ iounmap(msm_emdh_base);
+ return 0;
+}
+
+static int mddi_ext_register_driver(void)
+{
+ return platform_driver_register(&mddi_ext_driver);
+}
+
+static int __init mddi_ext_driver_init(void)
+{
+ int ret;
+
+ mddi_ext_clk = clk_get(NULL, "emdh_clk");
+ if (IS_ERR(mddi_ext_clk)) {
+ printk(KERN_ERR "can't find emdh_clk\n");
+ return PTR_ERR(mddi_ext_clk);
+ }
+ clk_enable(mddi_ext_clk);
+
+ ret = mddi_ext_register_driver();
+ if (ret) {
+ clk_disable(mddi_ext_clk);
+ clk_put(mddi_ext_clk);
+ printk(KERN_ERR "mddi_ext_register_driver() failed!\n");
+ return ret;
+ }
+ mddi_init();
+
+ return ret;
+}
+
+module_init(mddi_ext_driver_init);
diff --git a/drivers/staging/msm/mddi_ext_lcd.c b/drivers/staging/msm/mddi_ext_lcd.c
new file mode 100644
index 0000000..502e80d
--- /dev/null
+++ b/drivers/staging/msm/mddi_ext_lcd.c
@@ -0,0 +1,91 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+static int mddi_ext_lcd_on(struct platform_device *pdev);
+static int mddi_ext_lcd_off(struct platform_device *pdev);
+
+static int mddi_ext_lcd_on(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static int mddi_ext_lcd_off(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static int __init mddi_ext_lcd_probe(struct platform_device *pdev)
+{
+ msm_fb_add_device(pdev);
+
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = mddi_ext_lcd_probe,
+ .driver = {
+ .name = "extmddi_svga",
+ },
+};
+
+static struct msm_fb_panel_data mddi_ext_lcd_panel_data = {
+ .panel_info.xres = 800,
+ .panel_info.yres = 600,
+ .panel_info.type = EXT_MDDI_PANEL,
+ .panel_info.pdest = DISPLAY_1,
+ .panel_info.wait_cycle = 0,
+ .panel_info.bpp = 18,
+ .panel_info.fb_num = 2,
+ .panel_info.clk_rate = 122880000,
+ .panel_info.clk_min = 120000000,
+ .panel_info.clk_max = 125000000,
+ .on = mddi_ext_lcd_on,
+ .off = mddi_ext_lcd_off,
+};
+
+static struct platform_device this_device = {
+ .name = "extmddi_svga",
+ .id = 0,
+ .dev = {
+ .platform_data = &mddi_ext_lcd_panel_data,
+ }
+};
+
+static int __init mddi_ext_lcd_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+
+ ret = platform_driver_register(&this_driver);
+ if (!ret) {
+ pinfo = &mddi_ext_lcd_panel_data.panel_info;
+ pinfo->lcd.vsync_enable = FALSE;
+ pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+
+ ret = platform_device_register(&this_device);
+ if (ret)
+ platform_driver_unregister(&this_driver);
+ }
+
+ return ret;
+}
+
+module_init(mddi_ext_lcd_init);
diff --git a/drivers/staging/msm/mddi_prism.c b/drivers/staging/msm/mddi_prism.c
new file mode 100644
index 0000000..489d404
--- /dev/null
+++ b/drivers/staging/msm/mddi_prism.c
@@ -0,0 +1,114 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+static int prism_lcd_on(struct platform_device *pdev);
+static int prism_lcd_off(struct platform_device *pdev);
+
+static int prism_lcd_on(struct platform_device *pdev)
+{
+ /* Set the MDP pixel data attributes for Primary Display */
+ mddi_host_write_pix_attr_reg(0x00C3);
+
+ return 0;
+}
+
+static int prism_lcd_off(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static int __init prism_probe(struct platform_device *pdev)
+{
+ msm_fb_add_device(pdev);
+
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = prism_probe,
+ .driver = {
+ .name = "mddi_prism_wvga",
+ },
+};
+
+static struct msm_fb_panel_data prism_panel_data = {
+ .on = prism_lcd_on,
+ .off = prism_lcd_off,
+};
+
+static struct platform_device this_device = {
+ .name = "mddi_prism_wvga",
+ .id = 0,
+ .dev = {
+ .platform_data = &prism_panel_data,
+ }
+};
+
+static int __init prism_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+ u32 id;
+
+ ret = msm_fb_detect_client("mddi_prism_wvga");
+ if (ret == -ENODEV)
+ return 0;
+
+ if (ret) {
+ id = mddi_get_client_id();
+
+ if (((id >> 16) != 0x4474) || ((id & 0xffff) == 0x8960))
+ return 0;
+ }
+#endif
+ ret = platform_driver_register(&this_driver);
+ if (!ret) {
+ pinfo = &prism_panel_data.panel_info;
+ pinfo->xres = 800;
+ pinfo->yres = 480;
+ pinfo->type = MDDI_PANEL;
+ pinfo->pdest = DISPLAY_1;
+ pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 18;
+ pinfo->fb_num = 2;
+ pinfo->clk_rate = 153600000;
+ pinfo->clk_min = 150000000;
+ pinfo->clk_max = 160000000;
+ pinfo->lcd.vsync_enable = TRUE;
+ pinfo->lcd.refx100 = 6050;
+ pinfo->lcd.v_back_porch = 23;
+ pinfo->lcd.v_front_porch = 20;
+ pinfo->lcd.v_pulse_width = 105;
+ pinfo->lcd.hw_vsync_mode = TRUE;
+ pinfo->lcd.vsync_notifier_period = 0;
+
+ ret = platform_device_register(&this_device);
+ if (ret)
+ platform_driver_unregister(&this_driver);
+ }
+
+ return ret;
+}
+
+module_init(prism_init);
diff --git a/drivers/staging/msm/mddi_sharp.c b/drivers/staging/msm/mddi_sharp.c
new file mode 100644
index 0000000..1da1be4
--- /dev/null
+++ b/drivers/staging/msm/mddi_sharp.c
@@ -0,0 +1,892 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+#define SHARP_QVGA_PRIM 1
+#define SHARP_128X128_SECD 2
+
+extern uint32 mddi_host_core_version;
+static boolean mddi_debug_prim_wait = FALSE;
+static boolean mddi_sharp_vsync_wake = TRUE;
+static boolean mddi_sharp_monitor_refresh_value = TRUE;
+static boolean mddi_sharp_report_refresh_measurements = FALSE;
+static uint32 mddi_sharp_rows_per_second = 13830; /* 5200000/376 */
+static uint32 mddi_sharp_rows_per_refresh = 338;
+static uint32 mddi_sharp_usecs_per_refresh = 24440; /* (376+338)/5200000 */
+static boolean mddi_sharp_debug_60hz_refresh = FALSE;
+
+extern mddi_gpio_info_type mddi_gpio;
+extern boolean mddi_vsync_detect_enabled;
+static msm_fb_vsync_handler_type mddi_sharp_vsync_handler;
+static void *mddi_sharp_vsync_handler_arg;
+static uint16 mddi_sharp_vsync_attempts;
+
+static void mddi_sharp_prim_lcd_init(void);
+static void mddi_sharp_sub_lcd_init(void);
+static void mddi_sharp_lcd_set_backlight(struct msm_fb_data_type *mfd);
+static void mddi_sharp_vsync_set_handler(msm_fb_vsync_handler_type handler,
+ void *);
+static void mddi_sharp_lcd_vsync_detected(boolean detected);
+static struct msm_panel_common_pdata *mddi_sharp_pdata;
+
+#define REG_SYSCTL 0x0000
+#define REG_INTR 0x0006
+#define REG_CLKCNF 0x000C
+#define REG_CLKDIV1 0x000E
+#define REG_CLKDIV2 0x0010
+
+#define REG_GIOD 0x0040
+#define REG_GIOA 0x0042
+
+#define REG_AGM 0x010A
+#define REG_FLFT 0x0110
+#define REG_FRGT 0x0112
+#define REG_FTOP 0x0114
+#define REG_FBTM 0x0116
+#define REG_FSTRX 0x0118
+#define REG_FSTRY 0x011A
+#define REG_VRAM 0x0202
+#define REG_SSDCTL 0x0330
+#define REG_SSD0 0x0332
+#define REG_PSTCTL1 0x0400
+#define REG_PSTCTL2 0x0402
+#define REG_PTGCTL 0x042A
+#define REG_PTHP 0x042C
+#define REG_PTHB 0x042E
+#define REG_PTHW 0x0430
+#define REG_PTHF 0x0432
+#define REG_PTVP 0x0434
+#define REG_PTVB 0x0436
+#define REG_PTVW 0x0438
+#define REG_PTVF 0x043A
+#define REG_VBLKS 0x0458
+#define REG_VBLKE 0x045A
+#define REG_SUBCTL 0x0700
+#define REG_SUBTCMD 0x0702
+#define REG_SUBTCMDD 0x0704
+#define REG_REVBYTE 0x0A02
+#define REG_REVCNT 0x0A04
+#define REG_REVATTR 0x0A06
+#define REG_REVFMT 0x0A08
+
+#define SHARP_SUB_UNKNOWN 0xffffffff
+#define SHARP_SUB_HYNIX 1
+#define SHARP_SUB_ROHM 2
+
+static uint32 sharp_subpanel_type = SHARP_SUB_UNKNOWN;
+
+static void sub_through_write(int sub_rs, uint32 sub_data)
+{
+ mddi_queue_register_write(REG_SUBTCMDD, sub_data, FALSE, 0);
+
+ /* CS=1,RD=1,WE=1,RS=sub_rs */
+ mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, FALSE, 0);
+
+ /* CS=0,RD=1,WE=1,RS=sub_rs */
+ mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
+
+ /* CS=0,RD=1,WE=0,RS=sub_rs */
+ mddi_queue_register_write(REG_SUBTCMD, 0x0004 | sub_rs, FALSE, 0);
+
+ /* CS=0,RD=1,WE=1,RS=sub_rs */
+ mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
+
+ /* CS=1,RD=1,WE=1,RS=sub_rs */
+ mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, TRUE, 0);
+}
+
+static uint32 sub_through_read(int sub_rs)
+{
+ uint32 sub_data;
+
+ /* CS=1,RD=1,WE=1,RS=sub_rs */
+ mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, FALSE, 0);
+
+ /* CS=0,RD=1,WE=1,RS=sub_rs */
+ mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
+
+ /* CS=0,RD=1,WE=0,RS=sub_rs */
+ mddi_queue_register_write(REG_SUBTCMD, 0x0002 | sub_rs, TRUE, 0);
+
+ mddi_queue_register_read(REG_SUBTCMDD, &sub_data, TRUE, 0);
+
+ /* CS=0,RD=1,WE=1,RS=sub_rs */
+ mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
+
+ /* CS=1,RD=1,WE=1,RS=sub_rs */
+ mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, TRUE, 0);
+
+ return sub_data;
+}
+
+static void serigo(uint32 ssd)
+{
+ uint32 ssdctl;
+
+ mddi_queue_register_read(REG_SSDCTL, &ssdctl, TRUE, 0);
+ ssdctl = ((ssdctl & 0xE7) | 0x02);
+
+ mddi_queue_register_write(REG_SSD0, ssd, FALSE, 0);
+ mddi_queue_register_write(REG_SSDCTL, ssdctl, TRUE, 0);
+
+ do {
+ mddi_queue_register_read(REG_SSDCTL, &ssdctl, TRUE, 0);
+ } while ((ssdctl & 0x0002) != 0);
+
+ if (mddi_debug_prim_wait)
+ mddi_wait(2);
+}
+
+static void mddi_sharp_lcd_powerdown(void)
+{
+ serigo(0x0131);
+ serigo(0x0300);
+ mddi_wait(40);
+ serigo(0x0135);
+ mddi_wait(20);
+ serigo(0x2122);
+ mddi_wait(20);
+ serigo(0x0201);
+ mddi_wait(20);
+ serigo(0x2100);
+ mddi_wait(20);
+ serigo(0x2000);
+ mddi_wait(20);
+
+ mddi_queue_register_write(REG_PSTCTL1, 0x1, TRUE, 0);
+ mddi_wait(100);
+ mddi_queue_register_write(REG_PSTCTL1, 0x0, TRUE, 0);
+ mddi_wait(2);
+ mddi_queue_register_write(REG_SYSCTL, 0x1, TRUE, 0);
+ mddi_wait(2);
+ mddi_queue_register_write(REG_CLKDIV1, 0x3, TRUE, 0);
+ mddi_wait(2);
+ mddi_queue_register_write(REG_SSDCTL, 0x0000, TRUE, 0); /* SSDRESET */
+ mddi_queue_register_write(REG_SYSCTL, 0x0, TRUE, 0);
+ mddi_wait(2);
+}
+
+static void mddi_sharp_lcd_set_backlight(struct msm_fb_data_type *mfd)
+{
+ uint32 regdata;
+ int32 level;
+ int max = mfd->panel_info.bl_max;
+ int min = mfd->panel_info.bl_min;
+
+ if (mddi_sharp_pdata && mddi_sharp_pdata->backlight_level) {
+ level = mddi_sharp_pdata->backlight_level(mfd->bl_level,
+ max,
+ min);
+
+ if (level < 0)
+ return;
+
+ /* use Rodem GPIO(2:0) to give 8 levels of backlight (7-0) */
+ /* Set lower 3 GPIOs as Outputs (set to 0) */
+ mddi_queue_register_read(REG_GIOA, ®data, TRUE, 0);
+ mddi_queue_register_write(REG_GIOA, regdata & 0xfff8, TRUE, 0);
+
+ /* Set lower 3 GPIOs as level */
+ mddi_queue_register_read(REG_GIOD, ®data, TRUE, 0);
+ mddi_queue_register_write(REG_GIOD,
+ (regdata & 0xfff8) | (0x07 & level), TRUE, 0);
+ }
+}
+
+static void mddi_sharp_prim_lcd_init(void)
+{
+ mddi_queue_register_write(REG_SYSCTL, 0x4000, TRUE, 0);
+ mddi_wait(1);
+ mddi_queue_register_write(REG_SYSCTL, 0x0000, TRUE, 0);
+ mddi_wait(5);
+ mddi_queue_register_write(REG_SYSCTL, 0x0001, FALSE, 0);
+ mddi_queue_register_write(REG_CLKDIV1, 0x000b, FALSE, 0);
+
+ /* new reg write below */
+ if (mddi_sharp_debug_60hz_refresh)
+ mddi_queue_register_write(REG_CLKCNF, 0x070d, FALSE, 0);
+ else
+ mddi_queue_register_write(REG_CLKCNF, 0x0708, FALSE, 0);
+
+ mddi_queue_register_write(REG_SYSCTL, 0x0201, FALSE, 0);
+ mddi_queue_register_write(REG_PTGCTL, 0x0010, FALSE, 0);
+ mddi_queue_register_write(REG_PTHP, 4, FALSE, 0);
+ mddi_queue_register_write(REG_PTHB, 40, FALSE, 0);
+ mddi_queue_register_write(REG_PTHW, 240, FALSE, 0);
+ if (mddi_sharp_debug_60hz_refresh)
+ mddi_queue_register_write(REG_PTHF, 12, FALSE, 0);
+ else
+ mddi_queue_register_write(REG_PTHF, 92, FALSE, 0);
+
+ mddi_wait(1);
+
+ mddi_queue_register_write(REG_PTVP, 1, FALSE, 0);
+ mddi_queue_register_write(REG_PTVB, 2, FALSE, 0);
+ mddi_queue_register_write(REG_PTVW, 320, FALSE, 0);
+ mddi_queue_register_write(REG_PTVF, 15, FALSE, 0);
+
+ mddi_wait(1);
+
+ /* vram_color set REG_AGM???? */
+ mddi_queue_register_write(REG_AGM, 0x0000, TRUE, 0);
+
+ mddi_queue_register_write(REG_SSDCTL, 0x0000, FALSE, 0);
+ mddi_queue_register_write(REG_SSDCTL, 0x0001, TRUE, 0);
+ mddi_wait(1);
+ mddi_queue_register_write(REG_PSTCTL1, 0x0001, TRUE, 0);
+ mddi_wait(10);
+
+ serigo(0x0701);
+ /* software reset */
+ mddi_wait(1);
+ /* Wait over 50us */
+
+ serigo(0x0400);
+ /* DCLK~ACHSYNC~ACVSYNC polarity setting */
+ serigo(0x2900);
+ /* EEPROM start read address setting */
+ serigo(0x2606);
+ /* EEPROM start read register setting */
+ mddi_wait(20);
+ /* Wait over 20ms */
+
+ serigo(0x0503);
+ /* Horizontal timing setting */
+ serigo(0x062C);
+ /* Veritical timing setting */
+ serigo(0x2001);
+ /* power initialize setting(VDC2) */
+ mddi_wait(20);
+ /* Wait over 20ms */
+
+ serigo(0x2120);
+ /* Initialize power setting(CPS) */
+ mddi_wait(20);
+ /* Wait over 20ms */
+
+ serigo(0x2130);
+ /* Initialize power setting(CPS) */
+ mddi_wait(20);
+ /* Wait over 20ms */
+
+ serigo(0x2132);
+ /* Initialize power setting(CPS) */
+ mddi_wait(10);
+ /* Wait over 10ms */
+
+ serigo(0x2133);
+ /* Initialize power setting(CPS) */
+ mddi_wait(20);
+ /* Wait over 20ms */
+
+ serigo(0x0200);
+ /* Panel initialize release(INIT) */
+ mddi_wait(1);
+ /* Wait over 1ms */
+
+ serigo(0x0131);
+ /* Panel setting(CPS) */
+ mddi_wait(1);
+ /* Wait over 1ms */
+
+ mddi_queue_register_write(REG_PSTCTL1, 0x0003, TRUE, 0);
+
+ /* if (FFA LCD is upside down) -> serigo(0x0100); */
+ serigo(0x0130);
+
+ /* Black mask release(display ON) */
+ mddi_wait(1);
+ /* Wait over 1ms */
+
+ if (mddi_sharp_vsync_wake) {
+ mddi_queue_register_write(REG_VBLKS, 0x1001, TRUE, 0);
+ mddi_queue_register_write(REG_VBLKE, 0x1002, TRUE, 0);
+ }
+
+ /* Set the MDP pixel data attributes for Primary Display */
+ mddi_host_write_pix_attr_reg(0x00C3);
+ return;
+
+}
+
+void mddi_sharp_sub_lcd_init(void)
+{
+
+ mddi_queue_register_write(REG_SYSCTL, 0x4000, FALSE, 0);
+ mddi_queue_register_write(REG_SYSCTL, 0x0000, TRUE, 0);
+ mddi_wait(100);
+
+ mddi_queue_register_write(REG_SYSCTL, 0x0001, FALSE, 0);
+ mddi_queue_register_write(REG_CLKDIV1, 0x000b, FALSE, 0);
+ mddi_queue_register_write(REG_CLKCNF, 0x0708, FALSE, 0);
+ mddi_queue_register_write(REG_SYSCTL, 0x0201, FALSE, 0);
+ mddi_queue_register_write(REG_PTGCTL, 0x0010, FALSE, 0);
+ mddi_queue_register_write(REG_PTHP, 4, FALSE, 0);
+ mddi_queue_register_write(REG_PTHB, 40, FALSE, 0);
+ mddi_queue_register_write(REG_PTHW, 128, FALSE, 0);
+ mddi_queue_register_write(REG_PTHF, 92, FALSE, 0);
+ mddi_queue_register_write(REG_PTVP, 1, FALSE, 0);
+ mddi_queue_register_write(REG_PTVB, 2, FALSE, 0);
+ mddi_queue_register_write(REG_PTVW, 128, FALSE, 0);
+ mddi_queue_register_write(REG_PTVF, 15, FALSE, 0);
+
+ /* Now the sub display..... */
+ /* Reset High */
+ mddi_queue_register_write(REG_SUBCTL, 0x0200, FALSE, 0);
+ /* CS=1,RD=1,WE=1,RS=1 */
+ mddi_queue_register_write(REG_SUBTCMD, 0x000f, TRUE, 0);
+ mddi_wait(1);
+ /* Wait 5us */
+
+ if (sharp_subpanel_type == SHARP_SUB_UNKNOWN) {
+ uint32 data;
+
+ sub_through_write(1, 0x05);
+ sub_through_write(1, 0x6A);
+ sub_through_write(1, 0x1D);
+ sub_through_write(1, 0x05);
+ data = sub_through_read(1);
+ if (data == 0x6A) {
+ sharp_subpanel_type = SHARP_SUB_HYNIX;
+ } else {
+ sub_through_write(0, 0x36);
+ sub_through_write(1, 0xA8);
+ sub_through_write(0, 0x09);
+ data = sub_through_read(1);
+ data = sub_through_read(1);
+ if (data == 0x54) {
+ sub_through_write(0, 0x36);
+ sub_through_write(1, 0x00);
+ sharp_subpanel_type = SHARP_SUB_ROHM;
+ }
+ }
+ }
+
+ if (sharp_subpanel_type == SHARP_SUB_HYNIX) {
+ sub_through_write(1, 0x00); /* Display setting 1 */
+ sub_through_write(1, 0x04);
+ sub_through_write(1, 0x01);
+ sub_through_write(1, 0x05);
+ sub_through_write(1, 0x0280);
+ sub_through_write(1, 0x0301);
+ sub_through_write(1, 0x0402);
+ sub_through_write(1, 0x0500);
+ sub_through_write(1, 0x0681);
+ sub_through_write(1, 0x077F);
+ sub_through_write(1, 0x08C0);
+ sub_through_write(1, 0x0905);
+ sub_through_write(1, 0x0A02);
+ sub_through_write(1, 0x0B00);
+ sub_through_write(1, 0x0C00);
+ sub_through_write(1, 0x0D00);
+ sub_through_write(1, 0x0E00);
+ sub_through_write(1, 0x0F00);
+
+ sub_through_write(1, 0x100B); /* Display setting 2 */
+ sub_through_write(1, 0x1103);
+ sub_through_write(1, 0x1237);
+ sub_through_write(1, 0x1300);
+ sub_through_write(1, 0x1400);
+ sub_through_write(1, 0x1500);
+ sub_through_write(1, 0x1605);
+ sub_through_write(1, 0x1700);
+ sub_through_write(1, 0x1800);
+ sub_through_write(1, 0x192E);
+ sub_through_write(1, 0x1A00);
+ sub_through_write(1, 0x1B00);
+ sub_through_write(1, 0x1C00);
+
+ sub_through_write(1, 0x151A); /* Power setting */
+
+ sub_through_write(1, 0x2002); /* Gradation Palette setting */
+ sub_through_write(1, 0x2107);
+ sub_through_write(1, 0x220C);
+ sub_through_write(1, 0x2310);
+ sub_through_write(1, 0x2414);
+ sub_through_write(1, 0x2518);
+ sub_through_write(1, 0x261C);
+ sub_through_write(1, 0x2720);
+ sub_through_write(1, 0x2824);
+ sub_through_write(1, 0x2928);
+ sub_through_write(1, 0x2A2B);
+ sub_through_write(1, 0x2B2E);
+ sub_through_write(1, 0x2C31);
+ sub_through_write(1, 0x2D34);
+ sub_through_write(1, 0x2E37);
+ sub_through_write(1, 0x2F3A);
+ sub_through_write(1, 0x303C);
+ sub_through_write(1, 0x313E);
+ sub_through_write(1, 0x323F);
+ sub_through_write(1, 0x3340);
+ sub_through_write(1, 0x3441);
+ sub_through_write(1, 0x3543);
+ sub_through_write(1, 0x3646);
+ sub_through_write(1, 0x3749);
+ sub_through_write(1, 0x384C);
+ sub_through_write(1, 0x394F);
+ sub_through_write(1, 0x3A52);
+ sub_through_write(1, 0x3B59);
+ sub_through_write(1, 0x3C60);
+ sub_through_write(1, 0x3D67);
+ sub_through_write(1, 0x3E6E);
+ sub_through_write(1, 0x3F7F);
+ sub_through_write(1, 0x4001);
+ sub_through_write(1, 0x4107);
+ sub_through_write(1, 0x420C);
+ sub_through_write(1, 0x4310);
+ sub_through_write(1, 0x4414);
+ sub_through_write(1, 0x4518);
+ sub_through_write(1, 0x461C);
+ sub_through_write(1, 0x4720);
+ sub_through_write(1, 0x4824);
+ sub_through_write(1, 0x4928);
+ sub_through_write(1, 0x4A2B);
+ sub_through_write(1, 0x4B2E);
+ sub_through_write(1, 0x4C31);
+ sub_through_write(1, 0x4D34);
+ sub_through_write(1, 0x4E37);
+ sub_through_write(1, 0x4F3A);
+ sub_through_write(1, 0x503C);
+ sub_through_write(1, 0x513E);
+ sub_through_write(1, 0x523F);
+ sub_through_write(1, 0x5340);
+ sub_through_write(1, 0x5441);
+ sub_through_write(1, 0x5543);
+ sub_through_write(1, 0x5646);
+ sub_through_write(1, 0x5749);
+ sub_through_write(1, 0x584C);
+ sub_through_write(1, 0x594F);
+ sub_through_write(1, 0x5A52);
+ sub_through_write(1, 0x5B59);
+ sub_through_write(1, 0x5C60);
+ sub_through_write(1, 0x5D67);
+ sub_through_write(1, 0x5E6E);
+ sub_through_write(1, 0x5F7E);
+ sub_through_write(1, 0x6000);
+ sub_through_write(1, 0x6107);
+ sub_through_write(1, 0x620C);
+ sub_through_write(1, 0x6310);
+ sub_through_write(1, 0x6414);
+ sub_through_write(1, 0x6518);
+ sub_through_write(1, 0x661C);
+ sub_through_write(1, 0x6720);
+ sub_through_write(1, 0x6824);
+ sub_through_write(1, 0x6928);
+ sub_through_write(1, 0x6A2B);
+ sub_through_write(1, 0x6B2E);
+ sub_through_write(1, 0x6C31);
+ sub_through_write(1, 0x6D34);
+ sub_through_write(1, 0x6E37);
+ sub_through_write(1, 0x6F3A);
+ sub_through_write(1, 0x703C);
+ sub_through_write(1, 0x713E);
+ sub_through_write(1, 0x723F);
+ sub_through_write(1, 0x7340);
+ sub_through_write(1, 0x7441);
+ sub_through_write(1, 0x7543);
+ sub_through_write(1, 0x7646);
+ sub_through_write(1, 0x7749);
+ sub_through_write(1, 0x784C);
+ sub_through_write(1, 0x794F);
+ sub_through_write(1, 0x7A52);
+ sub_through_write(1, 0x7B59);
+ sub_through_write(1, 0x7C60);
+ sub_through_write(1, 0x7D67);
+ sub_through_write(1, 0x7E6E);
+ sub_through_write(1, 0x7F7D);
+
+ sub_through_write(1, 0x1851); /* Display on */
+
+ mddi_queue_register_write(REG_AGM, 0x0000, TRUE, 0);
+
+ /* 1 pixel / 1 post clock */
+ mddi_queue_register_write(REG_CLKDIV2, 0x3b00, FALSE, 0);
+
+ /* SUB LCD select */
+ mddi_queue_register_write(REG_PSTCTL2, 0x0080, FALSE, 0);
+
+ /* RS=0,command initiate number=0,select master mode */
+ mddi_queue_register_write(REG_SUBCTL, 0x0202, FALSE, 0);
+
+ /* Sub LCD Data transform start */
+ mddi_queue_register_write(REG_PSTCTL1, 0x0003, FALSE, 0);
+
+ } else if (sharp_subpanel_type == SHARP_SUB_ROHM) {
+
+ sub_through_write(0, 0x01); /* Display setting */
+ sub_through_write(1, 0x00);
+
+ mddi_wait(1);
+ /* Wait 100us <----- ******* Update 2005/01/24 */
+
+ sub_through_write(0, 0xB6);
+ sub_through_write(1, 0x0C);
+ sub_through_write(1, 0x4A);
+ sub_through_write(1, 0x20);
+ sub_through_write(0, 0x3A);
+ sub_through_write(1, 0x05);
+ sub_through_write(0, 0xB7);
+ sub_through_write(1, 0x01);
+ sub_through_write(0, 0xBA);
+ sub_through_write(1, 0x20);
+ sub_through_write(1, 0x02);
+ sub_through_write(0, 0x25);
+ sub_through_write(1, 0x4F);
+ sub_through_write(0, 0xBB);
+ sub_through_write(1, 0x00);
+ sub_through_write(0, 0x36);
+ sub_through_write(1, 0x00);
+ sub_through_write(0, 0xB1);
+ sub_through_write(1, 0x05);
+ sub_through_write(0, 0xBE);
+ sub_through_write(1, 0x80);
+ sub_through_write(0, 0x26);
+ sub_through_write(1, 0x01);
+ sub_through_write(0, 0x2A);
+ sub_through_write(1, 0x02);
+ sub_through_write(1, 0x81);
+ sub_through_write(0, 0x2B);
+ sub_through_write(1, 0x00);
+ sub_through_write(1, 0x7F);
+
+ sub_through_write(0, 0x2C);
+ sub_through_write(0, 0x11); /* Sleep mode off */
+
+ mddi_wait(1);
+ /* Wait 100 ms <----- ******* Update 2005/01/24 */
+
+ sub_through_write(0, 0x29); /* Display on */
+ sub_through_write(0, 0xB3);
+ sub_through_write(1, 0x20);
+ sub_through_write(1, 0xAA);
+ sub_through_write(1, 0xA0);
+ sub_through_write(1, 0x20);
+ sub_through_write(1, 0x30);
+ sub_through_write(1, 0xA6);
+ sub_through_write(1, 0xFF);
+ sub_through_write(1, 0x9A);
+ sub_through_write(1, 0x9F);
+ sub_through_write(1, 0xAF);
+ sub_through_write(1, 0xBC);
+ sub_through_write(1, 0xCF);
+ sub_through_write(1, 0xDF);
+ sub_through_write(1, 0x20);
+ sub_through_write(1, 0x9C);
+ sub_through_write(1, 0x8A);
+
+ sub_through_write(0, 0x002C); /* Display on */
+
+ /* 1 pixel / 2 post clock */
+ mddi_queue_register_write(REG_CLKDIV2, 0x7b00, FALSE, 0);
+
+ /* SUB LCD select */
+ mddi_queue_register_write(REG_PSTCTL2, 0x0080, FALSE, 0);
+
+ /* RS=1,command initiate number=0,select master mode */
+ mddi_queue_register_write(REG_SUBCTL, 0x0242, FALSE, 0);
+
+ /* Sub LCD Data transform start */
+ mddi_queue_register_write(REG_PSTCTL1, 0x0003, FALSE, 0);
+
+ }
+
+ /* Set the MDP pixel data attributes for Sub Display */
+ mddi_host_write_pix_attr_reg(0x00C0);
+}
+
+void mddi_sharp_lcd_vsync_detected(boolean detected)
+{
+ /* static timetick_type start_time = 0; */
+ static struct timeval start_time;
+ static boolean first_time = TRUE;
+ /* uint32 mdp_cnt_val = 0; */
+ /* timetick_type elapsed_us; */
+ struct timeval now;
+ uint32 elapsed_us;
+ uint32 num_vsyncs;
+
+ if ((detected) || (mddi_sharp_vsync_attempts > 5)) {
+ if ((detected) && (mddi_sharp_monitor_refresh_value)) {
+ /* if (start_time != 0) */
+ if (!first_time) {
+ jiffies_to_timeval(jiffies, &now);
+ elapsed_us =
+ (now.tv_sec - start_time.tv_sec) * 1000000 +
+ now.tv_usec - start_time.tv_usec;
+ /*
+ * LCD is configured for a refresh every usecs,
+ * so to determine the number of vsyncs that
+ * have occurred since the last measurement add
+ * half that to the time difference and divide
+ * by the refresh rate.
+ */
+ num_vsyncs = (elapsed_us +
+ (mddi_sharp_usecs_per_refresh >>
+ 1)) /
+ mddi_sharp_usecs_per_refresh;
+ /*
+ * LCD is configured for * hsyncs (rows) per
+ * refresh cycle. Calculate new rows_per_second
+ * value based upon these new measurements.
+ * MDP can update with this new value.
+ */
+ mddi_sharp_rows_per_second =
+ (mddi_sharp_rows_per_refresh * 1000 *
+ num_vsyncs) / (elapsed_us / 1000);
+ }
+ /* start_time = timetick_get(); */
+ first_time = FALSE;
+ jiffies_to_timeval(jiffies, &start_time);
+ if (mddi_sharp_report_refresh_measurements) {
+ /* mdp_cnt_val = MDP_LINE_COUNT; */
+ }
+ }
+ /* if detected = TRUE, client initiated wakeup was detected */
+ if (mddi_sharp_vsync_handler != NULL) {
+ (*mddi_sharp_vsync_handler)
+ (mddi_sharp_vsync_handler_arg);
+ mddi_sharp_vsync_handler = NULL;
+ }
+ mddi_vsync_detect_enabled = FALSE;
+ mddi_sharp_vsync_attempts = 0;
+ /* need to clear this vsync wakeup */
+ if (!mddi_queue_register_write_int(REG_INTR, 0x0000)) {
+ MDDI_MSG_ERR("Vsync interrupt clear failed!\n");
+ }
+ if (!detected) {
+ /* give up after 5 failed attempts but show error */
+ MDDI_MSG_NOTICE("Vsync detection failed!\n");
+ } else if ((mddi_sharp_monitor_refresh_value) &&
+ (mddi_sharp_report_refresh_measurements)) {
+ MDDI_MSG_NOTICE(" Lines Per Second=%d!\n",
+ mddi_sharp_rows_per_second);
+ }
+ } else
+ /* if detected = FALSE, we woke up from hibernation, but did not
+ * detect client initiated wakeup.
+ */
+ mddi_sharp_vsync_attempts++;
+}
+
+/* ISR to be executed */
+void mddi_sharp_vsync_set_handler(msm_fb_vsync_handler_type handler, void *arg)
+{
+ boolean error = FALSE;
+ unsigned long flags;
+
+ /* Disable interrupts */
+ spin_lock_irqsave(&mddi_host_spin_lock, flags);
+ /* INTLOCK(); */
+
+ if (mddi_sharp_vsync_handler != NULL)
+ error = TRUE;
+
+ /* Register the handler for this particular GROUP interrupt source */
+ mddi_sharp_vsync_handler = handler;
+ mddi_sharp_vsync_handler_arg = arg;
+
+ /* Restore interrupts */
+ spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+ /* INTFREE(); */
+
+ if (error)
+ MDDI_MSG_ERR("MDDI: Previous Vsync handler never called\n");
+
+ /* Enable the vsync wakeup */
+ mddi_queue_register_write(REG_INTR, 0x8100, FALSE, 0);
+
+ mddi_sharp_vsync_attempts = 1;
+ mddi_vsync_detect_enabled = TRUE;
+} /* mddi_sharp_vsync_set_handler */
+
+static int mddi_sharp_lcd_on(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ if (mfd->panel.id == SHARP_QVGA_PRIM)
+ mddi_sharp_prim_lcd_init();
+ else
+ mddi_sharp_sub_lcd_init();
+
+ return 0;
+}
+
+static int mddi_sharp_lcd_off(struct platform_device *pdev)
+{
+ mddi_sharp_lcd_powerdown();
+ return 0;
+}
+
+static int __init mddi_sharp_probe(struct platform_device *pdev)
+{
+ if (pdev->id == 0) {
+ mddi_sharp_pdata = pdev->dev.platform_data;
+ return 0;
+ }
+
+ msm_fb_add_device(pdev);
+
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = mddi_sharp_probe,
+ .driver = {
+ .name = "mddi_sharp_qvga",
+ },
+};
+
+static struct msm_fb_panel_data mddi_sharp_panel_data0 = {
+ .on = mddi_sharp_lcd_on,
+ .off = mddi_sharp_lcd_off,
+ .set_backlight = mddi_sharp_lcd_set_backlight,
+ .set_vsync_notifier = mddi_sharp_vsync_set_handler,
+};
+
+static struct platform_device this_device_0 = {
+ .name = "mddi_sharp_qvga",
+ .id = SHARP_QVGA_PRIM,
+ .dev = {
+ .platform_data = &mddi_sharp_panel_data0,
+ }
+};
+
+static struct msm_fb_panel_data mddi_sharp_panel_data1 = {
+ .on = mddi_sharp_lcd_on,
+ .off = mddi_sharp_lcd_off,
+};
+
+static struct platform_device this_device_1 = {
+ .name = "mddi_sharp_qvga",
+ .id = SHARP_128X128_SECD,
+ .dev = {
+ .platform_data = &mddi_sharp_panel_data1,
+ }
+};
+
+static int __init mddi_sharp_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+ u32 id;
+
+ ret = msm_fb_detect_client("mddi_sharp_qvga");
+ if (ret == -ENODEV)
+ return 0;
+
+ if (ret) {
+ id = mddi_get_client_id();
+
+ if (((id >> 16) != 0x0) || ((id & 0xffff) != 0x8835))
+ return 0;
+ }
+#endif
+ if (mddi_host_core_version > 8) {
+ /* can use faster refresh with newer hw revisions */
+ mddi_sharp_debug_60hz_refresh = TRUE;
+
+ /* Timing variables for tracking vsync */
+ /* dot_clock = 6.00MHz
+ * horizontal count = 296
+ * vertical count = 338
+ * refresh rate = 6000000/(296+338) = 60Hz
+ */
+ mddi_sharp_rows_per_second = 20270; /* 6000000/296 */
+ mddi_sharp_rows_per_refresh = 338;
+ mddi_sharp_usecs_per_refresh = 16674; /* (296+338)/6000000 */
+ } else {
+ /* Timing variables for tracking vsync */
+ /* dot_clock = 5.20MHz
+ * horizontal count = 376
+ * vertical count = 338
+ * refresh rate = 5200000/(376+338) = 41Hz
+ */
+ mddi_sharp_rows_per_second = 13830; /* 5200000/376 */
+ mddi_sharp_rows_per_refresh = 338;
+ mddi_sharp_usecs_per_refresh = 24440; /* (376+338)/5200000 */
+ }
+
+ ret = platform_driver_register(&this_driver);
+ if (!ret) {
+ pinfo = &mddi_sharp_panel_data0.panel_info;
+ pinfo->xres = 240;
+ pinfo->yres = 320;
+ pinfo->type = MDDI_PANEL;
+ pinfo->pdest = DISPLAY_1;
+ pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 18;
+ pinfo->fb_num = 2;
+ pinfo->clk_rate = 122880000;
+ pinfo->clk_min = 120000000;
+ pinfo->clk_max = 125000000;
+ pinfo->lcd.vsync_enable = TRUE;
+ pinfo->lcd.refx100 =
+ (mddi_sharp_rows_per_second * 100) /
+ mddi_sharp_rows_per_refresh;
+ pinfo->lcd.v_back_porch = 12;
+ pinfo->lcd.v_front_porch = 6;
+ pinfo->lcd.v_pulse_width = 0;
+ pinfo->lcd.hw_vsync_mode = FALSE;
+ pinfo->lcd.vsync_notifier_period = (1 * HZ);
+ pinfo->bl_max = 7;
+ pinfo->bl_min = 1;
+
+ ret = platform_device_register(&this_device_0);
+ if (ret)
+ platform_driver_unregister(&this_driver);
+
+ pinfo = &mddi_sharp_panel_data1.panel_info;
+ pinfo->xres = 128;
+ pinfo->yres = 128;
+ pinfo->type = MDDI_PANEL;
+ pinfo->pdest = DISPLAY_2;
+ pinfo->mddi.vdopkt = 0x400;
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 18;
+ pinfo->clk_rate = 122880000;
+ pinfo->clk_min = 120000000;
+ pinfo->clk_max = 125000000;
+ pinfo->fb_num = 2;
+
+ ret = platform_device_register(&this_device_1);
+ if (ret) {
+ platform_device_unregister(&this_device_0);
+ platform_driver_unregister(&this_driver);
+ }
+ }
+
+ if (!ret)
+ mddi_lcd.vsync_detected = mddi_sharp_lcd_vsync_detected;
+
+ return ret;
+}
+
+module_init(mddi_sharp_init);
diff --git a/drivers/staging/msm/mddi_toshiba.c b/drivers/staging/msm/mddi_toshiba.c
new file mode 100644
index 0000000..e96342d
--- /dev/null
+++ b/drivers/staging/msm/mddi_toshiba.c
@@ -0,0 +1,1741 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+#include "mddi_toshiba.h"
+
+#define TM_GET_DID(id) ((id) & 0xff)
+#define TM_GET_PID(id) (((id) & 0xff00)>>8)
+
+#define MDDI_CLIENT_CORE_BASE 0x108000
+#define LCD_CONTROL_BLOCK_BASE 0x110000
+#define SPI_BLOCK_BASE 0x120000
+#define PWM_BLOCK_BASE 0x140000
+#define SYSTEM_BLOCK1_BASE 0x160000
+
+#define TTBUSSEL (MDDI_CLIENT_CORE_BASE|0x18)
+#define DPSET0 (MDDI_CLIENT_CORE_BASE|0x1C)
+#define DPSET1 (MDDI_CLIENT_CORE_BASE|0x20)
+#define DPSUS (MDDI_CLIENT_CORE_BASE|0x24)
+#define DPRUN (MDDI_CLIENT_CORE_BASE|0x28)
+#define SYSCKENA (MDDI_CLIENT_CORE_BASE|0x2C)
+
+#define BITMAP0 (MDDI_CLIENT_CORE_BASE|0x44)
+#define BITMAP1 (MDDI_CLIENT_CORE_BASE|0x48)
+#define BITMAP2 (MDDI_CLIENT_CORE_BASE|0x4C)
+#define BITMAP3 (MDDI_CLIENT_CORE_BASE|0x50)
+#define BITMAP4 (MDDI_CLIENT_CORE_BASE|0x54)
+
+#define SRST (LCD_CONTROL_BLOCK_BASE|0x00)
+#define PORT_ENB (LCD_CONTROL_BLOCK_BASE|0x04)
+#define START (LCD_CONTROL_BLOCK_BASE|0x08)
+#define PORT (LCD_CONTROL_BLOCK_BASE|0x0C)
+
+#define INTFLG (LCD_CONTROL_BLOCK_BASE|0x18)
+#define INTMSK (LCD_CONTROL_BLOCK_BASE|0x1C)
+#define MPLFBUF (LCD_CONTROL_BLOCK_BASE|0x20)
+
+#define PXL (LCD_CONTROL_BLOCK_BASE|0x30)
+#define HCYCLE (LCD_CONTROL_BLOCK_BASE|0x34)
+#define HSW (LCD_CONTROL_BLOCK_BASE|0x38)
+#define HDE_START (LCD_CONTROL_BLOCK_BASE|0x3C)
+#define HDE_SIZE (LCD_CONTROL_BLOCK_BASE|0x40)
+#define VCYCLE (LCD_CONTROL_BLOCK_BASE|0x44)
+#define VSW (LCD_CONTROL_BLOCK_BASE|0x48)
+#define VDE_START (LCD_CONTROL_BLOCK_BASE|0x4C)
+#define VDE_SIZE (LCD_CONTROL_BLOCK_BASE|0x50)
+#define WAKEUP (LCD_CONTROL_BLOCK_BASE|0x54)
+#define REGENB (LCD_CONTROL_BLOCK_BASE|0x5C)
+#define VSYNIF (LCD_CONTROL_BLOCK_BASE|0x60)
+#define WRSTB (LCD_CONTROL_BLOCK_BASE|0x64)
+#define RDSTB (LCD_CONTROL_BLOCK_BASE|0x68)
+#define ASY_DATA (LCD_CONTROL_BLOCK_BASE|0x6C)
+#define ASY_DATB (LCD_CONTROL_BLOCK_BASE|0x70)
+#define ASY_DATC (LCD_CONTROL_BLOCK_BASE|0x74)
+#define ASY_DATD (LCD_CONTROL_BLOCK_BASE|0x78)
+#define ASY_DATE (LCD_CONTROL_BLOCK_BASE|0x7C)
+#define ASY_DATF (LCD_CONTROL_BLOCK_BASE|0x80)
+#define ASY_DATG (LCD_CONTROL_BLOCK_BASE|0x84)
+#define ASY_DATH (LCD_CONTROL_BLOCK_BASE|0x88)
+#define ASY_CMDSET (LCD_CONTROL_BLOCK_BASE|0x8C)
+#define MONI (LCD_CONTROL_BLOCK_BASE|0xB0)
+#define VPOS (LCD_CONTROL_BLOCK_BASE|0xC0)
+
+#define SSICTL (SPI_BLOCK_BASE|0x00)
+#define SSITIME (SPI_BLOCK_BASE|0x04)
+#define SSITX (SPI_BLOCK_BASE|0x08)
+#define SSIINTS (SPI_BLOCK_BASE|0x14)
+
+#define TIMER0LOAD (PWM_BLOCK_BASE|0x00)
+#define TIMER0CTRL (PWM_BLOCK_BASE|0x08)
+#define PWM0OFF (PWM_BLOCK_BASE|0x1C)
+#define TIMER1LOAD (PWM_BLOCK_BASE|0x20)
+#define TIMER1CTRL (PWM_BLOCK_BASE|0x28)
+#define PWM1OFF (PWM_BLOCK_BASE|0x3C)
+#define TIMER2LOAD (PWM_BLOCK_BASE|0x40)
+#define TIMER2CTRL (PWM_BLOCK_BASE|0x48)
+#define PWM2OFF (PWM_BLOCK_BASE|0x5C)
+#define PWMCR (PWM_BLOCK_BASE|0x68)
+
+#define GPIOIS (GPIO_BLOCK_BASE|0x08)
+#define GPIOIEV (GPIO_BLOCK_BASE|0x10)
+#define GPIOIC (GPIO_BLOCK_BASE|0x20)
+
+#define WKREQ (SYSTEM_BLOCK1_BASE|0x00)
+#define CLKENB (SYSTEM_BLOCK1_BASE|0x04)
+#define DRAMPWR (SYSTEM_BLOCK1_BASE|0x08)
+#define INTMASK (SYSTEM_BLOCK1_BASE|0x0C)
+#define CNT_DIS (SYSTEM_BLOCK1_BASE|0x10)
+
+typedef enum {
+ TOSHIBA_STATE_OFF,
+ TOSHIBA_STATE_PRIM_SEC_STANDBY,
+ TOSHIBA_STATE_PRIM_SEC_READY,
+ TOSHIBA_STATE_PRIM_NORMAL_MODE,
+ TOSHIBA_STATE_SEC_NORMAL_MODE
+} mddi_toshiba_state_t;
+
+static uint32 mddi_toshiba_curr_vpos;
+static boolean mddi_toshiba_monitor_refresh_value = FALSE;
+static boolean mddi_toshiba_report_refresh_measurements = FALSE;
+
+boolean mddi_toshiba_61Hz_refresh = TRUE;
+
+/* Modifications to timing to increase refresh rate to > 60Hz.
+ * 20MHz dot clock.
+ * 646 total rows.
+ * 506 total columns.
+ * refresh rate = 61.19Hz
+ */
+static uint32 mddi_toshiba_rows_per_second = 39526;
+static uint32 mddi_toshiba_usecs_per_refresh = 16344;
+static uint32 mddi_toshiba_rows_per_refresh = 646;
+extern boolean mddi_vsync_detect_enabled;
+
+static msm_fb_vsync_handler_type mddi_toshiba_vsync_handler;
+static void *mddi_toshiba_vsync_handler_arg;
+static uint16 mddi_toshiba_vsync_attempts;
+
+static mddi_toshiba_state_t toshiba_state = TOSHIBA_STATE_OFF;
+
+static struct msm_panel_common_pdata *mddi_toshiba_pdata;
+
+static int mddi_toshiba_lcd_on(struct platform_device *pdev);
+static int mddi_toshiba_lcd_off(struct platform_device *pdev);
+
+static void mddi_toshiba_state_transition(mddi_toshiba_state_t a,
+ mddi_toshiba_state_t b)
+{
+ if (toshiba_state != a) {
+ MDDI_MSG_ERR("toshiba state trans. (%d->%d) found %d\n", a, b,
+ toshiba_state);
+ }
+ toshiba_state = b;
+}
+
+#define GORDON_REG_IMGCTL1 0x10 /* Image interface control 1 */
+#define GORDON_REG_IMGCTL2 0x11 /* Image interface control 2 */
+#define GORDON_REG_IMGSET1 0x12 /* Image interface settings 1 */
+#define GORDON_REG_IMGSET2 0x13 /* Image interface settings 2 */
+#define GORDON_REG_IVBP1 0x14 /* DM0: Vert back porch */
+#define GORDON_REG_IHBP1 0x15 /* DM0: Horiz back porch */
+#define GORDON_REG_IVNUM1 0x16 /* DM0: Num of vert lines */
+#define GORDON_REG_IHNUM1 0x17 /* DM0: Num of pixels per line */
+#define GORDON_REG_IVBP2 0x18 /* DM1: Vert back porch */
+#define GORDON_REG_IHBP2 0x19 /* DM1: Horiz back porch */
+#define GORDON_REG_IVNUM2 0x1A /* DM1: Num of vert lines */
+#define GORDON_REG_IHNUM2 0x1B /* DM1: Num of pixels per line */
+#define GORDON_REG_LCDIFCTL1 0x30 /* LCD interface control 1 */
+#define GORDON_REG_VALTRAN 0x31 /* LCD IF ctl: VALTRAN sync flag */
+#define GORDON_REG_AVCTL 0x33
+#define GORDON_REG_LCDIFCTL2 0x34 /* LCD interface control 2 */
+#define GORDON_REG_LCDIFCTL3 0x35 /* LCD interface control 3 */
+#define GORDON_REG_LCDIFSET1 0x36 /* LCD interface settings 1 */
+#define GORDON_REG_PCCTL 0x3C
+#define GORDON_REG_TPARAM1 0x40
+#define GORDON_REG_TLCDIF1 0x41
+#define GORDON_REG_TSSPB_ST1 0x42
+#define GORDON_REG_TSSPB_ED1 0x43
+#define GORDON_REG_TSCK_ST1 0x44
+#define GORDON_REG_TSCK_WD1 0x45
+#define GORDON_REG_TGSPB_VST1 0x46
+#define GORDON_REG_TGSPB_VED1 0x47
+#define GORDON_REG_TGSPB_CH1 0x48
+#define GORDON_REG_TGCK_ST1 0x49
+#define GORDON_REG_TGCK_ED1 0x4A
+#define GORDON_REG_TPCTL_ST1 0x4B
+#define GORDON_REG_TPCTL_ED1 0x4C
+#define GORDON_REG_TPCHG_ED1 0x4D
+#define GORDON_REG_TCOM_CH1 0x4E
+#define GORDON_REG_THBP1 0x4F
+#define GORDON_REG_TPHCTL1 0x50
+#define GORDON_REG_EVPH1 0x51
+#define GORDON_REG_EVPL1 0x52
+#define GORDON_REG_EVNH1 0x53
+#define GORDON_REG_EVNL1 0x54
+#define GORDON_REG_TBIAS1 0x55
+#define GORDON_REG_TPARAM2 0x56
+#define GORDON_REG_TLCDIF2 0x57
+#define GORDON_REG_TSSPB_ST2 0x58
+#define GORDON_REG_TSSPB_ED2 0x59
+#define GORDON_REG_TSCK_ST2 0x5A
+#define GORDON_REG_TSCK_WD2 0x5B
+#define GORDON_REG_TGSPB_VST2 0x5C
+#define GORDON_REG_TGSPB_VED2 0x5D
+#define GORDON_REG_TGSPB_CH2 0x5E
+#define GORDON_REG_TGCK_ST2 0x5F
+#define GORDON_REG_TGCK_ED2 0x60
+#define GORDON_REG_TPCTL_ST2 0x61
+#define GORDON_REG_TPCTL_ED2 0x62
+#define GORDON_REG_TPCHG_ED2 0x63
+#define GORDON_REG_TCOM_CH2 0x64
+#define GORDON_REG_THBP2 0x65
+#define GORDON_REG_TPHCTL2 0x66
+#define GORDON_REG_EVPH2 0x67
+#define GORDON_REG_EVPL2 0x68
+#define GORDON_REG_EVNH2 0x69
+#define GORDON_REG_EVNL2 0x6A
+#define GORDON_REG_TBIAS2 0x6B
+#define GORDON_REG_POWCTL 0x80
+#define GORDON_REG_POWOSC1 0x81
+#define GORDON_REG_POWOSC2 0x82
+#define GORDON_REG_POWSET 0x83
+#define GORDON_REG_POWTRM1 0x85
+#define GORDON_REG_POWTRM2 0x86
+#define GORDON_REG_POWTRM3 0x87
+#define GORDON_REG_POWTRMSEL 0x88
+#define GORDON_REG_POWHIZ 0x89
+
+void serigo(uint16 reg, uint8 data)
+{
+ uint32 mddi_val = 0;
+ mddi_queue_register_read(SSIINTS, &mddi_val, TRUE, 0);
+ if (mddi_val & (1 << 8))
+ mddi_wait(1);
+ /* No De-assert of CS and send 2 bytes */
+ mddi_val = 0x90000 | ((0x00FF & reg) << 8) | data;
+ mddi_queue_register_write(SSITX, mddi_val, TRUE, 0);
+}
+
+void gordon_init(void)
+{
+ /* Image interface settings ***/
+ serigo(GORDON_REG_IMGCTL2, 0x00);
+ serigo(GORDON_REG_IMGSET1, 0x01);
+
+ /* Exchange the RGB signal for J510(Softbank mobile) */
+ serigo(GORDON_REG_IMGSET2, 0x12);
+ serigo(GORDON_REG_LCDIFSET1, 0x00);
+ mddi_wait(2);
+
+ /* Pre-charge settings */
+ serigo(GORDON_REG_PCCTL, 0x09);
+ serigo(GORDON_REG_LCDIFCTL2, 0x1B);
+ mddi_wait(1);
+}
+
+void gordon_disp_on(void)
+{
+ /*gordon_dispmode setting */
+ /*VGA settings */
+ serigo(GORDON_REG_TPARAM1, 0x30);
+ serigo(GORDON_REG_TLCDIF1, 0x00);
+ serigo(GORDON_REG_TSSPB_ST1, 0x8B);
+ serigo(GORDON_REG_TSSPB_ED1, 0x93);
+ mddi_wait(2);
+ serigo(GORDON_REG_TSCK_ST1, 0x88);
+ serigo(GORDON_REG_TSCK_WD1, 0x00);
+ serigo(GORDON_REG_TGSPB_VST1, 0x01);
+ serigo(GORDON_REG_TGSPB_VED1, 0x02);
+ mddi_wait(2);
+ serigo(GORDON_REG_TGSPB_CH1, 0x5E);
+ serigo(GORDON_REG_TGCK_ST1, 0x80);
+ serigo(GORDON_REG_TGCK_ED1, 0x3C);
+ serigo(GORDON_REG_TPCTL_ST1, 0x50);
+ mddi_wait(2);
+ serigo(GORDON_REG_TPCTL_ED1, 0x74);
+ serigo(GORDON_REG_TPCHG_ED1, 0x78);
+ serigo(GORDON_REG_TCOM_CH1, 0x50);
+ serigo(GORDON_REG_THBP1, 0x84);
+ mddi_wait(2);
+ serigo(GORDON_REG_TPHCTL1, 0x00);
+ serigo(GORDON_REG_EVPH1, 0x70);
+ serigo(GORDON_REG_EVPL1, 0x64);
+ serigo(GORDON_REG_EVNH1, 0x56);
+ mddi_wait(2);
+ serigo(GORDON_REG_EVNL1, 0x48);
+ serigo(GORDON_REG_TBIAS1, 0x88);
+ mddi_wait(2);
+ serigo(GORDON_REG_TPARAM2, 0x28);
+ serigo(GORDON_REG_TLCDIF2, 0x14);
+ serigo(GORDON_REG_TSSPB_ST2, 0x49);
+ serigo(GORDON_REG_TSSPB_ED2, 0x4B);
+ mddi_wait(2);
+ serigo(GORDON_REG_TSCK_ST2, 0x4A);
+ serigo(GORDON_REG_TSCK_WD2, 0x02);
+ serigo(GORDON_REG_TGSPB_VST2, 0x02);
+ serigo(GORDON_REG_TGSPB_VED2, 0x03);
+ mddi_wait(2);
+ serigo(GORDON_REG_TGSPB_CH2, 0x2F);
+ serigo(GORDON_REG_TGCK_ST2, 0x40);
+ serigo(GORDON_REG_TGCK_ED2, 0x1E);
+ serigo(GORDON_REG_TPCTL_ST2, 0x2C);
+ mddi_wait(2);
+ serigo(GORDON_REG_TPCTL_ED2, 0x3A);
+ serigo(GORDON_REG_TPCHG_ED2, 0x3C);
+ serigo(GORDON_REG_TCOM_CH2, 0x28);
+ serigo(GORDON_REG_THBP2, 0x4D);
+ mddi_wait(2);
+ serigo(GORDON_REG_TPHCTL2, 0x1A);
+ mddi_wait(2);
+ serigo(GORDON_REG_IVBP1, 0x02);
+ serigo(GORDON_REG_IHBP1, 0x90);
+ serigo(GORDON_REG_IVNUM1, 0xA0);
+ serigo(GORDON_REG_IHNUM1, 0x78);
+ mddi_wait(2);
+ serigo(GORDON_REG_IVBP2, 0x02);
+ serigo(GORDON_REG_IHBP2, 0x48);
+ serigo(GORDON_REG_IVNUM2, 0x50);
+ serigo(GORDON_REG_IHNUM2, 0x3C);
+ mddi_wait(2);
+ serigo(GORDON_REG_POWCTL, 0x03);
+ mddi_wait(15);
+ serigo(GORDON_REG_POWCTL, 0x07);
+ mddi_wait(15);
+ serigo(GORDON_REG_POWCTL, 0x0F);
+ mddi_wait(15);
+ serigo(GORDON_REG_AVCTL, 0x03);
+ mddi_wait(15);
+ serigo(GORDON_REG_POWCTL, 0x1F);
+ mddi_wait(15);
+ serigo(GORDON_REG_POWCTL, 0x5F);
+ mddi_wait(15);
+ serigo(GORDON_REG_POWCTL, 0x7F);
+ mddi_wait(15);
+ serigo(GORDON_REG_LCDIFCTL1, 0x02);
+ mddi_wait(15);
+ serigo(GORDON_REG_IMGCTL1, 0x00);
+ mddi_wait(15);
+ serigo(GORDON_REG_LCDIFCTL3, 0x00);
+ mddi_wait(15);
+ serigo(GORDON_REG_VALTRAN, 0x01);
+ mddi_wait(15);
+ serigo(GORDON_REG_LCDIFCTL1, 0x03);
+ serigo(GORDON_REG_LCDIFCTL1, 0x03);
+ mddi_wait(1);
+}
+
+void gordon_disp_off(void)
+{
+ serigo(GORDON_REG_LCDIFCTL2, 0x7B);
+ serigo(GORDON_REG_VALTRAN, 0x01);
+ serigo(GORDON_REG_LCDIFCTL1, 0x02);
+ serigo(GORDON_REG_LCDIFCTL3, 0x01);
+ mddi_wait(20);
+ serigo(GORDON_REG_VALTRAN, 0x01);
+ serigo(GORDON_REG_IMGCTL1, 0x01);
+ serigo(GORDON_REG_LCDIFCTL1, 0x00);
+ mddi_wait(20);
+ serigo(GORDON_REG_POWCTL, 0x1F);
+ mddi_wait(40);
+ serigo(GORDON_REG_POWCTL, 0x07);
+ mddi_wait(40);
+ serigo(GORDON_REG_POWCTL, 0x03);
+ mddi_wait(40);
+ serigo(GORDON_REG_POWCTL, 0x00);
+ mddi_wait(40);
+}
+
+void gordon_disp_init(void)
+{
+ gordon_init();
+ mddi_wait(20);
+ gordon_disp_on();
+}
+
+static void toshiba_common_initial_setup(struct msm_fb_data_type *mfd)
+{
+ if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT) {
+ write_client_reg(DPSET0 , 0x4bec0066, TRUE);
+ write_client_reg(DPSET1 , 0x00000113, TRUE);
+ write_client_reg(DPSUS , 0x00000000, TRUE);
+ write_client_reg(DPRUN , 0x00000001, TRUE);
+ mddi_wait(5);
+ write_client_reg(SYSCKENA , 0x00000001, TRUE);
+ write_client_reg(CLKENB , 0x0000a0e9, TRUE);
+
+ write_client_reg(GPIODATA , 0x03FF0000, TRUE);
+ write_client_reg(GPIODIR , 0x0000024D, TRUE);
+ write_client_reg(GPIOSEL , 0x00000173, TRUE);
+ write_client_reg(GPIOPC , 0x03C300C0, TRUE);
+ write_client_reg(WKREQ , 0x00000000, TRUE);
+ write_client_reg(GPIOIS , 0x00000000, TRUE);
+ write_client_reg(GPIOIEV , 0x00000001, TRUE);
+ write_client_reg(GPIOIC , 0x000003FF, TRUE);
+ write_client_reg(GPIODATA , 0x00040004, TRUE);
+
+ write_client_reg(GPIODATA , 0x00080008, TRUE);
+ write_client_reg(DRAMPWR , 0x00000001, TRUE);
+ write_client_reg(CLKENB , 0x0000a0eb, TRUE);
+ write_client_reg(PWMCR , 0x00000000, TRUE);
+ mddi_wait(1);
+
+ write_client_reg(SSICTL , 0x00060399, TRUE);
+ write_client_reg(SSITIME , 0x00000100, TRUE);
+ write_client_reg(CNT_DIS , 0x00000002, TRUE);
+ write_client_reg(SSICTL , 0x0006039b, TRUE);
+
+ write_client_reg(SSITX , 0x00000000, TRUE);
+ mddi_wait(7);
+ write_client_reg(SSITX , 0x00000000, TRUE);
+ mddi_wait(7);
+ write_client_reg(SSITX , 0x00000000, TRUE);
+ mddi_wait(7);
+
+ write_client_reg(SSITX , 0x000800BA, TRUE);
+ write_client_reg(SSITX , 0x00000111, TRUE);
+ write_client_reg(SSITX , 0x00080036, TRUE);
+ write_client_reg(SSITX , 0x00000100, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x0008003A, TRUE);
+ write_client_reg(SSITX , 0x00000160, TRUE);
+ write_client_reg(SSITX , 0x000800B1, TRUE);
+ write_client_reg(SSITX , 0x0000015D, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800B2, TRUE);
+ write_client_reg(SSITX , 0x00000133, TRUE);
+ write_client_reg(SSITX , 0x000800B3, TRUE);
+ write_client_reg(SSITX , 0x00000122, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800B4, TRUE);
+ write_client_reg(SSITX , 0x00000102, TRUE);
+ write_client_reg(SSITX , 0x000800B5, TRUE);
+ write_client_reg(SSITX , 0x0000011E, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800B6, TRUE);
+ write_client_reg(SSITX , 0x00000127, TRUE);
+ write_client_reg(SSITX , 0x000800B7, TRUE);
+ write_client_reg(SSITX , 0x00000103, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800B9, TRUE);
+ write_client_reg(SSITX , 0x00000124, TRUE);
+ write_client_reg(SSITX , 0x000800BD, TRUE);
+ write_client_reg(SSITX , 0x000001A1, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800BB, TRUE);
+ write_client_reg(SSITX , 0x00000100, TRUE);
+ write_client_reg(SSITX , 0x000800BF, TRUE);
+ write_client_reg(SSITX , 0x00000101, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800BE, TRUE);
+ write_client_reg(SSITX , 0x00000100, TRUE);
+ write_client_reg(SSITX , 0x000800C0, TRUE);
+ write_client_reg(SSITX , 0x00000111, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800C1, TRUE);
+ write_client_reg(SSITX , 0x00000111, TRUE);
+ write_client_reg(SSITX , 0x000800C2, TRUE);
+ write_client_reg(SSITX , 0x00000111, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800C3, TRUE);
+ write_client_reg(SSITX , 0x00080132, TRUE);
+ write_client_reg(SSITX , 0x00000132, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800C4, TRUE);
+ write_client_reg(SSITX , 0x00080132, TRUE);
+ write_client_reg(SSITX , 0x00000132, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800C5, TRUE);
+ write_client_reg(SSITX , 0x00080132, TRUE);
+ write_client_reg(SSITX , 0x00000132, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800C6, TRUE);
+ write_client_reg(SSITX , 0x00080132, TRUE);
+ write_client_reg(SSITX , 0x00000132, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800C7, TRUE);
+ write_client_reg(SSITX , 0x00080164, TRUE);
+ write_client_reg(SSITX , 0x00000145, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800C8, TRUE);
+ write_client_reg(SSITX , 0x00000144, TRUE);
+ write_client_reg(SSITX , 0x000800C9, TRUE);
+ write_client_reg(SSITX , 0x00000152, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800CA, TRUE);
+ write_client_reg(SSITX , 0x00000100, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800EC, TRUE);
+ write_client_reg(SSITX , 0x00080101, TRUE);
+ write_client_reg(SSITX , 0x000001FC, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800CF, TRUE);
+ write_client_reg(SSITX , 0x00000101, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800D0, TRUE);
+ write_client_reg(SSITX , 0x00080110, TRUE);
+ write_client_reg(SSITX , 0x00000104, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800D1, TRUE);
+ write_client_reg(SSITX , 0x00000101, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800D2, TRUE);
+ write_client_reg(SSITX , 0x00080100, TRUE);
+ write_client_reg(SSITX , 0x00000128, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800D3, TRUE);
+ write_client_reg(SSITX , 0x00080100, TRUE);
+ write_client_reg(SSITX , 0x00000128, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800D4, TRUE);
+ write_client_reg(SSITX , 0x00080126, TRUE);
+ write_client_reg(SSITX , 0x000001A4, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800D5, TRUE);
+ write_client_reg(SSITX , 0x00000120, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800EF, TRUE);
+ write_client_reg(SSITX , 0x00080132, TRUE);
+ write_client_reg(SSITX , 0x00000100, TRUE);
+ mddi_wait(1);
+
+ write_client_reg(BITMAP0 , 0x032001E0, TRUE);
+ write_client_reg(BITMAP1 , 0x032001E0, TRUE);
+ write_client_reg(BITMAP2 , 0x014000F0, TRUE);
+ write_client_reg(BITMAP3 , 0x014000F0, TRUE);
+ write_client_reg(BITMAP4 , 0x014000F0, TRUE);
+ write_client_reg(CLKENB , 0x0000A1EB, TRUE);
+ write_client_reg(PORT_ENB , 0x00000001, TRUE);
+ write_client_reg(PORT , 0x00000004, TRUE);
+ write_client_reg(PXL , 0x00000002, TRUE);
+ write_client_reg(MPLFBUF , 0x00000000, TRUE);
+ write_client_reg(HCYCLE , 0x000000FD, TRUE);
+ write_client_reg(HSW , 0x00000003, TRUE);
+ write_client_reg(HDE_START , 0x00000007, TRUE);
+ write_client_reg(HDE_SIZE , 0x000000EF, TRUE);
+ write_client_reg(VCYCLE , 0x00000325, TRUE);
+ write_client_reg(VSW , 0x00000001, TRUE);
+ write_client_reg(VDE_START , 0x00000003, TRUE);
+ write_client_reg(VDE_SIZE , 0x0000031F, TRUE);
+ write_client_reg(START , 0x00000001, TRUE);
+ mddi_wait(32);
+ write_client_reg(SSITX , 0x000800BC, TRUE);
+ write_client_reg(SSITX , 0x00000180, TRUE);
+ write_client_reg(SSITX , 0x0008003B, TRUE);
+ write_client_reg(SSITX , 0x00000100, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800B0, TRUE);
+ write_client_reg(SSITX , 0x00000116, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x000800B8, TRUE);
+ write_client_reg(SSITX , 0x000801FF, TRUE);
+ write_client_reg(SSITX , 0x000001F5, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX , 0x00000011, TRUE);
+ mddi_wait(5);
+ write_client_reg(SSITX , 0x00000029, TRUE);
+ return;
+ }
+
+ if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) {
+ write_client_reg(DPSET0, 0x4BEC0066, TRUE);
+ write_client_reg(DPSET1, 0x00000113, TRUE);
+ write_client_reg(DPSUS, 0x00000000, TRUE);
+ write_client_reg(DPRUN, 0x00000001, TRUE);
+ mddi_wait(14);
+ write_client_reg(SYSCKENA, 0x00000001, TRUE);
+ write_client_reg(CLKENB, 0x000000EF, TRUE);
+ write_client_reg(GPIO_BLOCK_BASE, 0x03FF0000, TRUE);
+ write_client_reg(GPIODIR, 0x0000024D, TRUE);
+ write_client_reg(SYSTEM_BLOCK2_BASE, 0x00000173, TRUE);
+ write_client_reg(GPIOPC, 0x03C300C0, TRUE);
+ write_client_reg(SYSTEM_BLOCK1_BASE, 0x00000000, TRUE);
+ write_client_reg(GPIOIS, 0x00000000, TRUE);
+ write_client_reg(GPIOIEV, 0x00000001, TRUE);
+ write_client_reg(GPIOIC, 0x000003FF, TRUE);
+ write_client_reg(GPIO_BLOCK_BASE, 0x00060006, TRUE);
+ write_client_reg(GPIO_BLOCK_BASE, 0x00080008, TRUE);
+ write_client_reg(GPIO_BLOCK_BASE, 0x02000200, TRUE);
+ write_client_reg(DRAMPWR, 0x00000001, TRUE);
+ write_client_reg(TIMER0CTRL, 0x00000060, TRUE);
+ write_client_reg(PWM_BLOCK_BASE, 0x00001388, TRUE);
+ write_client_reg(PWM0OFF, 0x00001387, TRUE);
+ write_client_reg(TIMER1CTRL, 0x00000060, TRUE);
+ write_client_reg(TIMER1LOAD, 0x00001388, TRUE);
+ write_client_reg(PWM1OFF, 0x00001387, TRUE);
+ write_client_reg(TIMER0CTRL, 0x000000E0, TRUE);
+ write_client_reg(TIMER1CTRL, 0x000000E0, TRUE);
+ write_client_reg(PWMCR, 0x00000003, TRUE);
+ mddi_wait(1);
+ write_client_reg(SPI_BLOCK_BASE, 0x00063111, TRUE);
+ write_client_reg(SSITIME, 0x00000100, TRUE);
+ write_client_reg(SPI_BLOCK_BASE, 0x00063113, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX, 0x00000000, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX, 0x00000000, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX, 0x00000000, TRUE);
+ mddi_wait(1);
+ write_client_reg(CLKENB, 0x0000A1EF, TRUE);
+ write_client_reg(START, 0x00000000, TRUE);
+ write_client_reg(WRSTB, 0x0000003F, TRUE);
+ write_client_reg(RDSTB, 0x00000432, TRUE);
+ write_client_reg(PORT_ENB, 0x00000002, TRUE);
+ write_client_reg(VSYNIF, 0x00000000, TRUE);
+ write_client_reg(ASY_DATA, 0x80000000, TRUE);
+ write_client_reg(ASY_DATB, 0x00000001, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(10);
+ write_client_reg(ASY_DATA, 0x80000000, TRUE);
+ write_client_reg(ASY_DATB, 0x80000000, TRUE);
+ write_client_reg(ASY_DATC, 0x80000000, TRUE);
+ write_client_reg(ASY_DATD, 0x80000000, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
+ write_client_reg(ASY_DATA, 0x80000007, TRUE);
+ write_client_reg(ASY_DATB, 0x00004005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(20);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x00000000, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+
+ write_client_reg(VSYNIF, 0x00000001, TRUE);
+ write_client_reg(PORT_ENB, 0x00000001, TRUE);
+ } else {
+ write_client_reg(DPSET0, 0x4BEC0066, TRUE);
+ write_client_reg(DPSET1, 0x00000113, TRUE);
+ write_client_reg(DPSUS, 0x00000000, TRUE);
+ write_client_reg(DPRUN, 0x00000001, TRUE);
+ mddi_wait(14);
+ write_client_reg(SYSCKENA, 0x00000001, TRUE);
+ write_client_reg(CLKENB, 0x000000EF, TRUE);
+ write_client_reg(GPIODATA, 0x03FF0000, TRUE);
+ write_client_reg(GPIODIR, 0x0000024D, TRUE);
+ write_client_reg(GPIOSEL, 0x00000173, TRUE);
+ write_client_reg(GPIOPC, 0x03C300C0, TRUE);
+ write_client_reg(WKREQ, 0x00000000, TRUE);
+ write_client_reg(GPIOIS, 0x00000000, TRUE);
+ write_client_reg(GPIOIEV, 0x00000001, TRUE);
+ write_client_reg(GPIOIC, 0x000003FF, TRUE);
+ write_client_reg(GPIODATA, 0x00060006, TRUE);
+ write_client_reg(GPIODATA, 0x00080008, TRUE);
+ write_client_reg(GPIODATA, 0x02000200, TRUE);
+
+ if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA) {
+ mddi_wait(400);
+ write_client_reg(DRAMPWR, 0x00000001, TRUE);
+
+ write_client_reg(CNT_DIS, 0x00000002, TRUE);
+ write_client_reg(BITMAP0, 0x01E00320, TRUE);
+ write_client_reg(PORT_ENB, 0x00000001, TRUE);
+ write_client_reg(PORT, 0x00000004, TRUE);
+ write_client_reg(PXL, 0x0000003A, TRUE);
+ write_client_reg(MPLFBUF, 0x00000000, TRUE);
+ write_client_reg(HCYCLE, 0x00000253, TRUE);
+ write_client_reg(HSW, 0x00000003, TRUE);
+ write_client_reg(HDE_START, 0x00000017, TRUE);
+ write_client_reg(HDE_SIZE, 0x0000018F, TRUE);
+ write_client_reg(VCYCLE, 0x000001FF, TRUE);
+ write_client_reg(VSW, 0x00000001, TRUE);
+ write_client_reg(VDE_START, 0x00000003, TRUE);
+ write_client_reg(VDE_SIZE, 0x000001DF, TRUE);
+ write_client_reg(START, 0x00000001, TRUE);
+ mddi_wait(1);
+ write_client_reg(TIMER0CTRL, 0x00000060, TRUE);
+ write_client_reg(TIMER0LOAD, 0x00001388, TRUE);
+ write_client_reg(TIMER1CTRL, 0x00000060, TRUE);
+ write_client_reg(TIMER1LOAD, 0x00001388, TRUE);
+ write_client_reg(PWM1OFF, 0x00000087, TRUE);
+ } else {
+ write_client_reg(DRAMPWR, 0x00000001, TRUE);
+ write_client_reg(TIMER0CTRL, 0x00000060, TRUE);
+ write_client_reg(TIMER0LOAD, 0x00001388, TRUE);
+ write_client_reg(TIMER1CTRL, 0x00000060, TRUE);
+ write_client_reg(TIMER1LOAD, 0x00001388, TRUE);
+ write_client_reg(PWM1OFF, 0x00001387, TRUE);
+ }
+
+ write_client_reg(TIMER0CTRL, 0x000000E0, TRUE);
+ write_client_reg(TIMER1CTRL, 0x000000E0, TRUE);
+ write_client_reg(PWMCR, 0x00000003, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSICTL, 0x00000799, TRUE);
+ write_client_reg(SSITIME, 0x00000100, TRUE);
+ write_client_reg(SSICTL, 0x0000079b, TRUE);
+ write_client_reg(SSITX, 0x00000000, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX, 0x00000000, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX, 0x00000000, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX, 0x000800BA, TRUE);
+ write_client_reg(SSITX, 0x00000111, TRUE);
+ write_client_reg(SSITX, 0x00080036, TRUE);
+ write_client_reg(SSITX, 0x00000100, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800BB, TRUE);
+ write_client_reg(SSITX, 0x00000100, TRUE);
+ write_client_reg(SSITX, 0x0008003A, TRUE);
+ write_client_reg(SSITX, 0x00000160, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800BF, TRUE);
+ write_client_reg(SSITX, 0x00000100, TRUE);
+ write_client_reg(SSITX, 0x000800B1, TRUE);
+ write_client_reg(SSITX, 0x0000015D, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800B2, TRUE);
+ write_client_reg(SSITX, 0x00000133, TRUE);
+ write_client_reg(SSITX, 0x000800B3, TRUE);
+ write_client_reg(SSITX, 0x00000122, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800B4, TRUE);
+ write_client_reg(SSITX, 0x00000102, TRUE);
+ write_client_reg(SSITX, 0x000800B5, TRUE);
+ write_client_reg(SSITX, 0x0000011F, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800B6, TRUE);
+ write_client_reg(SSITX, 0x00000128, TRUE);
+ write_client_reg(SSITX, 0x000800B7, TRUE);
+ write_client_reg(SSITX, 0x00000103, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800B9, TRUE);
+ write_client_reg(SSITX, 0x00000120, TRUE);
+ write_client_reg(SSITX, 0x000800BD, TRUE);
+ write_client_reg(SSITX, 0x00000102, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800BE, TRUE);
+ write_client_reg(SSITX, 0x00000100, TRUE);
+ write_client_reg(SSITX, 0x000800C0, TRUE);
+ write_client_reg(SSITX, 0x00000111, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800C1, TRUE);
+ write_client_reg(SSITX, 0x00000111, TRUE);
+ write_client_reg(SSITX, 0x000800C2, TRUE);
+ write_client_reg(SSITX, 0x00000111, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800C3, TRUE);
+ write_client_reg(SSITX, 0x0008010A, TRUE);
+ write_client_reg(SSITX, 0x0000010A, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800C4, TRUE);
+ write_client_reg(SSITX, 0x00080160, TRUE);
+ write_client_reg(SSITX, 0x00000160, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800C5, TRUE);
+ write_client_reg(SSITX, 0x00080160, TRUE);
+ write_client_reg(SSITX, 0x00000160, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800C6, TRUE);
+ write_client_reg(SSITX, 0x00080160, TRUE);
+ write_client_reg(SSITX, 0x00000160, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800C7, TRUE);
+ write_client_reg(SSITX, 0x00080133, TRUE);
+ write_client_reg(SSITX, 0x00000143, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800C8, TRUE);
+ write_client_reg(SSITX, 0x00000144, TRUE);
+ write_client_reg(SSITX, 0x000800C9, TRUE);
+ write_client_reg(SSITX, 0x00000133, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800CA, TRUE);
+ write_client_reg(SSITX, 0x00000100, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800EC, TRUE);
+ write_client_reg(SSITX, 0x00080102, TRUE);
+ write_client_reg(SSITX, 0x00000118, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800CF, TRUE);
+ write_client_reg(SSITX, 0x00000101, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800D0, TRUE);
+ write_client_reg(SSITX, 0x00080110, TRUE);
+ write_client_reg(SSITX, 0x00000104, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800D1, TRUE);
+ write_client_reg(SSITX, 0x00000101, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800D2, TRUE);
+ write_client_reg(SSITX, 0x00080100, TRUE);
+ write_client_reg(SSITX, 0x0000013A, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800D3, TRUE);
+ write_client_reg(SSITX, 0x00080100, TRUE);
+ write_client_reg(SSITX, 0x0000013A, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800D4, TRUE);
+ write_client_reg(SSITX, 0x00080124, TRUE);
+ write_client_reg(SSITX, 0x0000016E, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX, 0x000800D5, TRUE);
+ write_client_reg(SSITX, 0x00000124, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800ED, TRUE);
+ write_client_reg(SSITX, 0x00080101, TRUE);
+ write_client_reg(SSITX, 0x0000010A, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800D6, TRUE);
+ write_client_reg(SSITX, 0x00000101, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800D7, TRUE);
+ write_client_reg(SSITX, 0x00080110, TRUE);
+ write_client_reg(SSITX, 0x0000010A, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800D8, TRUE);
+ write_client_reg(SSITX, 0x00000101, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800D9, TRUE);
+ write_client_reg(SSITX, 0x00080100, TRUE);
+ write_client_reg(SSITX, 0x00000114, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800DE, TRUE);
+ write_client_reg(SSITX, 0x00080100, TRUE);
+ write_client_reg(SSITX, 0x00000114, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800DF, TRUE);
+ write_client_reg(SSITX, 0x00080112, TRUE);
+ write_client_reg(SSITX, 0x0000013F, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800E0, TRUE);
+ write_client_reg(SSITX, 0x0000010B, TRUE);
+ write_client_reg(SSITX, 0x000800E2, TRUE);
+ write_client_reg(SSITX, 0x00000101, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800E3, TRUE);
+ write_client_reg(SSITX, 0x00000136, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800E4, TRUE);
+ write_client_reg(SSITX, 0x00080100, TRUE);
+ write_client_reg(SSITX, 0x00000103, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800E5, TRUE);
+ write_client_reg(SSITX, 0x00080102, TRUE);
+ write_client_reg(SSITX, 0x00000104, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800E6, TRUE);
+ write_client_reg(SSITX, 0x00000103, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800E7, TRUE);
+ write_client_reg(SSITX, 0x00080104, TRUE);
+ write_client_reg(SSITX, 0x0000010A, TRUE);
+ mddi_wait(2);
+ write_client_reg(SSITX, 0x000800E8, TRUE);
+ write_client_reg(SSITX, 0x00000104, TRUE);
+ write_client_reg(CLKENB, 0x000001EF, TRUE);
+ write_client_reg(START, 0x00000000, TRUE);
+ write_client_reg(WRSTB, 0x0000003F, TRUE);
+ write_client_reg(RDSTB, 0x00000432, TRUE);
+ write_client_reg(PORT_ENB, 0x00000002, TRUE);
+ write_client_reg(VSYNIF, 0x00000000, TRUE);
+ write_client_reg(ASY_DATA, 0x80000000, TRUE);
+ write_client_reg(ASY_DATB, 0x00000001, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(10);
+ write_client_reg(ASY_DATA, 0x80000000, TRUE);
+ write_client_reg(ASY_DATB, 0x80000000, TRUE);
+ write_client_reg(ASY_DATC, 0x80000000, TRUE);
+ write_client_reg(ASY_DATD, 0x80000000, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
+ write_client_reg(ASY_DATA, 0x80000007, TRUE);
+ write_client_reg(ASY_DATB, 0x00004005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(20);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x00000000, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ write_client_reg(VSYNIF, 0x00000001, TRUE);
+ write_client_reg(PORT_ENB, 0x00000001, TRUE);
+ }
+
+ mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_SEC_STANDBY,
+ TOSHIBA_STATE_PRIM_SEC_READY);
+}
+
+static void toshiba_prim_start(struct msm_fb_data_type *mfd)
+{
+ if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+ return;
+
+ if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) {
+ write_client_reg(BITMAP1, 0x01E000F0, TRUE);
+ write_client_reg(BITMAP2, 0x01E000F0, TRUE);
+ write_client_reg(BITMAP3, 0x01E000F0, TRUE);
+ write_client_reg(BITMAP4, 0x00DC00B0, TRUE);
+ write_client_reg(CLKENB, 0x000001EF, TRUE);
+ write_client_reg(PORT_ENB, 0x00000001, TRUE);
+ write_client_reg(PORT, 0x00000016, TRUE);
+ write_client_reg(PXL, 0x00000002, TRUE);
+ write_client_reg(MPLFBUF, 0x00000000, TRUE);
+ write_client_reg(HCYCLE, 0x00000185, TRUE);
+ write_client_reg(HSW, 0x00000018, TRUE);
+ write_client_reg(HDE_START, 0x0000004A, TRUE);
+ write_client_reg(HDE_SIZE, 0x000000EF, TRUE);
+ write_client_reg(VCYCLE, 0x0000028E, TRUE);
+ write_client_reg(VSW, 0x00000004, TRUE);
+ write_client_reg(VDE_START, 0x00000009, TRUE);
+ write_client_reg(VDE_SIZE, 0x0000027F, TRUE);
+ write_client_reg(START, 0x00000001, TRUE);
+ write_client_reg(SYSTEM_BLOCK1_BASE, 0x00000002, TRUE);
+ } else{
+
+ write_client_reg(VSYNIF, 0x00000001, TRUE);
+ write_client_reg(PORT_ENB, 0x00000001, TRUE);
+ write_client_reg(BITMAP1, 0x01E000F0, TRUE);
+ write_client_reg(BITMAP2, 0x01E000F0, TRUE);
+ write_client_reg(BITMAP3, 0x01E000F0, TRUE);
+ write_client_reg(BITMAP4, 0x00DC00B0, TRUE);
+ write_client_reg(CLKENB, 0x000001EF, TRUE);
+ write_client_reg(PORT_ENB, 0x00000001, TRUE);
+ write_client_reg(PORT, 0x00000004, TRUE);
+ write_client_reg(PXL, 0x00000002, TRUE);
+ write_client_reg(MPLFBUF, 0x00000000, TRUE);
+
+ if (mddi_toshiba_61Hz_refresh) {
+ write_client_reg(HCYCLE, 0x000000FC, TRUE);
+ mddi_toshiba_rows_per_second = 39526;
+ mddi_toshiba_rows_per_refresh = 646;
+ mddi_toshiba_usecs_per_refresh = 16344;
+ } else {
+ write_client_reg(HCYCLE, 0x0000010b, TRUE);
+ mddi_toshiba_rows_per_second = 37313;
+ mddi_toshiba_rows_per_refresh = 646;
+ mddi_toshiba_usecs_per_refresh = 17313;
+ }
+
+ write_client_reg(HSW, 0x00000003, TRUE);
+ write_client_reg(HDE_START, 0x00000007, TRUE);
+ write_client_reg(HDE_SIZE, 0x000000EF, TRUE);
+ write_client_reg(VCYCLE, 0x00000285, TRUE);
+ write_client_reg(VSW, 0x00000001, TRUE);
+ write_client_reg(VDE_START, 0x00000003, TRUE);
+ write_client_reg(VDE_SIZE, 0x0000027F, TRUE);
+ write_client_reg(START, 0x00000001, TRUE);
+ mddi_wait(10);
+ write_client_reg(SSITX, 0x000800BC, TRUE);
+ write_client_reg(SSITX, 0x00000180, TRUE);
+ write_client_reg(SSITX, 0x0008003B, TRUE);
+ write_client_reg(SSITX, 0x00000100, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX, 0x000800B0, TRUE);
+ write_client_reg(SSITX, 0x00000116, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX, 0x000800B8, TRUE);
+ write_client_reg(SSITX, 0x000801FF, TRUE);
+ write_client_reg(SSITX, 0x000001F5, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX, 0x00000011, TRUE);
+ write_client_reg(SSITX, 0x00000029, TRUE);
+ write_client_reg(WKREQ, 0x00000000, TRUE);
+ write_client_reg(WAKEUP, 0x00000000, TRUE);
+ write_client_reg(INTMSK, 0x00000001, TRUE);
+ }
+
+ mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_SEC_READY,
+ TOSHIBA_STATE_PRIM_NORMAL_MODE);
+}
+
+static void toshiba_sec_start(struct msm_fb_data_type *mfd)
+{
+ if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+ return;
+
+ write_client_reg(VSYNIF, 0x00000000, TRUE);
+ write_client_reg(PORT_ENB, 0x00000002, TRUE);
+ write_client_reg(CLKENB, 0x000011EF, TRUE);
+ write_client_reg(BITMAP0, 0x028001E0, TRUE);
+ write_client_reg(BITMAP1, 0x00000000, TRUE);
+ write_client_reg(BITMAP2, 0x00000000, TRUE);
+ write_client_reg(BITMAP3, 0x00000000, TRUE);
+ write_client_reg(BITMAP4, 0x00DC00B0, TRUE);
+ write_client_reg(PORT, 0x00000000, TRUE);
+ write_client_reg(PXL, 0x00000000, TRUE);
+ write_client_reg(MPLFBUF, 0x00000004, TRUE);
+ write_client_reg(HCYCLE, 0x0000006B, TRUE);
+ write_client_reg(HSW, 0x00000003, TRUE);
+ write_client_reg(HDE_START, 0x00000007, TRUE);
+ write_client_reg(HDE_SIZE, 0x00000057, TRUE);
+ write_client_reg(VCYCLE, 0x000000E6, TRUE);
+ write_client_reg(VSW, 0x00000001, TRUE);
+ write_client_reg(VDE_START, 0x00000003, TRUE);
+ write_client_reg(VDE_SIZE, 0x000000DB, TRUE);
+ write_client_reg(ASY_DATA, 0x80000001, TRUE);
+ write_client_reg(ASY_DATB, 0x0000011B, TRUE);
+ write_client_reg(ASY_DATC, 0x80000002, TRUE);
+ write_client_reg(ASY_DATD, 0x00000700, TRUE);
+ write_client_reg(ASY_DATE, 0x80000003, TRUE);
+ write_client_reg(ASY_DATF, 0x00000230, TRUE);
+ write_client_reg(ASY_DATG, 0x80000008, TRUE);
+ write_client_reg(ASY_DATH, 0x00000402, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+ write_client_reg(ASY_DATA, 0x80000009, TRUE);
+ write_client_reg(ASY_DATB, 0x00000000, TRUE);
+ write_client_reg(ASY_DATC, 0x8000000B, TRUE);
+ write_client_reg(ASY_DATD, 0x00000000, TRUE);
+ write_client_reg(ASY_DATE, 0x8000000C, TRUE);
+ write_client_reg(ASY_DATF, 0x00000000, TRUE);
+ write_client_reg(ASY_DATG, 0x8000000D, TRUE);
+ write_client_reg(ASY_DATH, 0x00000409, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+ write_client_reg(ASY_DATA, 0x8000000E, TRUE);
+ write_client_reg(ASY_DATB, 0x00000409, TRUE);
+ write_client_reg(ASY_DATC, 0x80000030, TRUE);
+ write_client_reg(ASY_DATD, 0x00000000, TRUE);
+ write_client_reg(ASY_DATE, 0x80000031, TRUE);
+ write_client_reg(ASY_DATF, 0x00000100, TRUE);
+ write_client_reg(ASY_DATG, 0x80000032, TRUE);
+ write_client_reg(ASY_DATH, 0x00000104, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+ write_client_reg(ASY_DATA, 0x80000033, TRUE);
+ write_client_reg(ASY_DATB, 0x00000400, TRUE);
+ write_client_reg(ASY_DATC, 0x80000034, TRUE);
+ write_client_reg(ASY_DATD, 0x00000306, TRUE);
+ write_client_reg(ASY_DATE, 0x80000035, TRUE);
+ write_client_reg(ASY_DATF, 0x00000706, TRUE);
+ write_client_reg(ASY_DATG, 0x80000036, TRUE);
+ write_client_reg(ASY_DATH, 0x00000707, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+ write_client_reg(ASY_DATA, 0x80000037, TRUE);
+ write_client_reg(ASY_DATB, 0x00000004, TRUE);
+ write_client_reg(ASY_DATC, 0x80000038, TRUE);
+ write_client_reg(ASY_DATD, 0x00000000, TRUE);
+ write_client_reg(ASY_DATE, 0x80000039, TRUE);
+ write_client_reg(ASY_DATF, 0x00000000, TRUE);
+ write_client_reg(ASY_DATG, 0x8000003A, TRUE);
+ write_client_reg(ASY_DATH, 0x00000001, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+ write_client_reg(ASY_DATA, 0x80000044, TRUE);
+ write_client_reg(ASY_DATB, 0x0000AF00, TRUE);
+ write_client_reg(ASY_DATC, 0x80000045, TRUE);
+ write_client_reg(ASY_DATD, 0x0000DB00, TRUE);
+ write_client_reg(ASY_DATE, 0x08000042, TRUE);
+ write_client_reg(ASY_DATF, 0x0000DB00, TRUE);
+ write_client_reg(ASY_DATG, 0x80000021, TRUE);
+ write_client_reg(ASY_DATH, 0x00000000, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+ write_client_reg(PXL, 0x0000000C, TRUE);
+ write_client_reg(VSYNIF, 0x00000001, TRUE);
+ write_client_reg(ASY_DATA, 0x80000022, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000003, TRUE);
+ write_client_reg(START, 0x00000001, TRUE);
+ mddi_wait(60);
+ write_client_reg(PXL, 0x00000000, TRUE);
+ write_client_reg(VSYNIF, 0x00000000, TRUE);
+ write_client_reg(START, 0x00000000, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+ write_client_reg(ASY_DATA, 0x80000050, TRUE);
+ write_client_reg(ASY_DATB, 0x00000000, TRUE);
+ write_client_reg(ASY_DATC, 0x80000051, TRUE);
+ write_client_reg(ASY_DATD, 0x00000E00, TRUE);
+ write_client_reg(ASY_DATE, 0x80000052, TRUE);
+ write_client_reg(ASY_DATF, 0x00000D01, TRUE);
+ write_client_reg(ASY_DATG, 0x80000053, TRUE);
+ write_client_reg(ASY_DATH, 0x00000000, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+ write_client_reg(ASY_DATA, 0x80000058, TRUE);
+ write_client_reg(ASY_DATB, 0x00000000, TRUE);
+ write_client_reg(ASY_DATC, 0x8000005A, TRUE);
+ write_client_reg(ASY_DATD, 0x00000E01, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
+ write_client_reg(ASY_DATA, 0x80000011, TRUE);
+ write_client_reg(ASY_DATB, 0x00000812, TRUE);
+ write_client_reg(ASY_DATC, 0x80000012, TRUE);
+ write_client_reg(ASY_DATD, 0x00000003, TRUE);
+ write_client_reg(ASY_DATE, 0x80000013, TRUE);
+ write_client_reg(ASY_DATF, 0x00000909, TRUE);
+ write_client_reg(ASY_DATG, 0x80000010, TRUE);
+ write_client_reg(ASY_DATH, 0x00000040, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+ mddi_wait(40);
+ write_client_reg(ASY_DATA, 0x80000010, TRUE);
+ write_client_reg(ASY_DATB, 0x00000340, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(60);
+ write_client_reg(ASY_DATA, 0x80000010, TRUE);
+ write_client_reg(ASY_DATB, 0x00003340, TRUE);
+ write_client_reg(ASY_DATC, 0x80000007, TRUE);
+ write_client_reg(ASY_DATD, 0x00004007, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
+ mddi_wait(1);
+ write_client_reg(ASY_DATA, 0x80000007, TRUE);
+ write_client_reg(ASY_DATB, 0x00004017, TRUE);
+ write_client_reg(ASY_DATC, 0x8000005B, TRUE);
+ write_client_reg(ASY_DATD, 0x00000000, TRUE);
+ write_client_reg(ASY_DATE, 0x80000059, TRUE);
+ write_client_reg(ASY_DATF, 0x00000011, TRUE);
+ write_client_reg(ASY_CMDSET, 0x0000000D, TRUE);
+ write_client_reg(ASY_CMDSET, 0x0000000C, TRUE);
+ mddi_wait(20);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ /* LTPS I/F control */
+ write_client_reg(ASY_DATB, 0x00000019, TRUE);
+ /* Direct cmd transfer enable */
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ /* Direct cmd transfer disable */
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(20);
+ /* Index setting of SUB LCDD */
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ /* LTPS I/F control */
+ write_client_reg(ASY_DATB, 0x00000079, TRUE);
+ /* Direct cmd transfer enable */
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ /* Direct cmd transfer disable */
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(20);
+ /* Index setting of SUB LCDD */
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ /* LTPS I/F control */
+ write_client_reg(ASY_DATB, 0x000003FD, TRUE);
+ /* Direct cmd transfer enable */
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ /* Direct cmd transfer disable */
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(20);
+ mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_SEC_READY,
+ TOSHIBA_STATE_SEC_NORMAL_MODE);
+}
+
+static void toshiba_prim_lcd_off(struct msm_fb_data_type *mfd)
+{
+ if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) {
+ gordon_disp_off();
+ } else{
+
+ /* Main panel power off (Deep standby in) */
+ write_client_reg(SSITX, 0x000800BC, TRUE);
+ write_client_reg(SSITX, 0x00000100, TRUE);
+ write_client_reg(SSITX, 0x00000028, TRUE);
+ mddi_wait(1);
+ write_client_reg(SSITX, 0x000800B8, TRUE);
+ write_client_reg(SSITX, 0x00000180, TRUE);
+ write_client_reg(SSITX, 0x00000102, TRUE);
+ write_client_reg(SSITX, 0x00000010, TRUE);
+ }
+ write_client_reg(PORT, 0x00000003, TRUE);
+ write_client_reg(REGENB, 0x00000001, TRUE);
+ mddi_wait(1);
+ write_client_reg(PXL, 0x00000000, TRUE);
+ write_client_reg(START, 0x00000000, TRUE);
+ write_client_reg(REGENB, 0x00000001, TRUE);
+ mddi_wait(3);
+ if (TM_GET_PID(mfd->panel.id) != LCD_SHARP_2P4_VGA) {
+ write_client_reg(SSITX, 0x000800B0, TRUE);
+ write_client_reg(SSITX, 0x00000100, TRUE);
+ }
+ mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_NORMAL_MODE,
+ TOSHIBA_STATE_PRIM_SEC_STANDBY);
+}
+
+static void toshiba_sec_lcd_off(struct msm_fb_data_type *mfd)
+{
+ if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+ return;
+
+ write_client_reg(VSYNIF, 0x00000000, TRUE);
+ write_client_reg(PORT_ENB, 0x00000002, TRUE);
+ write_client_reg(ASY_DATA, 0x80000007, TRUE);
+ write_client_reg(ASY_DATB, 0x00004016, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x00000019, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x0000000B, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x00000002, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(4);
+ write_client_reg(ASY_DATA, 0x80000010, TRUE);
+ write_client_reg(ASY_DATB, 0x00000300, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(4);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x00000000, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+ write_client_reg(ASY_DATA, 0x80000007, TRUE);
+ write_client_reg(ASY_DATB, 0x00004004, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+ write_client_reg(PORT, 0x00000000, TRUE);
+ write_client_reg(PXL, 0x00000000, TRUE);
+ write_client_reg(START, 0x00000000, TRUE);
+ write_client_reg(VSYNIF, 0x00000001, TRUE);
+ write_client_reg(PORT_ENB, 0x00000001, TRUE);
+ write_client_reg(REGENB, 0x00000001, TRUE);
+ mddi_toshiba_state_transition(TOSHIBA_STATE_SEC_NORMAL_MODE,
+ TOSHIBA_STATE_PRIM_SEC_STANDBY);
+}
+
+static void toshiba_sec_cont_update_start(struct msm_fb_data_type *mfd)
+{
+
+ if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+ return;
+
+ write_client_reg(VSYNIF, 0x00000000, TRUE);
+ write_client_reg(PORT_ENB, 0x00000002, TRUE);
+ write_client_reg(INTMASK, 0x00000001, TRUE);
+ write_client_reg(TTBUSSEL, 0x0000000B, TRUE);
+ write_client_reg(MONI, 0x00000008, TRUE);
+ write_client_reg(CLKENB, 0x000000EF, TRUE);
+ write_client_reg(CLKENB, 0x000010EF, TRUE);
+ write_client_reg(CLKENB, 0x000011EF, TRUE);
+ write_client_reg(BITMAP4, 0x00DC00B0, TRUE);
+ write_client_reg(HCYCLE, 0x0000006B, TRUE);
+ write_client_reg(HSW, 0x00000003, TRUE);
+ write_client_reg(HDE_START, 0x00000002, TRUE);
+ write_client_reg(HDE_SIZE, 0x00000057, TRUE);
+ write_client_reg(VCYCLE, 0x000000E6, TRUE);
+ write_client_reg(VSW, 0x00000001, TRUE);
+ write_client_reg(VDE_START, 0x00000003, TRUE);
+ write_client_reg(VDE_SIZE, 0x000000DB, TRUE);
+ write_client_reg(WRSTB, 0x00000015, TRUE);
+ write_client_reg(MPLFBUF, 0x00000004, TRUE);
+ write_client_reg(ASY_DATA, 0x80000021, TRUE);
+ write_client_reg(ASY_DATB, 0x00000000, TRUE);
+ write_client_reg(ASY_DATC, 0x80000022, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000007, TRUE);
+ write_client_reg(PXL, 0x00000089, TRUE);
+ write_client_reg(VSYNIF, 0x00000001, TRUE);
+ mddi_wait(2);
+}
+
+static void toshiba_sec_cont_update_stop(struct msm_fb_data_type *mfd)
+{
+ if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+ return;
+
+ write_client_reg(PXL, 0x00000000, TRUE);
+ write_client_reg(VSYNIF, 0x00000000, TRUE);
+ write_client_reg(START, 0x00000000, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+ mddi_wait(3);
+ write_client_reg(SRST, 0x00000002, TRUE);
+ mddi_wait(3);
+ write_client_reg(SRST, 0x00000003, TRUE);
+}
+
+static void toshiba_sec_backlight_on(struct msm_fb_data_type *mfd)
+{
+ if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+ return;
+
+ write_client_reg(TIMER0CTRL, 0x00000060, TRUE);
+ write_client_reg(TIMER0LOAD, 0x00001388, TRUE);
+ write_client_reg(PWM0OFF, 0x00000001, TRUE);
+ write_client_reg(TIMER1CTRL, 0x00000060, TRUE);
+ write_client_reg(TIMER1LOAD, 0x00001388, TRUE);
+ write_client_reg(PWM1OFF, 0x00001387, TRUE);
+ write_client_reg(TIMER0CTRL, 0x000000E0, TRUE);
+ write_client_reg(TIMER1CTRL, 0x000000E0, TRUE);
+ write_client_reg(PWMCR, 0x00000003, TRUE);
+}
+
+static void toshiba_sec_sleep_in(struct msm_fb_data_type *mfd)
+{
+ if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+ return;
+
+ write_client_reg(VSYNIF, 0x00000000, TRUE);
+ write_client_reg(PORT_ENB, 0x00000002, TRUE);
+ write_client_reg(ASY_DATA, 0x80000007, TRUE);
+ write_client_reg(ASY_DATB, 0x00004016, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x00000019, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x0000000B, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x00000002, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(4);
+ write_client_reg(ASY_DATA, 0x80000010, TRUE);
+ write_client_reg(ASY_DATB, 0x00000300, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(4);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x00000000, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+ write_client_reg(ASY_DATA, 0x80000007, TRUE);
+ write_client_reg(ASY_DATB, 0x00004004, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+ write_client_reg(PORT, 0x00000000, TRUE);
+ write_client_reg(PXL, 0x00000000, TRUE);
+ write_client_reg(START, 0x00000000, TRUE);
+ write_client_reg(REGENB, 0x00000001, TRUE);
+ /* Sleep in sequence */
+ write_client_reg(ASY_DATA, 0x80000010, TRUE);
+ write_client_reg(ASY_DATB, 0x00000302, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+}
+
+static void toshiba_sec_sleep_out(struct msm_fb_data_type *mfd)
+{
+ if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+ return;
+
+ write_client_reg(VSYNIF, 0x00000000, TRUE);
+ write_client_reg(PORT_ENB, 0x00000002, TRUE);
+ write_client_reg(ASY_DATA, 0x80000010, TRUE);
+ write_client_reg(ASY_DATB, 0x00000300, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ /* Display ON sequence */
+ write_client_reg(ASY_DATA, 0x80000011, TRUE);
+ write_client_reg(ASY_DATB, 0x00000812, TRUE);
+ write_client_reg(ASY_DATC, 0x80000012, TRUE);
+ write_client_reg(ASY_DATD, 0x00000003, TRUE);
+ write_client_reg(ASY_DATE, 0x80000013, TRUE);
+ write_client_reg(ASY_DATF, 0x00000909, TRUE);
+ write_client_reg(ASY_DATG, 0x80000010, TRUE);
+ write_client_reg(ASY_DATH, 0x00000040, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+ mddi_wait(4);
+ write_client_reg(ASY_DATA, 0x80000010, TRUE);
+ write_client_reg(ASY_DATB, 0x00000340, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(6);
+ write_client_reg(ASY_DATA, 0x80000010, TRUE);
+ write_client_reg(ASY_DATB, 0x00003340, TRUE);
+ write_client_reg(ASY_DATC, 0x80000007, TRUE);
+ write_client_reg(ASY_DATD, 0x00004007, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
+ mddi_wait(1);
+ write_client_reg(ASY_DATA, 0x80000007, TRUE);
+ write_client_reg(ASY_DATB, 0x00004017, TRUE);
+ write_client_reg(ASY_DATC, 0x8000005B, TRUE);
+ write_client_reg(ASY_DATD, 0x00000000, TRUE);
+ write_client_reg(ASY_DATE, 0x80000059, TRUE);
+ write_client_reg(ASY_DATF, 0x00000011, TRUE);
+ write_client_reg(ASY_CMDSET, 0x0000000D, TRUE);
+ write_client_reg(ASY_CMDSET, 0x0000000C, TRUE);
+ mddi_wait(2);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x00000019, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x00000079, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+ write_client_reg(ASY_DATA, 0x80000059, TRUE);
+ write_client_reg(ASY_DATB, 0x000003FD, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+ write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+ mddi_wait(2);
+}
+
+static void mddi_toshiba_lcd_set_backlight(struct msm_fb_data_type *mfd)
+{
+ int32 level;
+ int ret = -EPERM;
+ int max = mfd->panel_info.bl_max;
+ int min = mfd->panel_info.bl_min;
+
+ if (mddi_toshiba_pdata && mddi_toshiba_pdata->pmic_backlight) {
+ ret = mddi_toshiba_pdata->pmic_backlight(mfd->bl_level);
+ if (!ret)
+ return;
+ }
+
+ if (ret && mddi_toshiba_pdata && mddi_toshiba_pdata->backlight_level) {
+ level = mddi_toshiba_pdata->backlight_level(mfd->bl_level,
+ max, min);
+
+ if (level < 0)
+ return;
+
+ if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA)
+ write_client_reg(TIMER0LOAD, 0x00001388, TRUE);
+ } else {
+ if (!max)
+ level = 0;
+ else
+ level = (mfd->bl_level * 4999) / max;
+ }
+
+ write_client_reg(PWM0OFF, level, TRUE);
+}
+
+static void mddi_toshiba_vsync_set_handler(msm_fb_vsync_handler_type handler, /* ISR to be executed */
+ void *arg)
+{
+ boolean error = FALSE;
+ unsigned long flags;
+
+ /* Disable interrupts */
+ spin_lock_irqsave(&mddi_host_spin_lock, flags);
+ /* INTLOCK(); */
+
+ if (mddi_toshiba_vsync_handler != NULL) {
+ error = TRUE;
+ } else {
+ /* Register the handler for this particular GROUP interrupt source */
+ mddi_toshiba_vsync_handler = handler;
+ mddi_toshiba_vsync_handler_arg = arg;
+ }
+
+ /* Restore interrupts */
+ spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+ /* MDDI_INTFREE(); */
+ if (error) {
+ MDDI_MSG_ERR("MDDI: Previous Vsync handler never called\n");
+ } else {
+ /* Enable the vsync wakeup */
+ mddi_queue_register_write(INTMSK, 0x0000, FALSE, 0);
+
+ mddi_toshiba_vsync_attempts = 1;
+ mddi_vsync_detect_enabled = TRUE;
+ }
+} /* mddi_toshiba_vsync_set_handler */
+
+static void mddi_toshiba_lcd_vsync_detected(boolean detected)
+{
+ /* static timetick_type start_time = 0; */
+ static struct timeval start_time;
+ static boolean first_time = TRUE;
+ /* uint32 mdp_cnt_val = 0; */
+ /* timetick_type elapsed_us; */
+ struct timeval now;
+ uint32 elapsed_us;
+ uint32 num_vsyncs;
+
+ if ((detected) || (mddi_toshiba_vsync_attempts > 5)) {
+ if ((detected) && (mddi_toshiba_monitor_refresh_value)) {
+ /* if (start_time != 0) */
+ if (!first_time) {
+ jiffies_to_timeval(jiffies, &now);
+ elapsed_us =
+ (now.tv_sec - start_time.tv_sec) * 1000000 +
+ now.tv_usec - start_time.tv_usec;
+ /*
+ * LCD is configured for a refresh every usecs,
+ * so to determine the number of vsyncs that
+ * have occurred since the last measurement
+ * add half that to the time difference and
+ * divide by the refresh rate.
+ */
+ num_vsyncs = (elapsed_us +
+ (mddi_toshiba_usecs_per_refresh >>
+ 1)) /
+ mddi_toshiba_usecs_per_refresh;
+ /*
+ * LCD is configured for * hsyncs (rows) per
+ * refresh cycle. Calculate new rows_per_second
+ * value based upon these new measurements.
+ * MDP can update with this new value.
+ */
+ mddi_toshiba_rows_per_second =
+ (mddi_toshiba_rows_per_refresh * 1000 *
+ num_vsyncs) / (elapsed_us / 1000);
+ }
+ /* start_time = timetick_get(); */
+ first_time = FALSE;
+ jiffies_to_timeval(jiffies, &start_time);
+ if (mddi_toshiba_report_refresh_measurements) {
+ (void)mddi_queue_register_read_int(VPOS,
+ &mddi_toshiba_curr_vpos);
+ /* mdp_cnt_val = MDP_LINE_COUNT; */
+ }
+ }
+ /* if detected = TRUE, client initiated wakeup was detected */
+ if (mddi_toshiba_vsync_handler != NULL) {
+ (*mddi_toshiba_vsync_handler)
+ (mddi_toshiba_vsync_handler_arg);
+ mddi_toshiba_vsync_handler = NULL;
+ }
+ mddi_vsync_detect_enabled = FALSE;
+ mddi_toshiba_vsync_attempts = 0;
+ /* need to disable the interrupt wakeup */
+ if (!mddi_queue_register_write_int(INTMSK, 0x0001))
+ MDDI_MSG_ERR("Vsync interrupt disable failed!\n");
+ if (!detected) {
+ /* give up after 5 failed attempts but show error */
+ MDDI_MSG_NOTICE("Vsync detection failed!\n");
+ } else if ((mddi_toshiba_monitor_refresh_value) &&
+ (mddi_toshiba_report_refresh_measurements)) {
+ MDDI_MSG_NOTICE(" Last Line Counter=%d!\n",
+ mddi_toshiba_curr_vpos);
+ /* MDDI_MSG_NOTICE(" MDP Line Counter=%d!\n",mdp_cnt_val); */
+ MDDI_MSG_NOTICE(" Lines Per Second=%d!\n",
+ mddi_toshiba_rows_per_second);
+ }
+ /* clear the interrupt */
+ if (!mddi_queue_register_write_int(INTFLG, 0x0001))
+ MDDI_MSG_ERR("Vsync interrupt clear failed!\n");
+ } else {
+ /* if detected = FALSE, we woke up from hibernation, but did not
+ * detect client initiated wakeup.
+ */
+ mddi_toshiba_vsync_attempts++;
+ }
+}
+
+static void mddi_toshiba_prim_init(struct msm_fb_data_type *mfd)
+{
+
+ switch (toshiba_state) {
+ case TOSHIBA_STATE_PRIM_SEC_READY:
+ break;
+ case TOSHIBA_STATE_OFF:
+ toshiba_state = TOSHIBA_STATE_PRIM_SEC_STANDBY;
+ toshiba_common_initial_setup(mfd);
+ break;
+ case TOSHIBA_STATE_PRIM_SEC_STANDBY:
+ toshiba_common_initial_setup(mfd);
+ break;
+ case TOSHIBA_STATE_SEC_NORMAL_MODE:
+ toshiba_sec_cont_update_stop(mfd);
+ toshiba_sec_sleep_in(mfd);
+ toshiba_sec_sleep_out(mfd);
+ toshiba_sec_lcd_off(mfd);
+ toshiba_common_initial_setup(mfd);
+ break;
+ default:
+ MDDI_MSG_ERR("mddi_toshiba_prim_init from state %d\n",
+ toshiba_state);
+ }
+
+ toshiba_prim_start(mfd);
+ if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA)
+ gordon_disp_init();
+ mddi_host_write_pix_attr_reg(0x00C3);
+}
+
+static void mddi_toshiba_sec_init(struct msm_fb_data_type *mfd)
+{
+
+ switch (toshiba_state) {
+ case TOSHIBA_STATE_PRIM_SEC_READY:
+ break;
+ case TOSHIBA_STATE_PRIM_SEC_STANDBY:
+ toshiba_common_initial_setup(mfd);
+ break;
+ case TOSHIBA_STATE_PRIM_NORMAL_MODE:
+ toshiba_prim_lcd_off(mfd);
+ toshiba_common_initial_setup(mfd);
+ break;
+ default:
+ MDDI_MSG_ERR("mddi_toshiba_sec_init from state %d\n",
+ toshiba_state);
+ }
+
+ toshiba_sec_start(mfd);
+ toshiba_sec_backlight_on(mfd);
+ toshiba_sec_cont_update_start(mfd);
+ mddi_host_write_pix_attr_reg(0x0400);
+}
+
+static void mddi_toshiba_lcd_powerdown(struct msm_fb_data_type *mfd)
+{
+ switch (toshiba_state) {
+ case TOSHIBA_STATE_PRIM_SEC_READY:
+ mddi_toshiba_prim_init(mfd);
+ mddi_toshiba_lcd_powerdown(mfd);
+ return;
+ case TOSHIBA_STATE_PRIM_SEC_STANDBY:
+ break;
+ case TOSHIBA_STATE_PRIM_NORMAL_MODE:
+ toshiba_prim_lcd_off(mfd);
+ break;
+ case TOSHIBA_STATE_SEC_NORMAL_MODE:
+ toshiba_sec_cont_update_stop(mfd);
+ toshiba_sec_sleep_in(mfd);
+ toshiba_sec_sleep_out(mfd);
+ toshiba_sec_lcd_off(mfd);
+ break;
+ default:
+ MDDI_MSG_ERR("mddi_toshiba_lcd_powerdown from state %d\n",
+ toshiba_state);
+ }
+}
+
+static int mddi_sharpgordon_firsttime = 1;
+
+static int mddi_toshiba_lcd_on(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ mfd = platform_get_drvdata(pdev);
+ if (!mfd)
+ return -ENODEV;
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ if (TM_GET_DID(mfd->panel.id) == TOSHIBA_VGA_PRIM)
+ mddi_toshiba_prim_init(mfd);
+ else
+ mddi_toshiba_sec_init(mfd);
+ if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) {
+ if (mddi_sharpgordon_firsttime) {
+ mddi_sharpgordon_firsttime = 0;
+ write_client_reg(REGENB, 0x00000001, TRUE);
+ }
+ }
+ return 0;
+}
+
+static int mddi_toshiba_lcd_off(struct platform_device *pdev)
+{
+ mddi_toshiba_lcd_powerdown(platform_get_drvdata(pdev));
+ return 0;
+}
+
+static int __init mddi_toshiba_lcd_probe(struct platform_device *pdev)
+{
+ if (pdev->id == 0) {
+ mddi_toshiba_pdata = pdev->dev.platform_data;
+ return 0;
+ }
+
+ msm_fb_add_device(pdev);
+
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = mddi_toshiba_lcd_probe,
+ .driver = {
+ .name = "mddi_toshiba",
+ },
+};
+
+static struct msm_fb_panel_data toshiba_panel_data = {
+ .on = mddi_toshiba_lcd_on,
+ .off = mddi_toshiba_lcd_off,
+};
+
+static int ch_used[3];
+
+int mddi_toshiba_device_register(struct msm_panel_info *pinfo,
+ u32 channel, u32 panel)
+{
+ struct platform_device *pdev = NULL;
+ int ret;
+
+ if ((channel >= 3) || ch_used[channel])
+ return -ENODEV;
+
+ if ((channel != TOSHIBA_VGA_PRIM) &&
+ mddi_toshiba_pdata && mddi_toshiba_pdata->panel_num)
+ if (mddi_toshiba_pdata->panel_num() < 2)
+ return -ENODEV;
+
+ ch_used[channel] = TRUE;
+
+ pdev = platform_device_alloc("mddi_toshiba", (panel << 8)|channel);
+ if (!pdev)
+ return -ENOMEM;
+
+ if (channel == TOSHIBA_VGA_PRIM) {
+ toshiba_panel_data.set_backlight =
+ mddi_toshiba_lcd_set_backlight;
+
+ if (pinfo->lcd.vsync_enable) {
+ toshiba_panel_data.set_vsync_notifier =
+ mddi_toshiba_vsync_set_handler;
+ mddi_lcd.vsync_detected =
+ mddi_toshiba_lcd_vsync_detected;
+ }
+ } else {
+ toshiba_panel_data.set_backlight = NULL;
+ toshiba_panel_data.set_vsync_notifier = NULL;
+ }
+
+ toshiba_panel_data.panel_info = *pinfo;
+
+ ret = platform_device_add_data(pdev, &toshiba_panel_data,
+ sizeof(toshiba_panel_data));
+ if (ret) {
+ printk(KERN_ERR
+ "%s: platform_device_add_data failed!\n", __func__);
+ goto err_device_put;
+ }
+
+ ret = platform_device_add(pdev);
+ if (ret) {
+ printk(KERN_ERR
+ "%s: platform_device_register failed!\n", __func__);
+ goto err_device_put;
+ }
+
+ return 0;
+
+err_device_put:
+ platform_device_put(pdev);
+ return ret;
+}
+
+static int __init mddi_toshiba_lcd_init(void)
+{
+ return platform_driver_register(&this_driver);
+}
+
+module_init(mddi_toshiba_lcd_init);
diff --git a/drivers/staging/msm/mddi_toshiba.h b/drivers/staging/msm/mddi_toshiba.h
new file mode 100644
index 0000000..2d22b9a
--- /dev/null
+++ b/drivers/staging/msm/mddi_toshiba.h
@@ -0,0 +1,52 @@
+/* Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora 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, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT 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 MDDI_TOSHIBA_H
+#define MDDI_TOSHIBA_H
+
+#define TOSHIBA_VGA_PRIM 1
+#define TOSHIBA_VGA_SECD 2
+
+#define LCD_TOSHIBA_2P4_VGA 0
+#define LCD_TOSHIBA_2P4_WVGA 1
+#define LCD_TOSHIBA_2P4_WVGA_PT 2
+#define LCD_SHARP_2P4_VGA 3
+
+#define GPIO_BLOCK_BASE 0x150000
+#define SYSTEM_BLOCK2_BASE 0x170000
+
+#define GPIODIR (GPIO_BLOCK_BASE|0x04)
+#define GPIOSEL (SYSTEM_BLOCK2_BASE|0x00)
+#define GPIOPC (GPIO_BLOCK_BASE|0x28)
+#define GPIODATA (GPIO_BLOCK_BASE|0x00)
+
+#define write_client_reg(__X, __Y, __Z) {\
+ mddi_queue_register_write(__X, __Y, TRUE, 0);\
+}
+
+#endif /* MDDI_TOSHIBA_H */
diff --git a/drivers/staging/msm/mddi_toshiba_vga.c b/drivers/staging/msm/mddi_toshiba_vga.c
new file mode 100644
index 0000000..7e61d3a
--- /dev/null
+++ b/drivers/staging/msm/mddi_toshiba_vga.c
@@ -0,0 +1,136 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+#include "mddi_toshiba.h"
+
+static uint32 read_client_reg(uint32 addr)
+{
+ uint32 val;
+ mddi_queue_register_read(addr, &val, TRUE, 0);
+ return val;
+}
+
+static uint32 toshiba_lcd_gpio_read(void)
+{
+ uint32 val;
+
+ write_client_reg(GPIODIR, 0x0000000C, TRUE);
+ write_client_reg(GPIOSEL, 0x00000000, TRUE);
+ write_client_reg(GPIOSEL, 0x00000000, TRUE);
+ write_client_reg(GPIOPC, 0x03CF00C0, TRUE);
+ val = read_client_reg(GPIODATA) & 0x2C0;
+
+ return val;
+}
+
+static u32 mddi_toshiba_panel_detect(void)
+{
+ mddi_host_type host_idx = MDDI_HOST_PRIM;
+ uint32 lcd_gpio;
+ u32 mddi_toshiba_lcd = LCD_TOSHIBA_2P4_VGA;
+
+ /* Toshiba display requires larger drive_lo value */
+ mddi_host_reg_out(DRIVE_LO, 0x0050);
+
+ lcd_gpio = toshiba_lcd_gpio_read();
+ switch (lcd_gpio) {
+ case 0x0080:
+ mddi_toshiba_lcd = LCD_SHARP_2P4_VGA;
+ break;
+
+ case 0x00C0:
+ default:
+ mddi_toshiba_lcd = LCD_TOSHIBA_2P4_VGA;
+ break;
+ }
+
+ return mddi_toshiba_lcd;
+}
+
+static int __init mddi_toshiba_vga_init(void)
+{
+ int ret;
+ struct msm_panel_info pinfo;
+ u32 panel;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+ u32 id;
+
+ ret = msm_fb_detect_client("mddi_toshiba_vga");
+ if (ret == -ENODEV)
+ return 0;
+
+ if (ret) {
+ id = mddi_get_client_id();
+ if ((id >> 16) != 0xD263)
+ return 0;
+ }
+#endif
+
+ panel = mddi_toshiba_panel_detect();
+
+ pinfo.xres = 480;
+ pinfo.yres = 640;
+ pinfo.type = MDDI_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 18;
+ pinfo.lcd.vsync_enable = TRUE;
+ pinfo.lcd.refx100 = 6118;
+ pinfo.lcd.v_back_porch = 6;
+ pinfo.lcd.v_front_porch = 0;
+ pinfo.lcd.v_pulse_width = 0;
+ pinfo.lcd.hw_vsync_mode = FALSE;
+ pinfo.lcd.vsync_notifier_period = (1 * HZ);
+ pinfo.bl_max = 99;
+ pinfo.bl_min = 1;
+ pinfo.clk_rate = 122880000;
+ pinfo.clk_min = 120000000;
+ pinfo.clk_max = 200000000;
+ pinfo.fb_num = 2;
+
+ ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_PRIM, panel);
+ if (ret) {
+ printk(KERN_ERR "%s: failed to register device!\n", __func__);
+ return ret;
+ }
+
+ pinfo.xres = 176;
+ pinfo.yres = 220;
+ pinfo.type = MDDI_PANEL;
+ pinfo.pdest = DISPLAY_2;
+ pinfo.mddi.vdopkt = 0x400;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 18;
+ pinfo.clk_rate = 122880000;
+ pinfo.clk_min = 120000000;
+ pinfo.clk_max = 200000000;
+ pinfo.fb_num = 2;
+
+ ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_SECD, panel);
+ if (ret)
+ printk(KERN_WARNING
+ "%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(mddi_toshiba_vga_init);
diff --git a/drivers/staging/msm/mddi_toshiba_wvga.c b/drivers/staging/msm/mddi_toshiba_wvga.c
new file mode 100644
index 0000000..557b0f0
--- /dev/null
+++ b/drivers/staging/msm/mddi_toshiba_wvga.c
@@ -0,0 +1,63 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddi_toshiba.h"
+
+static int __init mddi_toshiba_wvga_init(void)
+{
+ int ret;
+ struct msm_panel_info pinfo;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+ if (msm_fb_detect_client("mddi_toshiba_wvga"))
+ return 0;
+#endif
+
+ pinfo.xres = 800;
+ pinfo.yres = 480;
+ pinfo.pdest = DISPLAY_2;
+ pinfo.type = MDDI_PANEL;
+ pinfo.mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 18;
+ pinfo.lcd.vsync_enable = TRUE;
+ pinfo.lcd.refx100 = 6118;
+ pinfo.lcd.v_back_porch = 6;
+ pinfo.lcd.v_front_porch = 0;
+ pinfo.lcd.v_pulse_width = 0;
+ pinfo.lcd.hw_vsync_mode = FALSE;
+ pinfo.lcd.vsync_notifier_period = (1 * HZ);
+ pinfo.bl_max = 4;
+ pinfo.bl_min = 1;
+ pinfo.clk_rate = 192000000;
+ pinfo.clk_min = 190000000;
+ pinfo.clk_max = 200000000;
+ pinfo.fb_num = 2;
+
+ ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_PRIM,
+ LCD_TOSHIBA_2P4_WVGA);
+ if (ret) {
+ printk(KERN_ERR "%s: failed to register device!\n", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+module_init(mddi_toshiba_wvga_init);
diff --git a/drivers/staging/msm/mddi_toshiba_wvga_pt.c b/drivers/staging/msm/mddi_toshiba_wvga_pt.c
new file mode 100644
index 0000000..fc7d4e0
--- /dev/null
+++ b/drivers/staging/msm/mddi_toshiba_wvga_pt.c
@@ -0,0 +1,64 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+#include "mddi_toshiba.h"
+
+static int __init mddi_toshiba_wvga_pt_init(void)
+{
+ int ret;
+ struct msm_panel_info pinfo;
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+ uint id;
+
+ ret = msm_fb_detect_client("mddi_toshiba_wvga_pt");
+ if (ret == -ENODEV)
+ return 0;
+
+ if (ret) {
+ id = mddi_get_client_id();
+ if (id != 0xd2638722)
+ return 0;
+ }
+#endif
+
+ pinfo.xres = 480;
+ pinfo.yres = 800;
+ pinfo.type = MDDI_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 18;
+ pinfo.lcd.vsync_enable = FALSE;
+ pinfo.bl_max = 15;
+ pinfo.bl_min = 1;
+ pinfo.clk_rate = 192000000;
+ pinfo.clk_min = 190000000;
+ pinfo.clk_max = 200000000;
+ pinfo.fb_num = 2;
+
+ ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_PRIM,
+ LCD_TOSHIBA_2P4_WVGA_PT);
+ if (ret)
+ printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(mddi_toshiba_wvga_pt_init);
diff --git a/drivers/staging/msm/mddihost.c b/drivers/staging/msm/mddihost.c
new file mode 100644
index 0000000..c6c1ee4e
--- /dev/null
+++ b/drivers/staging/msm/mddihost.c
@@ -0,0 +1,377 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+#include <linux/clk.h>
+#include <mach/clk.h>
+
+struct semaphore mddi_host_mutex;
+
+struct clk *mddi_io_clk;
+static boolean mddi_host_powered = FALSE;
+static boolean mddi_host_initialized = FALSE;
+extern uint32 *mddi_reg_read_value_ptr;
+
+mddi_lcd_func_type mddi_lcd;
+
+extern mddi_client_capability_type mddi_client_capability_pkt;
+
+#ifdef FEATURE_MDDI_HITACHI
+extern void mddi_hitachi_window_adjust(uint16 x1,
+ uint16 x2, uint16 y1, uint16 y2);
+#endif
+
+extern void mddi_toshiba_lcd_init(void);
+
+#ifdef FEATURE_MDDI_S6D0142
+extern void mddi_s6d0142_lcd_init(void);
+extern void mddi_s6d0142_window_adjust(uint16 x1,
+ uint16 x2,
+ uint16 y1,
+ uint16 y2,
+ mddi_llist_done_cb_type done_cb);
+#endif
+
+void mddi_init(void)
+{
+ if (mddi_host_initialized)
+ return;
+
+ mddi_host_initialized = TRUE;
+
+ init_MUTEX(&mddi_host_mutex);
+
+ if (!mddi_host_powered) {
+ down(&mddi_host_mutex);
+ mddi_host_init(MDDI_HOST_PRIM);
+ mddi_host_powered = TRUE;
+ up(&mddi_host_mutex);
+ mdelay(10);
+ }
+}
+
+int mddi_host_register_read(uint32 reg_addr,
+ uint32 *reg_value_ptr, boolean wait, mddi_host_type host) {
+ mddi_linked_list_type *curr_llist_ptr;
+ mddi_register_access_packet_type *regacc_pkt_ptr;
+ uint16 curr_llist_idx;
+ int ret = 0;
+
+ if (in_interrupt())
+ MDDI_MSG_CRIT("Called from ISR context\n");
+
+ if (!mddi_host_powered) {
+ MDDI_MSG_ERR("MDDI powered down!\n");
+ mddi_init();
+ }
+
+ down(&mddi_host_mutex);
+
+ mddi_reg_read_value_ptr = reg_value_ptr;
+ curr_llist_idx = mddi_get_reg_read_llist_item(host, TRUE);
+ if (curr_llist_idx == UNASSIGNED_INDEX) {
+ up(&mddi_host_mutex);
+
+ /* need to change this to some sort of wait */
+ MDDI_MSG_ERR("Attempting to queue up more than 1 reg read\n");
+ return -EINVAL;
+ }
+
+ curr_llist_ptr = &llist_extern[host][curr_llist_idx];
+ curr_llist_ptr->link_controller_flags = 0x11;
+ curr_llist_ptr->packet_header_count = 14;
+ curr_llist_ptr->packet_data_count = 0;
+
+ curr_llist_ptr->next_packet_pointer = NULL;
+ curr_llist_ptr->packet_data_pointer = NULL;
+ curr_llist_ptr->reserved = 0;
+
+ regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
+
+ regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count;
+ regacc_pkt_ptr->packet_type = 146; /* register access packet */
+ regacc_pkt_ptr->bClient_ID = 0;
+ regacc_pkt_ptr->read_write_info = 0x8001;
+ regacc_pkt_ptr->register_address = reg_addr;
+
+ /* now adjust pointers */
+ mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, wait,
+ NULL, host);
+ /* need to check if we can write the pointer or not */
+
+ up(&mddi_host_mutex);
+
+ if (wait) {
+ int wait_ret;
+
+ mddi_linked_list_notify_type *llist_notify_ptr;
+ llist_notify_ptr = &llist_extern_notify[host][curr_llist_idx];
+ wait_ret = wait_for_completion_timeout(
+ &(llist_notify_ptr->done_comp), 5 * HZ);
+
+ if (wait_ret <= 0)
+ ret = -EBUSY;
+
+ if (wait_ret < 0)
+ printk(KERN_ERR "%s: failed to wait for completion!\n",
+ __func__);
+ else if (!wait_ret)
+ printk(KERN_ERR "%s: Timed out waiting!\n", __func__);
+ }
+
+ MDDI_MSG_DEBUG("Reg Read value=0x%x\n", *reg_value_ptr);
+
+ return ret;
+} /* mddi_host_register_read */
+
+int mddi_host_register_write(uint32 reg_addr,
+ uint32 reg_val, enum mddi_data_packet_size_type packet_size,
+ boolean wait, mddi_llist_done_cb_type done_cb, mddi_host_type host) {
+ mddi_linked_list_type *curr_llist_ptr;
+ mddi_linked_list_type *curr_llist_dma_ptr;
+ mddi_register_access_packet_type *regacc_pkt_ptr;
+ uint16 curr_llist_idx;
+ int ret = 0;
+
+ if (in_interrupt())
+ MDDI_MSG_CRIT("Called from ISR context\n");
+
+ if (!mddi_host_powered) {
+ MDDI_MSG_ERR("MDDI powered down!\n");
+ mddi_init();
+ }
+
+ down(&mddi_host_mutex);
+
+ curr_llist_idx = mddi_get_next_free_llist_item(host, TRUE);
+ curr_llist_ptr = &llist_extern[host][curr_llist_idx];
+ curr_llist_dma_ptr = &llist_dma_extern[host][curr_llist_idx];
+
+ curr_llist_ptr->link_controller_flags = 1;
+ curr_llist_ptr->packet_header_count = 14;
+ curr_llist_ptr->packet_data_count = 4;
+
+ curr_llist_ptr->next_packet_pointer = NULL;
+ curr_llist_ptr->reserved = 0;
+
+ regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
+
+ regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count +
+ (uint16)packet_size;
+ regacc_pkt_ptr->packet_type = 146; /* register access packet */
+ regacc_pkt_ptr->bClient_ID = 0;
+ regacc_pkt_ptr->read_write_info = 0x0001;
+ regacc_pkt_ptr->register_address = reg_addr;
+ regacc_pkt_ptr->register_data_list = reg_val;
+
+ MDDI_MSG_DEBUG("Reg Access write reg=0x%x, value=0x%x\n",
+ regacc_pkt_ptr->register_address,
+ regacc_pkt_ptr->register_data_list);
+
+ regacc_pkt_ptr = &curr_llist_dma_ptr->packet_header.register_pkt;
+ curr_llist_ptr->packet_data_pointer =
+ (void *)(®acc_pkt_ptr->register_data_list);
+
+ /* now adjust pointers */
+ mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, wait,
+ done_cb, host);
+
+ up(&mddi_host_mutex);
+
+ if (wait) {
+ int wait_ret;
+
+ mddi_linked_list_notify_type *llist_notify_ptr;
+ llist_notify_ptr = &llist_extern_notify[host][curr_llist_idx];
+ wait_ret = wait_for_completion_timeout(
+ &(llist_notify_ptr->done_comp), 5 * HZ);
+
+ if (wait_ret <= 0)
+ ret = -EBUSY;
+
+ if (wait_ret < 0)
+ printk(KERN_ERR "%s: failed to wait for completion!\n",
+ __func__);
+ else if (!wait_ret)
+ printk(KERN_ERR "%s: Timed out waiting!\n", __func__);
+ }
+
+ return ret;
+} /* mddi_host_register_write */
+
+boolean mddi_host_register_read_int
+ (uint32 reg_addr, uint32 *reg_value_ptr, mddi_host_type host) {
+ mddi_linked_list_type *curr_llist_ptr;
+ mddi_register_access_packet_type *regacc_pkt_ptr;
+ uint16 curr_llist_idx;
+
+ if (!in_interrupt())
+ MDDI_MSG_CRIT("Called from TASK context\n");
+
+ if (!mddi_host_powered) {
+ MDDI_MSG_ERR("MDDI powered down!\n");
+ return FALSE;
+ }
+
+ if (down_trylock(&mddi_host_mutex) != 0)
+ return FALSE;
+
+ mddi_reg_read_value_ptr = reg_value_ptr;
+ curr_llist_idx = mddi_get_reg_read_llist_item(host, FALSE);
+ if (curr_llist_idx == UNASSIGNED_INDEX) {
+ up(&mddi_host_mutex);
+ return FALSE;
+ }
+
+ curr_llist_ptr = &llist_extern[host][curr_llist_idx];
+ curr_llist_ptr->link_controller_flags = 0x11;
+ curr_llist_ptr->packet_header_count = 14;
+ curr_llist_ptr->packet_data_count = 0;
+
+ curr_llist_ptr->next_packet_pointer = NULL;
+ curr_llist_ptr->packet_data_pointer = NULL;
+ curr_llist_ptr->reserved = 0;
+
+ regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
+
+ regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count;
+ regacc_pkt_ptr->packet_type = 146; /* register access packet */
+ regacc_pkt_ptr->bClient_ID = 0;
+ regacc_pkt_ptr->read_write_info = 0x8001;
+ regacc_pkt_ptr->register_address = reg_addr;
+
+ /* now adjust pointers */
+ mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, FALSE,
+ NULL, host);
+ /* need to check if we can write the pointer or not */
+
+ up(&mddi_host_mutex);
+
+ return TRUE;
+
+} /* mddi_host_register_read */
+
+boolean mddi_host_register_write_int
+ (uint32 reg_addr,
+ uint32 reg_val, mddi_llist_done_cb_type done_cb, mddi_host_type host) {
+ mddi_linked_list_type *curr_llist_ptr;
+ mddi_linked_list_type *curr_llist_dma_ptr;
+ mddi_register_access_packet_type *regacc_pkt_ptr;
+ uint16 curr_llist_idx;
+
+ if (!in_interrupt())
+ MDDI_MSG_CRIT("Called from TASK context\n");
+
+ if (!mddi_host_powered) {
+ MDDI_MSG_ERR("MDDI powered down!\n");
+ return FALSE;
+ }
+
+ if (down_trylock(&mddi_host_mutex) != 0)
+ return FALSE;
+
+ curr_llist_idx = mddi_get_next_free_llist_item(host, FALSE);
+ if (curr_llist_idx == UNASSIGNED_INDEX) {
+ up(&mddi_host_mutex);
+ return FALSE;
+ }
+
+ curr_llist_ptr = &llist_extern[host][curr_llist_idx];
+ curr_llist_dma_ptr = &llist_dma_extern[host][curr_llist_idx];
+
+ curr_llist_ptr->link_controller_flags = 1;
+ curr_llist_ptr->packet_header_count = 14;
+ curr_llist_ptr->packet_data_count = 4;
+
+ curr_llist_ptr->next_packet_pointer = NULL;
+ curr_llist_ptr->reserved = 0;
+
+ regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
+
+ regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count + 4;
+ regacc_pkt_ptr->packet_type = 146; /* register access packet */
+ regacc_pkt_ptr->bClient_ID = 0;
+ regacc_pkt_ptr->read_write_info = 0x0001;
+ regacc_pkt_ptr->register_address = reg_addr;
+ regacc_pkt_ptr->register_data_list = reg_val;
+
+ regacc_pkt_ptr = &curr_llist_dma_ptr->packet_header.register_pkt;
+ curr_llist_ptr->packet_data_pointer =
+ (void *)(&(regacc_pkt_ptr->register_data_list));
+
+ /* now adjust pointers */
+ mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, FALSE,
+ done_cb, host);
+ up(&mddi_host_mutex);
+
+ return TRUE;
+
+} /* mddi_host_register_write */
+
+void mddi_wait(uint16 time_ms)
+{
+ mdelay(time_ms);
+}
+
+void mddi_client_lcd_vsync_detected(boolean detected)
+{
+ if (mddi_lcd.vsync_detected)
+ (*mddi_lcd.vsync_detected) (detected);
+}
+
+/* extended version of function includes done callback */
+void mddi_window_adjust_ext(struct msm_fb_data_type *mfd,
+ uint16 x1,
+ uint16 x2,
+ uint16 y1,
+ uint16 y2, mddi_llist_done_cb_type done_cb)
+{
+#ifdef FEATURE_MDDI_HITACHI
+ if (mfd->panel.id == HITACHI)
+ mddi_hitachi_window_adjust(x1, x2, y1, y2);
+#elif defined(FEATURE_MDDI_S6D0142)
+ if (mfd->panel.id == MDDI_LCD_S6D0142)
+ mddi_s6d0142_window_adjust(x1, x2, y1, y2, done_cb);
+#else
+ /* Do nothing then... except avoid lint/compiler warnings */
+ (void)x1;
+ (void)x2;
+ (void)y1;
+ (void)y2;
+ (void)done_cb;
+#endif
+}
+
+void mddi_window_adjust(struct msm_fb_data_type *mfd,
+ uint16 x1, uint16 x2, uint16 y1, uint16 y2)
+{
+ mddi_window_adjust_ext(mfd, x1, x2, y1, y2, NULL);
+}
diff --git a/drivers/staging/msm/mddihost.h b/drivers/staging/msm/mddihost.h
new file mode 100644
index 0000000..20b8178
--- /dev/null
+++ b/drivers/staging/msm/mddihost.h
@@ -0,0 +1,225 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 Code Aurora 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, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT 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 MDDIHOST_H
+#define MDDIHOST_H
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include "linux/proc_fs.h"
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+
+#include "msm_fb_panel.h"
+
+#undef FEATURE_MDDI_MC4
+#undef FEATURE_MDDI_S6D0142
+#undef FEATURE_MDDI_HITACHI
+#define FEATURE_MDDI_SHARP
+#define FEATURE_MDDI_TOSHIBA
+#undef FEATURE_MDDI_E751
+#define FEATURE_MDDI_CORONA
+#define FEATURE_MDDI_PRISM
+
+#define T_MSM7500
+
+typedef enum {
+ format_16bpp,
+ format_18bpp,
+ format_24bpp
+} mddi_video_format;
+
+typedef enum {
+ MDDI_LCD_NONE = 0,
+ MDDI_LCD_MC4,
+ MDDI_LCD_S6D0142,
+ MDDI_LCD_SHARP,
+ MDDI_LCD_E751,
+ MDDI_LCD_CORONA,
+ MDDI_LCD_HITACHI,
+ MDDI_LCD_TOSHIBA,
+ MDDI_LCD_PRISM,
+ MDDI_LCD_TP2,
+ MDDI_NUM_LCD_TYPES,
+ MDDI_LCD_DEFAULT = MDDI_LCD_TOSHIBA
+} mddi_lcd_type;
+
+typedef enum {
+ MDDI_HOST_PRIM = 0,
+ MDDI_HOST_EXT,
+ MDDI_NUM_HOST_CORES
+} mddi_host_type;
+
+typedef enum {
+ MDDI_DRIVER_RESET, /* host core registers have not been written. */
+ MDDI_DRIVER_DISABLED, /* registers written, interrupts disabled. */
+ MDDI_DRIVER_ENABLED /* registers written, interrupts enabled. */
+} mddi_host_driver_state_type;
+
+typedef enum {
+ MDDI_GPIO_INT_0 = 0,
+ MDDI_GPIO_INT_1,
+ MDDI_GPIO_INT_2,
+ MDDI_GPIO_INT_3,
+ MDDI_GPIO_INT_4,
+ MDDI_GPIO_INT_5,
+ MDDI_GPIO_INT_6,
+ MDDI_GPIO_INT_7,
+ MDDI_GPIO_INT_8,
+ MDDI_GPIO_INT_9,
+ MDDI_GPIO_INT_10,
+ MDDI_GPIO_INT_11,
+ MDDI_GPIO_INT_12,
+ MDDI_GPIO_INT_13,
+ MDDI_GPIO_INT_14,
+ MDDI_GPIO_INT_15,
+ MDDI_GPIO_NUM_INTS
+} mddi_gpio_int_type;
+
+enum mddi_data_packet_size_type {
+ MDDI_DATA_PACKET_4_BYTES = 4,
+ MDDI_DATA_PACKET_8_BYTES = 8,
+ MDDI_DATA_PACKET_12_BYTES = 12,
+ MDDI_DATA_PACKET_16_BYTES = 16,
+ MDDI_DATA_PACKET_24_BYTES = 24
+};
+
+typedef struct {
+ uint32 addr;
+ uint32 value;
+} mddi_reg_write_type;
+
+boolean mddi_vsync_set_handler(msm_fb_vsync_handler_type handler, void *arg);
+
+typedef void (*mddi_llist_done_cb_type) (void);
+
+typedef void (*mddi_rev_handler_type) (void *);
+
+boolean mddi_set_rev_handler(mddi_rev_handler_type handler, uint16 pkt_type);
+
+#define MDDI_DEFAULT_PRIM_PIX_ATTR 0xC3
+#define MDDI_DEFAULT_SECD_PIX_ATTR 0xC0
+
+typedef int gpio_int_polarity_type;
+typedef int gpio_int_handler_type;
+
+typedef struct {
+ void (*vsync_detected) (boolean);
+} mddi_lcd_func_type;
+
+extern mddi_lcd_func_type mddi_lcd;
+void mddi_init(void);
+
+void mddi_powerdown(void);
+
+void mddi_host_start_ext_display(void);
+void mddi_host_stop_ext_display(void);
+
+extern spinlock_t mddi_host_spin_lock;
+#ifdef T_MSM7500
+void mddi_reset(void);
+#ifdef FEATURE_DUAL_PROC_MODEM_DISPLAY
+void mddi_host_switch_proc_control(boolean on);
+#endif
+#endif
+void mddi_host_exit_power_collapse(void);
+
+void mddi_queue_splash_screen
+ (void *buf_ptr,
+ boolean clear_area,
+ int16 src_width,
+ int16 src_starting_row,
+ int16 src_starting_column,
+ int16 num_of_rows,
+ int16 num_of_columns, int16 dst_starting_row, int16 dst_starting_column);
+
+void mddi_queue_image
+ (void *buf_ptr,
+ uint8 stereo_video,
+ boolean clear_area,
+ int16 src_width,
+ int16 src_starting_row,
+ int16 src_starting_column,
+ int16 num_of_rows,
+ int16 num_of_columns, int16 dst_starting_row, int16 dst_starting_column);
+
+int mddi_host_register_read
+ (uint32 reg_addr,
+ uint32 *reg_value_ptr, boolean wait, mddi_host_type host_idx);
+int mddi_host_register_write
+ (uint32 reg_addr, uint32 reg_val,
+ enum mddi_data_packet_size_type packet_size,
+ boolean wait, mddi_llist_done_cb_type done_cb, mddi_host_type host);
+boolean mddi_host_register_write_int
+ (uint32 reg_addr,
+ uint32 reg_val, mddi_llist_done_cb_type done_cb, mddi_host_type host);
+boolean mddi_host_register_read_int
+ (uint32 reg_addr, uint32 *reg_value_ptr, mddi_host_type host_idx);
+void mddi_queue_register_write_static
+ (uint32 reg_addr,
+ uint32 reg_val, boolean wait, mddi_llist_done_cb_type done_cb);
+void mddi_queue_static_window_adjust
+ (const mddi_reg_write_type *reg_write,
+ uint16 num_writes, mddi_llist_done_cb_type done_cb);
+
+#define mddi_queue_register_read(reg, val_ptr, wait, sig) \
+ mddi_host_register_read(reg, val_ptr, wait, MDDI_HOST_PRIM)
+#define mddi_queue_register_write(reg, val, wait, sig) \
+ mddi_host_register_write(reg, val, MDDI_DATA_PACKET_4_BYTES,\
+ wait, NULL, MDDI_HOST_PRIM)
+#define mddi_queue_register_write_extn(reg, val, pkt_size, wait, sig) \
+ mddi_host_register_write(reg, val, pkt_size, \
+ wait, NULL, MDDI_HOST_PRIM)
+#define mddi_queue_register_write_int(reg, val) \
+ mddi_host_register_write_int(reg, val, NULL, MDDI_HOST_PRIM)
+#define mddi_queue_register_read_int(reg, val_ptr) \
+ mddi_host_register_read_int(reg, val_ptr, MDDI_HOST_PRIM)
+#define mddi_queue_register_writes(reg_ptr, val, wait, sig) \
+ mddi_host_register_writes(reg_ptr, val, wait, sig, MDDI_HOST_PRIM)
+
+void mddi_wait(uint16 time_ms);
+void mddi_assign_max_pkt_dimensions(uint16 image_cols,
+ uint16 image_rows,
+ uint16 bpp,
+ uint16 *max_cols, uint16 * max_rows);
+uint16 mddi_assign_pkt_height(uint16 pkt_width, uint16 pkt_height, uint16 bpp);
+void mddi_queue_reverse_encapsulation(boolean wait);
+void mddi_disable(int lock);
+#endif /* MDDIHOST_H */
diff --git a/drivers/staging/msm/mddihost_e.c b/drivers/staging/msm/mddihost_e.c
new file mode 100644
index 0000000..7de5eda
--- /dev/null
+++ b/drivers/staging/msm/mddihost_e.c
@@ -0,0 +1,63 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+#include <linux/clk.h>
+#include <mach/clk.h>
+
+extern struct semaphore mddi_host_mutex;
+static boolean mddi_host_ext_powered = FALSE;
+
+void mddi_host_start_ext_display(void)
+{
+ down(&mddi_host_mutex);
+
+ if (!mddi_host_ext_powered) {
+ mddi_host_init(MDDI_HOST_EXT);
+
+ mddi_host_ext_powered = TRUE;
+ }
+
+ up(&mddi_host_mutex);
+}
+
+void mddi_host_stop_ext_display(void)
+{
+ down(&mddi_host_mutex);
+
+ if (mddi_host_ext_powered) {
+ mddi_host_powerdown(MDDI_HOST_EXT);
+
+ mddi_host_ext_powered = FALSE;
+ }
+
+ up(&mddi_host_mutex);
+}
diff --git a/drivers/staging/msm/mddihosti.c b/drivers/staging/msm/mddihosti.c
new file mode 100644
index 0000000..f9d6e91
--- /dev/null
+++ b/drivers/staging/msm/mddihosti.c
@@ -0,0 +1,2239 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+
+#include "msm_fb_panel.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+#define FEATURE_MDDI_UNDERRUN_RECOVERY
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+static void mddi_read_rev_packet(byte *data_ptr);
+#endif
+
+struct timer_list mddi_host_timer;
+
+#define MDDI_DEFAULT_TIMER_LENGTH 5000 /* 5 seconds */
+uint32 mddi_rtd_frequency = 60000; /* send RTD every 60 seconds */
+uint32 mddi_client_status_frequency = 60000; /* get status pkt every 60 secs */
+
+boolean mddi_vsync_detect_enabled = FALSE;
+mddi_gpio_info_type mddi_gpio;
+
+uint32 mddi_host_core_version;
+boolean mddi_debug_log_statistics = FALSE;
+/* #define FEATURE_MDDI_HOST_ENABLE_EARLY_HIBERNATION */
+/* default to TRUE in case MDP does not vote */
+static boolean mddi_host_mdp_active_flag = TRUE;
+static uint32 mddi_log_stats_counter;
+uint32 mddi_log_stats_frequency = 4000;
+
+#define MDDI_DEFAULT_REV_PKT_SIZE 0x20
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+static boolean mddi_rev_ptr_workaround = TRUE;
+static uint32 mddi_reg_read_retry;
+static uint32 mddi_reg_read_retry_max = 20;
+static boolean mddi_enable_reg_read_retry = TRUE;
+static boolean mddi_enable_reg_read_retry_once = FALSE;
+
+#define MDDI_MAX_REV_PKT_SIZE 0x60
+
+#define MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE 0x60
+
+#define MDDI_VIDEO_REV_PKT_SIZE 0x40
+#define MDDI_REV_BUFFER_SIZE MDDI_MAX_REV_PKT_SIZE
+static byte rev_packet_data[MDDI_MAX_REV_PKT_SIZE];
+#endif /* FEATURE_MDDI_DISABLE_REVERSE */
+/* leave these variables so graphics will compile */
+
+#define MDDI_MAX_REV_DATA_SIZE 128
+/*lint -d__align(x) */
+boolean mddi_debug_clear_rev_data = TRUE;
+
+uint32 *mddi_reg_read_value_ptr;
+
+mddi_client_capability_type mddi_client_capability_pkt;
+static boolean mddi_client_capability_request = FALSE;
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+
+#define MAX_MDDI_REV_HANDLERS 2
+#define INVALID_PKT_TYPE 0xFFFF
+
+typedef struct {
+ mddi_rev_handler_type handler; /* ISR to be executed */
+ uint16 pkt_type;
+} mddi_rev_pkt_handler_type;
+static mddi_rev_pkt_handler_type mddi_rev_pkt_handler[MAX_MDDI_REV_HANDLERS] =
+ { {NULL, INVALID_PKT_TYPE}, {NULL, INVALID_PKT_TYPE} };
+
+static boolean mddi_rev_encap_user_request = FALSE;
+static mddi_linked_list_notify_type mddi_rev_user;
+
+spinlock_t mddi_host_spin_lock;
+extern uint32 mdp_in_processing;
+#endif
+
+typedef enum {
+ MDDI_REV_IDLE
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ , MDDI_REV_REG_READ_ISSUED,
+ MDDI_REV_REG_READ_SENT,
+ MDDI_REV_ENCAP_ISSUED,
+ MDDI_REV_STATUS_REQ_ISSUED,
+ MDDI_REV_CLIENT_CAP_ISSUED
+#endif
+} mddi_rev_link_state_type;
+
+typedef enum {
+ MDDI_LINK_DISABLED,
+ MDDI_LINK_HIBERNATING,
+ MDDI_LINK_ACTIVATING,
+ MDDI_LINK_ACTIVE
+} mddi_host_link_state_type;
+
+typedef struct {
+ uint32 count;
+ uint32 in_count;
+ uint32 disp_req_count;
+ uint32 state_change_count;
+ uint32 ll_done_count;
+ uint32 rev_avail_count;
+ uint32 error_count;
+ uint32 rev_encap_count;
+ uint32 llist_ptr_write_1;
+ uint32 llist_ptr_write_2;
+} mddi_host_int_type;
+
+typedef struct {
+ uint32 fwd_crc_count;
+ uint32 rev_crc_count;
+ uint32 pri_underflow;
+ uint32 sec_underflow;
+ uint32 rev_overflow;
+ uint32 pri_overwrite;
+ uint32 sec_overwrite;
+ uint32 rev_overwrite;
+ uint32 dma_failure;
+ uint32 rtd_failure;
+ uint32 reg_read_failure;
+#ifdef FEATURE_MDDI_UNDERRUN_RECOVERY
+ uint32 pri_underrun_detected;
+#endif
+} mddi_host_stat_type;
+
+typedef struct {
+ uint32 rtd_cnt;
+ uint32 rev_enc_cnt;
+ uint32 vid_cnt;
+ uint32 reg_acc_cnt;
+ uint32 cli_stat_cnt;
+ uint32 cli_cap_cnt;
+ uint32 reg_read_cnt;
+ uint32 link_active_cnt;
+ uint32 link_hibernate_cnt;
+ uint32 vsync_response_cnt;
+ uint32 fwd_crc_cnt;
+ uint32 rev_crc_cnt;
+} mddi_log_params_struct_type;
+
+typedef struct {
+ uint32 rtd_value;
+ uint32 rtd_counter;
+ uint32 client_status_cnt;
+ boolean rev_ptr_written;
+ uint8 *rev_ptr_start;
+ uint8 *rev_ptr_curr;
+ uint32 mddi_rev_ptr_write_val;
+ dma_addr_t rev_data_dma_addr;
+ uint16 rev_pkt_size;
+ mddi_rev_link_state_type rev_state;
+ mddi_host_link_state_type link_state;
+ mddi_host_driver_state_type driver_state;
+ boolean disable_hibernation;
+ uint32 saved_int_reg;
+ uint32 saved_int_en;
+ mddi_linked_list_type *llist_ptr;
+ dma_addr_t llist_dma_addr;
+ mddi_linked_list_type *llist_dma_ptr;
+ uint32 *rev_data_buf;
+ struct completion mddi_llist_avail_comp;
+ boolean mddi_waiting_for_llist_avail;
+ mddi_host_int_type int_type;
+ mddi_host_stat_type stats;
+ mddi_log_params_struct_type log_parms;
+ mddi_llist_info_type llist_info;
+ mddi_linked_list_notify_type llist_notify[MDDI_MAX_NUM_LLIST_ITEMS];
+} mddi_host_cntl_type;
+
+static mddi_host_type mddi_curr_host = MDDI_HOST_PRIM;
+static mddi_host_cntl_type mhctl[MDDI_NUM_HOST_CORES];
+mddi_linked_list_type *llist_extern[MDDI_NUM_HOST_CORES];
+mddi_linked_list_type *llist_dma_extern[MDDI_NUM_HOST_CORES];
+mddi_linked_list_notify_type *llist_extern_notify[MDDI_NUM_HOST_CORES];
+static mddi_log_params_struct_type prev_parms[MDDI_NUM_HOST_CORES];
+
+extern uint32 mdp_total_vdopkts;
+
+static boolean mddi_host_io_clock_on = FALSE;
+static boolean mddi_host_hclk_on = FALSE;
+
+int int_mddi_pri_flag = FALSE;
+int int_mddi_ext_flag = FALSE;
+
+static void mddi_report_errors(uint32 int_reg)
+{
+ mddi_host_type host_idx = mddi_curr_host;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ if (int_reg & MDDI_INT_PRI_UNDERFLOW) {
+ pmhctl->stats.pri_underflow++;
+ MDDI_MSG_ERR("!!! MDDI Primary Underflow !!!\n");
+ }
+ if (int_reg & MDDI_INT_SEC_UNDERFLOW) {
+ pmhctl->stats.sec_underflow++;
+ MDDI_MSG_ERR("!!! MDDI Secondary Underflow !!!\n");
+ }
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ if (int_reg & MDDI_INT_REV_OVERFLOW) {
+ pmhctl->stats.rev_overflow++;
+ MDDI_MSG_ERR("!!! MDDI Reverse Overflow !!!\n");
+ pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+ mddi_host_reg_out(REV_PTR, pmhctl->mddi_rev_ptr_write_val);
+
+ }
+ if (int_reg & MDDI_INT_CRC_ERROR)
+ MDDI_MSG_ERR("!!! MDDI Reverse CRC Error !!!\n");
+#endif
+ if (int_reg & MDDI_INT_PRI_OVERWRITE) {
+ pmhctl->stats.pri_overwrite++;
+ MDDI_MSG_ERR("!!! MDDI Primary Overwrite !!!\n");
+ }
+ if (int_reg & MDDI_INT_SEC_OVERWRITE) {
+ pmhctl->stats.sec_overwrite++;
+ MDDI_MSG_ERR("!!! MDDI Secondary Overwrite !!!\n");
+ }
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ if (int_reg & MDDI_INT_REV_OVERWRITE) {
+ pmhctl->stats.rev_overwrite++;
+ /* This will show up normally and is not a problem */
+ MDDI_MSG_DEBUG("MDDI Reverse Overwrite!\n");
+ }
+ if (int_reg & MDDI_INT_RTD_FAILURE) {
+ mddi_host_reg_outm(INTEN, MDDI_INT_RTD_FAILURE, 0);
+ pmhctl->stats.rtd_failure++;
+ MDDI_MSG_ERR("!!! MDDI RTD Failure !!!\n");
+ }
+#endif
+ if (int_reg & MDDI_INT_DMA_FAILURE) {
+ pmhctl->stats.dma_failure++;
+ MDDI_MSG_ERR("!!! MDDI DMA Abort !!!\n");
+ }
+}
+
+static void mddi_host_enable_io_clock(void)
+{
+ if (!MDDI_HOST_IS_IO_CLOCK_ON)
+ MDDI_HOST_ENABLE_IO_CLOCK;
+}
+
+static void mddi_host_enable_hclk(void)
+{
+
+ if (!MDDI_HOST_IS_HCLK_ON)
+ MDDI_HOST_ENABLE_HCLK;
+}
+
+static void mddi_host_disable_io_clock(void)
+{
+#ifndef FEATURE_MDDI_HOST_IO_CLOCK_CONTROL_DISABLE
+ if (MDDI_HOST_IS_IO_CLOCK_ON)
+ MDDI_HOST_DISABLE_IO_CLOCK;
+#endif
+}
+
+static void mddi_host_disable_hclk(void)
+{
+#ifndef FEATURE_MDDI_HOST_HCLK_CONTROL_DISABLE
+ if (MDDI_HOST_IS_HCLK_ON)
+ MDDI_HOST_DISABLE_HCLK;
+#endif
+}
+
+static void mddi_vote_to_sleep(mddi_host_type host_idx, boolean sleep)
+{
+ uint16 vote_mask;
+
+ if (host_idx == MDDI_HOST_PRIM)
+ vote_mask = 0x01;
+ else
+ vote_mask = 0x02;
+}
+
+static void mddi_report_state_change(uint32 int_reg)
+{
+ mddi_host_type host_idx = mddi_curr_host;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ if ((pmhctl->saved_int_reg & MDDI_INT_IN_HIBERNATION) &&
+ (pmhctl->saved_int_reg & MDDI_INT_LINK_ACTIVE)) {
+ /* recover from condition where the io_clock was turned off by the
+ clock driver during a transition to hibernation. The io_clock
+ disable is to prevent MDP/MDDI underruns when changing ARM
+ clock speeds. In the process of halting the ARM, the hclk
+ divider needs to be set to 1. When it is set to 1, there is
+ a small time (usecs) when hclk is off or slow, and this can
+ cause an underrun. To prevent the underrun, clock driver turns
+ off the MDDI io_clock before making the change. */
+ mddi_host_reg_out(CMD, MDDI_CMD_POWERUP);
+ }
+
+ if (int_reg & MDDI_INT_LINK_ACTIVE) {
+ pmhctl->link_state = MDDI_LINK_ACTIVE;
+ pmhctl->log_parms.link_active_cnt++;
+ pmhctl->rtd_value = mddi_host_reg_in(RTD_VAL);
+ MDDI_MSG_DEBUG("!!! MDDI Active RTD:0x%x!!!\n",
+ pmhctl->rtd_value);
+ /* now interrupt on hibernation */
+ mddi_host_reg_outm(INTEN,
+ (MDDI_INT_IN_HIBERNATION |
+ MDDI_INT_LINK_ACTIVE),
+ MDDI_INT_IN_HIBERNATION);
+
+#ifdef DEBUG_MDDIHOSTI
+ /* if gpio interrupt is enabled, start polling at fastest
+ * registered rate
+ */
+ if (mddi_gpio.polling_enabled) {
+ timer_reg(&mddi_gpio_poll_timer,
+ mddi_gpio_poll_timer_cb, 0, mddi_gpio.polling_interval, 0);
+ }
+#endif
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ if (mddi_rev_ptr_workaround) {
+ /* HW CR: need to reset reverse register stuff */
+ pmhctl->rev_ptr_written = FALSE;
+ pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+ }
+#endif
+ /* vote on sleep */
+ mddi_vote_to_sleep(host_idx, FALSE);
+
+ if (host_idx == MDDI_HOST_PRIM) {
+ if (mddi_vsync_detect_enabled) {
+ /*
+ * Indicate to client specific code that vsync
+ * was enabled, but we did not detect a client
+ * intiated wakeup. The client specific
+ * handler can either reassert vsync detection,
+ * or treat this as a valid vsync.
+ */
+ mddi_client_lcd_vsync_detected(FALSE);
+ pmhctl->log_parms.vsync_response_cnt++;
+ }
+ }
+ }
+ if (int_reg & MDDI_INT_IN_HIBERNATION) {
+ pmhctl->link_state = MDDI_LINK_HIBERNATING;
+ pmhctl->log_parms.link_hibernate_cnt++;
+ MDDI_MSG_DEBUG("!!! MDDI Hibernating !!!\n");
+ /* now interrupt on link_active */
+#ifdef FEATURE_MDDI_DISABLE_REVERSE
+ mddi_host_reg_outm(INTEN,
+ (MDDI_INT_MDDI_IN |
+ MDDI_INT_IN_HIBERNATION |
+ MDDI_INT_LINK_ACTIVE),
+ MDDI_INT_LINK_ACTIVE);
+#else
+ mddi_host_reg_outm(INTEN,
+ (MDDI_INT_MDDI_IN |
+ MDDI_INT_IN_HIBERNATION |
+ MDDI_INT_LINK_ACTIVE),
+ (MDDI_INT_MDDI_IN | MDDI_INT_LINK_ACTIVE));
+
+ pmhctl->rtd_counter = mddi_rtd_frequency;
+
+ if (pmhctl->rev_state != MDDI_REV_IDLE) {
+ /* a rev_encap will not wake up the link, so we do that here */
+ pmhctl->link_state = MDDI_LINK_ACTIVATING;
+ mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
+ }
+#endif
+
+ if (pmhctl->disable_hibernation) {
+ mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE);
+ mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
+ pmhctl->link_state = MDDI_LINK_ACTIVATING;
+ }
+#ifdef FEATURE_MDDI_UNDERRUN_RECOVERY
+ if ((pmhctl->llist_info.transmitting_start_idx !=
+ UNASSIGNED_INDEX)
+ &&
+ ((pmhctl->
+ saved_int_reg & (MDDI_INT_PRI_LINK_LIST_DONE |
+ MDDI_INT_PRI_PTR_READ)) ==
+ MDDI_INT_PRI_PTR_READ)) {
+ mddi_linked_list_type *llist_dma;
+ llist_dma = pmhctl->llist_dma_ptr;
+ /*
+ * All indications are that we have not received a
+ * linked list done interrupt, due to an underrun
+ * condition. Recovery attempt is to send again.
+ */
+ dma_coherent_pre_ops();
+ /* Write to primary pointer register again */
+ mddi_host_reg_out(PRI_PTR,
+ &llist_dma[pmhctl->llist_info.
+ transmitting_start_idx]);
+ pmhctl->stats.pri_underrun_detected++;
+ }
+#endif
+
+ /* vote on sleep */
+ if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
+ mddi_vote_to_sleep(host_idx, TRUE);
+ }
+
+#ifdef DEBUG_MDDIHOSTI
+ /* need to stop polling timer */
+ if (mddi_gpio.polling_enabled) {
+ (void) timer_clr(&mddi_gpio_poll_timer, T_NONE);
+ }
+#endif
+ }
+}
+
+void mddi_host_timer_service(unsigned long data)
+{
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ unsigned long flags;
+#endif
+ mddi_host_type host_idx;
+ mddi_host_cntl_type *pmhctl;
+
+ unsigned long time_ms = MDDI_DEFAULT_TIMER_LENGTH;
+ init_timer(&mddi_host_timer);
+ mddi_host_timer.function = mddi_host_timer_service;
+ mddi_host_timer.data = 0;
+
+ mddi_host_timer.expires = jiffies + ((time_ms * HZ) / 1000);
+ add_timer(&mddi_host_timer);
+
+ for (host_idx = MDDI_HOST_PRIM; host_idx < MDDI_NUM_HOST_CORES;
+ host_idx++) {
+ pmhctl = &(mhctl[host_idx]);
+ mddi_log_stats_counter += (uint32) time_ms;
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ pmhctl->rtd_counter += (uint32) time_ms;
+ pmhctl->client_status_cnt += (uint32) time_ms;
+
+ if (host_idx == MDDI_HOST_PRIM) {
+ if (pmhctl->client_status_cnt >=
+ mddi_client_status_frequency) {
+ if ((pmhctl->link_state ==
+ MDDI_LINK_HIBERNATING)
+ && (pmhctl->client_status_cnt >
+ mddi_client_status_frequency)) {
+ /*
+ * special case where we are hibernating
+ * and mddi_host_isr is not firing, so
+ * kick the link so that the status can
+ * be retrieved
+ */
+
+ /* need to wake up link before issuing
+ * rev encap command
+ */
+ MDDI_MSG_INFO("wake up link!\n");
+ spin_lock_irqsave(&mddi_host_spin_lock,
+ flags);
+ mddi_host_enable_hclk();
+ mddi_host_enable_io_clock();
+ pmhctl->link_state =
+ MDDI_LINK_ACTIVATING;
+ mddi_host_reg_out(CMD,
+ MDDI_CMD_LINK_ACTIVE);
+ spin_unlock_irqrestore
+ (&mddi_host_spin_lock, flags);
+ } else
+ if ((pmhctl->link_state == MDDI_LINK_ACTIVE)
+ && pmhctl->disable_hibernation) {
+ /*
+ * special case where we have disabled
+ * hibernation and mddi_host_isr
+ * is not firing, so enable interrupt
+ * for no pkts pending, which will
+ * generate an interrupt
+ */
+ MDDI_MSG_INFO("kick isr!\n");
+ spin_lock_irqsave(&mddi_host_spin_lock,
+ flags);
+ mddi_host_enable_hclk();
+ mddi_host_reg_outm(INTEN,
+ MDDI_INT_NO_CMD_PKTS_PEND,
+ MDDI_INT_NO_CMD_PKTS_PEND);
+ spin_unlock_irqrestore
+ (&mddi_host_spin_lock, flags);
+ }
+ }
+ }
+#endif /* #ifndef FEATURE_MDDI_DISABLE_REVERSE */
+ }
+
+ /* Check if logging is turned on */
+ for (host_idx = MDDI_HOST_PRIM; host_idx < MDDI_NUM_HOST_CORES;
+ host_idx++) {
+ mddi_log_params_struct_type *prev_ptr = &(prev_parms[host_idx]);
+ pmhctl = &(mhctl[host_idx]);
+
+ if (mddi_debug_log_statistics) {
+
+ /* get video pkt count from MDP, since MDDI sw cannot know this */
+ pmhctl->log_parms.vid_cnt = mdp_total_vdopkts;
+
+ if (mddi_log_stats_counter >= mddi_log_stats_frequency) {
+ /* mddi_log_stats_counter = 0; */
+ if (mddi_debug_log_statistics) {
+ MDDI_MSG_NOTICE
+ ("MDDI Statistics since last report:\n");
+ MDDI_MSG_NOTICE(" Packets sent:\n");
+ MDDI_MSG_NOTICE
+ (" %d RTD packet(s)\n",
+ pmhctl->log_parms.rtd_cnt -
+ prev_ptr->rtd_cnt);
+ if (prev_ptr->rtd_cnt !=
+ pmhctl->log_parms.rtd_cnt) {
+ unsigned long flags;
+ spin_lock_irqsave
+ (&mddi_host_spin_lock,
+ flags);
+ mddi_host_enable_hclk();
+ pmhctl->rtd_value =
+ mddi_host_reg_in(RTD_VAL);
+ spin_unlock_irqrestore
+ (&mddi_host_spin_lock,
+ flags);
+ MDDI_MSG_NOTICE
+ (" RTD value=%d\n",
+ pmhctl->rtd_value);
+ }
+ MDDI_MSG_NOTICE
+ (" %d VIDEO packets\n",
+ pmhctl->log_parms.vid_cnt -
+ prev_ptr->vid_cnt);
+ MDDI_MSG_NOTICE
+ (" %d Register Access packets\n",
+ pmhctl->log_parms.reg_acc_cnt -
+ prev_ptr->reg_acc_cnt);
+ MDDI_MSG_NOTICE
+ (" %d Reverse Encapsulation packet(s)\n",
+ pmhctl->log_parms.rev_enc_cnt -
+ prev_ptr->rev_enc_cnt);
+ if (prev_ptr->rev_enc_cnt !=
+ pmhctl->log_parms.rev_enc_cnt) {
+ /* report # of reverse CRC errors */
+ MDDI_MSG_NOTICE
+ (" %d reverse CRC errors detected\n",
+ pmhctl->log_parms.
+ rev_crc_cnt -
+ prev_ptr->rev_crc_cnt);
+ }
+ MDDI_MSG_NOTICE
+ (" Packets received:\n");
+ MDDI_MSG_NOTICE
+ (" %d Client Status packets",
+ pmhctl->log_parms.cli_stat_cnt -
+ prev_ptr->cli_stat_cnt);
+ if (prev_ptr->cli_stat_cnt !=
+ pmhctl->log_parms.cli_stat_cnt) {
+ MDDI_MSG_NOTICE
+ (" %d forward CRC errors reported\n",
+ pmhctl->log_parms.
+ fwd_crc_cnt -
+ prev_ptr->fwd_crc_cnt);
+ }
+ MDDI_MSG_NOTICE
+ (" %d Register Access Read packets\n",
+ pmhctl->log_parms.reg_read_cnt -
+ prev_ptr->reg_read_cnt);
+
+ if (pmhctl->link_state ==
+ MDDI_LINK_ACTIVE) {
+ MDDI_MSG_NOTICE
+ (" Current Link Status: Active\n");
+ } else
+ if ((pmhctl->link_state ==
+ MDDI_LINK_HIBERNATING)
+ || (pmhctl->link_state ==
+ MDDI_LINK_ACTIVATING)) {
+ MDDI_MSG_NOTICE
+ (" Current Link Status: Hibernation\n");
+ } else {
+ MDDI_MSG_NOTICE
+ (" Current Link Status: Inactive\n");
+ }
+ MDDI_MSG_NOTICE
+ (" Active state entered %d times\n",
+ pmhctl->log_parms.link_active_cnt -
+ prev_ptr->link_active_cnt);
+ MDDI_MSG_NOTICE
+ (" Hibernation state entered %d times\n",
+ pmhctl->log_parms.
+ link_hibernate_cnt -
+ prev_ptr->link_hibernate_cnt);
+ }
+ }
+ prev_parms[host_idx] = pmhctl->log_parms;
+ }
+ }
+ if (mddi_log_stats_counter >= mddi_log_stats_frequency)
+ mddi_log_stats_counter = 0;
+
+ return;
+} /* mddi_host_timer_cb */
+
+static void mddi_process_link_list_done(void)
+{
+ mddi_host_type host_idx = mddi_curr_host;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ /* normal forward linked list packet(s) were sent */
+ if (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) {
+ MDDI_MSG_ERR("**** getting LL done, but no list ****\n");
+ } else {
+ uint16 idx;
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ if (pmhctl->rev_state == MDDI_REV_REG_READ_ISSUED) {
+ /* special case where a register read packet was sent */
+ pmhctl->rev_state = MDDI_REV_REG_READ_SENT;
+ if (pmhctl->llist_info.reg_read_idx == UNASSIGNED_INDEX) {
+ MDDI_MSG_ERR
+ ("**** getting LL done, but no list ****\n");
+ }
+ }
+#endif
+ for (idx = pmhctl->llist_info.transmitting_start_idx;;) {
+ uint16 next_idx = pmhctl->llist_notify[idx].next_idx;
+ /* with reg read we don't release the waiting tcb until after
+ * the reverse encapsulation has completed.
+ */
+ if (idx != pmhctl->llist_info.reg_read_idx) {
+ /* notify task that may be waiting on this completion */
+ if (pmhctl->llist_notify[idx].waiting) {
+ complete(&
+ (pmhctl->llist_notify[idx].
+ done_comp));
+ }
+ if (pmhctl->llist_notify[idx].done_cb != NULL) {
+ (*(pmhctl->llist_notify[idx].done_cb))
+ ();
+ }
+
+ pmhctl->llist_notify[idx].in_use = FALSE;
+ pmhctl->llist_notify[idx].waiting = FALSE;
+ pmhctl->llist_notify[idx].done_cb = NULL;
+ if (idx < MDDI_NUM_DYNAMIC_LLIST_ITEMS) {
+ /* static LLIST items are configured only once */
+ pmhctl->llist_notify[idx].next_idx =
+ UNASSIGNED_INDEX;
+ }
+ /*
+ * currently, all linked list packets are
+ * register access, so we can increment the
+ * counter for that packet type here.
+ */
+ pmhctl->log_parms.reg_acc_cnt++;
+ }
+ if (idx == pmhctl->llist_info.transmitting_end_idx)
+ break;
+ idx = next_idx;
+ if (idx == UNASSIGNED_INDEX)
+ MDDI_MSG_CRIT("MDDI linked list corruption!\n");
+ }
+
+ pmhctl->llist_info.transmitting_start_idx = UNASSIGNED_INDEX;
+ pmhctl->llist_info.transmitting_end_idx = UNASSIGNED_INDEX;
+
+ if (pmhctl->mddi_waiting_for_llist_avail) {
+ if (!
+ (pmhctl->
+ llist_notify[pmhctl->llist_info.next_free_idx].
+ in_use)) {
+ pmhctl->mddi_waiting_for_llist_avail = FALSE;
+ complete(&(pmhctl->mddi_llist_avail_comp));
+ }
+ }
+ }
+
+ /* Turn off MDDI_INT_PRI_LINK_LIST_DONE interrupt */
+ mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE, 0);
+
+}
+
+static void mddi_queue_forward_linked_list(void)
+{
+ uint16 first_pkt_index;
+ mddi_linked_list_type *llist_dma;
+ mddi_host_type host_idx = mddi_curr_host;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+ llist_dma = pmhctl->llist_dma_ptr;
+
+ first_pkt_index = UNASSIGNED_INDEX;
+
+ if (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) {
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ if (pmhctl->llist_info.reg_read_waiting) {
+ if (pmhctl->rev_state == MDDI_REV_IDLE) {
+ /*
+ * we have a register read to send and
+ * can send it now
+ */
+ pmhctl->rev_state = MDDI_REV_REG_READ_ISSUED;
+ mddi_reg_read_retry = 0;
+ first_pkt_index =
+ pmhctl->llist_info.waiting_start_idx;
+ pmhctl->llist_info.reg_read_waiting = FALSE;
+ }
+ } else
+#endif
+ {
+ /*
+ * not register read to worry about, go ahead and write
+ * anything that may be on the waiting list.
+ */
+ first_pkt_index = pmhctl->llist_info.waiting_start_idx;
+ }
+ }
+
+ if (first_pkt_index != UNASSIGNED_INDEX) {
+ pmhctl->llist_info.transmitting_start_idx =
+ pmhctl->llist_info.waiting_start_idx;
+ pmhctl->llist_info.transmitting_end_idx =
+ pmhctl->llist_info.waiting_end_idx;
+ pmhctl->llist_info.waiting_start_idx = UNASSIGNED_INDEX;
+ pmhctl->llist_info.waiting_end_idx = UNASSIGNED_INDEX;
+
+ /* write to the primary pointer register */
+ MDDI_MSG_DEBUG("MDDI writing primary ptr with idx=%d\n",
+ first_pkt_index);
+
+ pmhctl->int_type.llist_ptr_write_2++;
+
+ dma_coherent_pre_ops();
+ mddi_host_reg_out(PRI_PTR, &llist_dma[first_pkt_index]);
+
+ /* enable interrupt when complete */
+ mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE,
+ MDDI_INT_PRI_LINK_LIST_DONE);
+
+ }
+
+}
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+static void mddi_read_rev_packet(byte *data_ptr)
+{
+ uint16 i, length;
+ mddi_host_type host_idx = mddi_curr_host;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ uint8 *rev_ptr_overflow =
+ (pmhctl->rev_ptr_start + MDDI_REV_BUFFER_SIZE);
+
+ /* first determine the length and handle invalid lengths */
+ length = *pmhctl->rev_ptr_curr++;
+ if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
+ pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+ length |= ((*pmhctl->rev_ptr_curr++) << 8);
+ if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
+ pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+ if (length > (pmhctl->rev_pkt_size - 2)) {
+ MDDI_MSG_ERR("Invalid rev pkt length %d\n", length);
+ /* rev_pkt_size should always be <= rev_ptr_size so limit to packet size */
+ length = pmhctl->rev_pkt_size - 2;
+ }
+
+ /* If the data pointer is NULL, just increment the pmhctl->rev_ptr_curr.
+ * Loop around if necessary. Don't bother reading the data.
+ */
+ if (data_ptr == NULL) {
+ pmhctl->rev_ptr_curr += length;
+ if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
+ pmhctl->rev_ptr_curr -= MDDI_REV_BUFFER_SIZE;
+ return;
+ }
+
+ data_ptr[0] = length & 0x0ff;
+ data_ptr[1] = length >> 8;
+ data_ptr += 2;
+ /* copy the data to data_ptr byte-at-a-time */
+ for (i = 0; (i < length) && (pmhctl->rev_ptr_curr < rev_ptr_overflow);
+ i++)
+ *data_ptr++ = *pmhctl->rev_ptr_curr++;
+ if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
+ pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+ for (; (i < length) && (pmhctl->rev_ptr_curr < rev_ptr_overflow); i++)
+ *data_ptr++ = *pmhctl->rev_ptr_curr++;
+}
+
+static void mddi_process_rev_packets(void)
+{
+ uint32 rev_packet_count;
+ word i;
+ uint32 crc_errors;
+ boolean mddi_reg_read_successful = FALSE;
+ mddi_host_type host_idx = mddi_curr_host;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ pmhctl->log_parms.rev_enc_cnt++;
+ if ((pmhctl->rev_state != MDDI_REV_ENCAP_ISSUED) &&
+ (pmhctl->rev_state != MDDI_REV_STATUS_REQ_ISSUED) &&
+ (pmhctl->rev_state != MDDI_REV_CLIENT_CAP_ISSUED)) {
+ MDDI_MSG_ERR("Wrong state %d for reverse int\n",
+ pmhctl->rev_state);
+ }
+ /* Turn off MDDI_INT_REV_AVAIL interrupt */
+ mddi_host_reg_outm(INTEN, MDDI_INT_REV_DATA_AVAIL, 0);
+
+ /* Clear rev data avail int */
+ mddi_host_reg_out(INT, MDDI_INT_REV_DATA_AVAIL);
+
+ /* Get Number of packets */
+ rev_packet_count = mddi_host_reg_in(REV_PKT_CNT);
+
+#ifndef T_MSM7500
+ /* Clear out rev packet counter */
+ mddi_host_reg_out(REV_PKT_CNT, 0x0000);
+#endif
+
+#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
+ if ((pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED) &&
+ (rev_packet_count > 0) &&
+ (mddi_host_core_version == 0x28 ||
+ mddi_host_core_version == 0x30)) {
+
+ uint32 int_reg;
+ uint32 max_count = 0;
+
+ mddi_host_reg_out(REV_PTR, pmhctl->mddi_rev_ptr_write_val);
+ int_reg = mddi_host_reg_in(INT);
+ while ((int_reg & 0x100000) == 0) {
+ udelay(3);
+ int_reg = mddi_host_reg_in(INT);
+ if (++max_count > 100)
+ break;
+ }
+ }
+#endif
+
+ /* Get CRC error count */
+ crc_errors = mddi_host_reg_in(REV_CRC_ERR);
+ if (crc_errors != 0) {
+ pmhctl->log_parms.rev_crc_cnt += crc_errors;
+ pmhctl->stats.rev_crc_count += crc_errors;
+ MDDI_MSG_ERR("!!! MDDI %d Reverse CRC Error(s) !!!\n",
+ crc_errors);
+#ifndef T_MSM7500
+ /* Clear CRC error count */
+ mddi_host_reg_out(REV_CRC_ERR, 0x0000);
+#endif
+ /* also issue an RTD to attempt recovery */
+ pmhctl->rtd_counter = mddi_rtd_frequency;
+ }
+
+ pmhctl->rtd_value = mddi_host_reg_in(RTD_VAL);
+
+ MDDI_MSG_DEBUG("MDDI rev pkt cnt=%d, ptr=0x%x, RTD:0x%x\n",
+ rev_packet_count,
+ pmhctl->rev_ptr_curr - pmhctl->rev_ptr_start,
+ pmhctl->rtd_value);
+
+ if (rev_packet_count >= 1) {
+ mddi_invalidate_cache_lines((uint32 *) pmhctl->rev_ptr_start,
+ MDDI_REV_BUFFER_SIZE);
+ }
+ /* order the reads */
+ dma_coherent_post_ops();
+ for (i = 0; i < rev_packet_count; i++) {
+ mddi_rev_packet_type *rev_pkt_ptr;
+
+ mddi_read_rev_packet(rev_packet_data);
+
+ rev_pkt_ptr = (mddi_rev_packet_type *) rev_packet_data;
+
+ if (rev_pkt_ptr->packet_length > pmhctl->rev_pkt_size) {
+ MDDI_MSG_ERR("!!!invalid packet size: %d\n",
+ rev_pkt_ptr->packet_length);
+ }
+
+ MDDI_MSG_DEBUG("MDDI rev pkt 0x%x size 0x%x\n",
+ rev_pkt_ptr->packet_type,
+ rev_pkt_ptr->packet_length);
+
+ /* Do whatever you want to do with the data based on the packet type */
+ switch (rev_pkt_ptr->packet_type) {
+ case 66: /* Client Capability */
+ {
+ mddi_client_capability_type
+ *client_capability_pkt_ptr;
+
+ client_capability_pkt_ptr =
+ (mddi_client_capability_type *)
+ rev_packet_data;
+ MDDI_MSG_NOTICE
+ ("Client Capability: Week=%d, Year=%d\n",
+ client_capability_pkt_ptr->
+ Week_of_Manufacture,
+ client_capability_pkt_ptr->
+ Year_of_Manufacture);
+ memcpy((void *)&mddi_client_capability_pkt,
+ (void *)rev_packet_data,
+ sizeof(mddi_client_capability_type));
+ pmhctl->log_parms.cli_cap_cnt++;
+ }
+ break;
+
+ case 70: /* Display Status */
+ {
+ mddi_client_status_type *client_status_pkt_ptr;
+
+ client_status_pkt_ptr =
+ (mddi_client_status_type *) rev_packet_data;
+ if ((client_status_pkt_ptr->crc_error_count !=
+ 0)
+ || (client_status_pkt_ptr->
+ reverse_link_request != 0)) {
+ MDDI_MSG_ERR
+ ("Client Status: RevReq=%d, CrcErr=%d\n",
+ client_status_pkt_ptr->
+ reverse_link_request,
+ client_status_pkt_ptr->
+ crc_error_count);
+ } else {
+ MDDI_MSG_DEBUG
+ ("Client Status: RevReq=%d, CrcErr=%d\n",
+ client_status_pkt_ptr->
+ reverse_link_request,
+ client_status_pkt_ptr->
+ crc_error_count);
+ }
+ pmhctl->log_parms.fwd_crc_cnt +=
+ client_status_pkt_ptr->crc_error_count;
+ pmhctl->stats.fwd_crc_count +=
+ client_status_pkt_ptr->crc_error_count;
+ pmhctl->log_parms.cli_stat_cnt++;
+ }
+ break;
+
+ case 146: /* register access packet */
+ {
+ mddi_register_access_packet_type
+ * regacc_pkt_ptr;
+
+ regacc_pkt_ptr =
+ (mddi_register_access_packet_type *)
+ rev_packet_data;
+
+ MDDI_MSG_DEBUG
+ ("Reg Acc parse reg=0x%x, value=0x%x\n",
+ regacc_pkt_ptr->register_address,
+ regacc_pkt_ptr->register_data_list);
+
+ /* Copy register value to location passed in */
+ if (mddi_reg_read_value_ptr) {
+#if defined(T_MSM6280) && !defined(T_MSM7200)
+ /* only least significant 16 bits are valid with 6280 */
+ *mddi_reg_read_value_ptr =
+ regacc_pkt_ptr->
+ register_data_list & 0x0000ffff;
+#else
+ *mddi_reg_read_value_ptr =
+ regacc_pkt_ptr->register_data_list;
+#endif
+ mddi_reg_read_successful = TRUE;
+ mddi_reg_read_value_ptr = NULL;
+ }
+
+#ifdef DEBUG_MDDIHOSTI
+ if ((mddi_gpio.polling_enabled) &&
+ (regacc_pkt_ptr->register_address ==
+ mddi_gpio.polling_reg)) {
+ /*
+ * ToDo: need to call Linux GPIO call
+ * here...
+ */
+ mddi_client_lcd_gpio_poll(
+ regacc_pkt_ptr->register_data_list);
+ }
+#endif
+ pmhctl->log_parms.reg_read_cnt++;
+ }
+ break;
+
+ default: /* any other packet */
+ {
+ uint16 hdlr;
+
+ for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS;
+ hdlr++) {
+ if (mddi_rev_pkt_handler[hdlr].
+ pkt_type ==
+ rev_pkt_ptr->packet_type) {
+ (*
+ (mddi_rev_pkt_handler[hdlr].
+ handler)) (rev_pkt_ptr);
+ /* pmhctl->rev_state = MDDI_REV_IDLE; */
+ break;
+ }
+ }
+ if (hdlr >= MAX_MDDI_REV_HANDLERS)
+ MDDI_MSG_ERR("MDDI unknown rev pkt\n");
+ }
+ break;
+ }
+ }
+ if ((pmhctl->rev_ptr_curr + pmhctl->rev_pkt_size) >=
+ (pmhctl->rev_ptr_start + MDDI_REV_BUFFER_SIZE)) {
+ pmhctl->rev_ptr_written = FALSE;
+ }
+
+ if (pmhctl->rev_state == MDDI_REV_ENCAP_ISSUED) {
+ pmhctl->rev_state = MDDI_REV_IDLE;
+ if (mddi_rev_user.waiting) {
+ mddi_rev_user.waiting = FALSE;
+ complete(&(mddi_rev_user.done_comp));
+ } else if (pmhctl->llist_info.reg_read_idx == UNASSIGNED_INDEX) {
+ MDDI_MSG_ERR
+ ("Reverse Encap state, but no reg read in progress\n");
+ } else {
+ if ((!mddi_reg_read_successful) &&
+ (mddi_reg_read_retry < mddi_reg_read_retry_max) &&
+ (mddi_enable_reg_read_retry)) {
+ /*
+ * There is a race condition that can happen
+ * where the reverse encapsulation message is
+ * sent out by the MDDI host before the register
+ * read packet is sent. As a work-around for
+ * that problem we issue the reverse
+ * encapsulation one more time before giving up.
+ */
+ if (mddi_enable_reg_read_retry_once)
+ mddi_reg_read_retry =
+ mddi_reg_read_retry_max;
+ pmhctl->rev_state = MDDI_REV_REG_READ_SENT;
+ pmhctl->stats.reg_read_failure++;
+ } else {
+ uint16 reg_read_idx =
+ pmhctl->llist_info.reg_read_idx;
+
+ mddi_reg_read_retry = 0;
+ if (pmhctl->llist_notify[reg_read_idx].waiting) {
+ complete(&
+ (pmhctl->
+ llist_notify[reg_read_idx].
+ done_comp));
+ }
+ pmhctl->llist_info.reg_read_idx =
+ UNASSIGNED_INDEX;
+ if (pmhctl->llist_notify[reg_read_idx].
+ done_cb != NULL) {
+ (*
+ (pmhctl->llist_notify[reg_read_idx].
+ done_cb)) ();
+ }
+ pmhctl->llist_notify[reg_read_idx].next_idx =
+ UNASSIGNED_INDEX;
+ pmhctl->llist_notify[reg_read_idx].in_use =
+ FALSE;
+ pmhctl->llist_notify[reg_read_idx].waiting =
+ FALSE;
+ pmhctl->llist_notify[reg_read_idx].done_cb =
+ NULL;
+ if (!mddi_reg_read_successful)
+ pmhctl->stats.reg_read_failure++;
+ }
+ }
+ } else if (pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED) {
+#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
+ if (mddi_host_core_version == 0x28 ||
+ mddi_host_core_version == 0x30) {
+ mddi_host_reg_out(FIFO_ALLOC, 0x00);
+ pmhctl->rev_ptr_written = TRUE;
+ mddi_host_reg_out(REV_PTR,
+ pmhctl->mddi_rev_ptr_write_val);
+ pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+ mddi_host_reg_out(CMD, 0xC00);
+ }
+#endif
+
+ if (mddi_rev_user.waiting) {
+ mddi_rev_user.waiting = FALSE;
+ complete(&(mddi_rev_user.done_comp));
+ }
+ pmhctl->rev_state = MDDI_REV_IDLE;
+ } else {
+ pmhctl->rev_state = MDDI_REV_IDLE;
+ }
+
+ /* pmhctl->rev_state = MDDI_REV_IDLE; */
+
+ /* Re-enable interrupt */
+ mddi_host_reg_outm(INTEN, MDDI_INT_REV_DATA_AVAIL,
+ MDDI_INT_REV_DATA_AVAIL);
+
+}
+
+static void mddi_issue_reverse_encapsulation(void)
+{
+ mddi_host_type host_idx = mddi_curr_host;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+ /* Only issue a reverse encapsulation packet if:
+ * 1) another reverse is not in progress (MDDI_REV_IDLE).
+ * 2) a register read has been sent (MDDI_REV_REG_READ_SENT).
+ * 3) forward is not in progress, because of a hw bug in client that
+ * causes forward crc errors on packet immediately after rev encap.
+ */
+ if (((pmhctl->rev_state == MDDI_REV_IDLE) ||
+ (pmhctl->rev_state == MDDI_REV_REG_READ_SENT)) &&
+ (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) &&
+ (!mdp_in_processing)) {
+ uint32 mddi_command = MDDI_CMD_SEND_REV_ENCAP;
+
+ if ((pmhctl->rev_state == MDDI_REV_REG_READ_SENT) ||
+ (mddi_rev_encap_user_request == TRUE)) {
+ mddi_host_enable_io_clock();
+ if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
+ /* need to wake up link before issuing rev encap command */
+ MDDI_MSG_DEBUG("wake up link!\n");
+ pmhctl->link_state = MDDI_LINK_ACTIVATING;
+ mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
+ } else {
+ if (pmhctl->rtd_counter >= mddi_rtd_frequency) {
+ MDDI_MSG_DEBUG
+ ("mddi sending RTD command!\n");
+ mddi_host_reg_out(CMD,
+ MDDI_CMD_SEND_RTD);
+ pmhctl->rtd_counter = 0;
+ pmhctl->log_parms.rtd_cnt++;
+ }
+ if (pmhctl->rev_state != MDDI_REV_REG_READ_SENT) {
+ /* this is generic reverse request by user, so
+ * reset the waiting flag. */
+ mddi_rev_encap_user_request = FALSE;
+ }
+ /* link is active so send reverse encap to get register read results */
+ pmhctl->rev_state = MDDI_REV_ENCAP_ISSUED;
+ mddi_command = MDDI_CMD_SEND_REV_ENCAP;
+ MDDI_MSG_DEBUG("sending rev encap!\n");
+ }
+ } else
+ if ((pmhctl->client_status_cnt >=
+ mddi_client_status_frequency)
+ || mddi_client_capability_request) {
+ mddi_host_enable_io_clock();
+ if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
+ /* only wake up the link if it client status is overdue */
+ if ((pmhctl->client_status_cnt >=
+ (mddi_client_status_frequency * 2))
+ || mddi_client_capability_request) {
+ /* need to wake up link before issuing rev encap command */
+ MDDI_MSG_DEBUG("wake up link!\n");
+ pmhctl->link_state =
+ MDDI_LINK_ACTIVATING;
+ mddi_host_reg_out(CMD,
+ MDDI_CMD_LINK_ACTIVE);
+ }
+ } else {
+ if (pmhctl->rtd_counter >= mddi_rtd_frequency) {
+ MDDI_MSG_DEBUG
+ ("mddi sending RTD command!\n");
+ mddi_host_reg_out(CMD,
+ MDDI_CMD_SEND_RTD);
+ pmhctl->rtd_counter = 0;
+ pmhctl->log_parms.rtd_cnt++;
+ }
+ /* periodically get client status */
+ MDDI_MSG_DEBUG
+ ("mddi sending rev enc! (get status)\n");
+ if (mddi_client_capability_request) {
+ pmhctl->rev_state =
+ MDDI_REV_CLIENT_CAP_ISSUED;
+ mddi_command = MDDI_CMD_GET_CLIENT_CAP;
+ mddi_client_capability_request = FALSE;
+ } else {
+ pmhctl->rev_state =
+ MDDI_REV_STATUS_REQ_ISSUED;
+ pmhctl->client_status_cnt = 0;
+ mddi_command =
+ MDDI_CMD_GET_CLIENT_STATUS;
+ }
+ }
+ }
+ if ((pmhctl->rev_state == MDDI_REV_ENCAP_ISSUED) ||
+ (pmhctl->rev_state == MDDI_REV_STATUS_REQ_ISSUED) ||
+ (pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED)) {
+ pmhctl->int_type.rev_encap_count++;
+#if defined(T_MSM6280) && !defined(T_MSM7200)
+ mddi_rev_pointer_written = TRUE;
+ mddi_host_reg_out(REV_PTR, mddi_rev_ptr_write_val);
+ mddi_rev_ptr_curr = mddi_rev_ptr_start;
+ /* force new rev ptr command */
+ mddi_host_reg_out(CMD, 0xC00);
+#else
+ if (!pmhctl->rev_ptr_written) {
+ MDDI_MSG_DEBUG("writing reverse pointer!\n");
+ pmhctl->rev_ptr_written = TRUE;
+#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
+ if ((pmhctl->rev_state ==
+ MDDI_REV_CLIENT_CAP_ISSUED) &&
+ (mddi_host_core_version == 0x28 ||
+ mddi_host_core_version == 0x30)) {
+ pmhctl->rev_ptr_written = FALSE;
+ mddi_host_reg_out(FIFO_ALLOC, 0x02);
+ } else
+ mddi_host_reg_out(REV_PTR,
+ pmhctl->
+ mddi_rev_ptr_write_val);
+#else
+ mddi_host_reg_out(REV_PTR,
+ pmhctl->
+ mddi_rev_ptr_write_val);
+#endif
+ }
+#endif
+ if (mddi_debug_clear_rev_data) {
+ uint16 i;
+ for (i = 0; i < MDDI_MAX_REV_DATA_SIZE / 4; i++)
+ pmhctl->rev_data_buf[i] = 0xdddddddd;
+ /* clean cache */
+ mddi_flush_cache_lines(pmhctl->rev_data_buf,
+ MDDI_MAX_REV_DATA_SIZE);
+ }
+
+ /* send reverse encapsulation to get needed data */
+ mddi_host_reg_out(CMD, mddi_command);
+ }
+ }
+
+}
+
+static void mddi_process_client_initiated_wakeup(void)
+{
+ mddi_host_type host_idx = mddi_curr_host;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ /* Disable MDDI_INT Interrupt, we detect client initiated wakeup one
+ * time for each entry into hibernation */
+ mddi_host_reg_outm(INTEN, MDDI_INT_MDDI_IN, 0);
+
+ if (host_idx == MDDI_HOST_PRIM) {
+ if (mddi_vsync_detect_enabled) {
+ mddi_host_enable_io_clock();
+#ifndef MDDI_HOST_DISP_LISTEN
+ /* issue command to bring up link */
+ /* need to do this to clear the vsync condition */
+ if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
+ pmhctl->link_state = MDDI_LINK_ACTIVATING;
+ mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
+ }
+#endif
+ /*
+ * Indicate to client specific code that vsync was
+ * enabled, and we did not detect a client initiated
+ * wakeup. The client specific handler can clear the
+ * condition if necessary to prevent subsequent
+ * client initiated wakeups.
+ */
+ mddi_client_lcd_vsync_detected(TRUE);
+ pmhctl->log_parms.vsync_response_cnt++;
+ MDDI_MSG_NOTICE("MDDI_INT_IN condition\n");
+
+ }
+ }
+
+ if (mddi_gpio.polling_enabled) {
+ mddi_host_enable_io_clock();
+ /* check interrupt status now */
+ (void)mddi_queue_register_read_int(mddi_gpio.polling_reg,
+ &mddi_gpio.polling_val);
+ }
+}
+#endif /* FEATURE_MDDI_DISABLE_REVERSE */
+
+static void mddi_host_isr(void)
+{
+ uint32 int_reg, int_en;
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ uint32 status_reg;
+#endif
+ mddi_host_type host_idx = mddi_curr_host;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ if (!MDDI_HOST_IS_HCLK_ON) {
+ MDDI_HOST_ENABLE_HCLK;
+ MDDI_MSG_DEBUG("HCLK disabled, but isr is firing\n");
+ }
+ int_reg = mddi_host_reg_in(INT);
+ int_en = mddi_host_reg_in(INTEN);
+ pmhctl->saved_int_reg = int_reg;
+ pmhctl->saved_int_en = int_en;
+ int_reg = int_reg & int_en;
+ pmhctl->int_type.count++;
+
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ status_reg = mddi_host_reg_in(STAT);
+
+ if ((int_reg & MDDI_INT_MDDI_IN) ||
+ ((int_en & MDDI_INT_MDDI_IN) &&
+ ((int_reg == 0) || (status_reg & MDDI_STAT_CLIENT_WAKEUP_REQ)))) {
+ /*
+ * The MDDI_IN condition will clear itself, and so it is
+ * possible that MDDI_IN was the reason for the isr firing,
+ * even though the interrupt register does not have the
+ * MDDI_IN bit set. To check if this was the case we need to
+ * look at the status register bit that signifies a client
+ * initiated wakeup. If the status register bit is set, as well
+ * as the MDDI_IN interrupt enabled, then we treat this as a
+ * client initiated wakeup.
+ */
+ if (int_reg & MDDI_INT_MDDI_IN)
+ pmhctl->int_type.in_count++;
+ mddi_process_client_initiated_wakeup();
+ }
+#endif
+
+ if (int_reg & MDDI_INT_LINK_STATE_CHANGES) {
+ pmhctl->int_type.state_change_count++;
+ mddi_report_state_change(int_reg);
+ }
+
+ if (int_reg & MDDI_INT_PRI_LINK_LIST_DONE) {
+ pmhctl->int_type.ll_done_count++;
+ mddi_process_link_list_done();
+ }
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ if (int_reg & MDDI_INT_REV_DATA_AVAIL) {
+ pmhctl->int_type.rev_avail_count++;
+ mddi_process_rev_packets();
+ }
+#endif
+
+ if (int_reg & MDDI_INT_ERROR_CONDITIONS) {
+ pmhctl->int_type.error_count++;
+ mddi_report_errors(int_reg);
+
+ mddi_host_reg_out(INT, int_reg & MDDI_INT_ERROR_CONDITIONS);
+ }
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ mddi_issue_reverse_encapsulation();
+
+ if ((pmhctl->rev_state != MDDI_REV_ENCAP_ISSUED) &&
+ (pmhctl->rev_state != MDDI_REV_STATUS_REQ_ISSUED))
+#endif
+ /* don't want simultaneous reverse and forward with Eagle */
+ mddi_queue_forward_linked_list();
+
+ if (int_reg & MDDI_INT_NO_CMD_PKTS_PEND) {
+ /* this interrupt is used to kick the isr when hibernation is disabled */
+ mddi_host_reg_outm(INTEN, MDDI_INT_NO_CMD_PKTS_PEND, 0);
+ }
+
+ if ((!mddi_host_mdp_active_flag) &&
+ (!mddi_vsync_detect_enabled) &&
+ (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) &&
+ (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) &&
+ (pmhctl->rev_state == MDDI_REV_IDLE)) {
+ if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
+ mddi_host_disable_io_clock();
+ mddi_host_disable_hclk();
+ }
+#ifdef FEATURE_MDDI_HOST_ENABLE_EARLY_HIBERNATION
+ else if ((pmhctl->link_state == MDDI_LINK_ACTIVE) &&
+ (!pmhctl->disable_hibernation)) {
+ mddi_host_reg_out(CMD, MDDI_CMD_POWERDOWN);
+ }
+#endif
+ }
+}
+
+static void mddi_host_isr_primary(void)
+{
+ mddi_curr_host = MDDI_HOST_PRIM;
+ mddi_host_isr();
+}
+
+irqreturn_t mddi_pmdh_isr_proxy(int irq, void *ptr)
+{
+ mddi_host_isr_primary();
+ return IRQ_HANDLED;
+}
+
+static void mddi_host_isr_external(void)
+{
+ mddi_curr_host = MDDI_HOST_EXT;
+ mddi_host_isr();
+ mddi_curr_host = MDDI_HOST_PRIM;
+}
+
+irqreturn_t mddi_emdh_isr_proxy(int irq, void *ptr)
+{
+ mddi_host_isr_external();
+ return IRQ_HANDLED;
+}
+
+static void mddi_host_initialize_registers(mddi_host_type host_idx)
+{
+ uint32 pad_reg_val;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ if (pmhctl->driver_state == MDDI_DRIVER_ENABLED)
+ return;
+
+ /* turn on HCLK to MDDI host core */
+ mddi_host_enable_hclk();
+
+ /* MDDI Reset command */
+ mddi_host_reg_out(CMD, MDDI_CMD_RESET);
+
+ /* Version register (= 0x01) */
+ mddi_host_reg_out(VERSION, 0x0001);
+
+ /* Bytes per subframe register */
+ mddi_host_reg_out(BPS, MDDI_HOST_BYTES_PER_SUBFRAME);
+
+ /* Subframes per media frames register (= 0x03) */
+ mddi_host_reg_out(SPM, 0x0003);
+
+ /* Turn Around 1 register (= 0x05) */
+ mddi_host_reg_out(TA1_LEN, 0x0005);
+
+ /* Turn Around 2 register (= 0x0C) */
+ mddi_host_reg_out(TA2_LEN, MDDI_HOST_TA2_LEN);
+
+ /* Drive hi register (= 0x96) */
+ mddi_host_reg_out(DRIVE_HI, 0x0096);
+
+ /* Drive lo register (= 0x32) */
+ mddi_host_reg_out(DRIVE_LO, 0x0032);
+
+ /* Display wakeup count register (= 0x3c) */
+ mddi_host_reg_out(DISP_WAKE, 0x003c);
+
+ /* Reverse Rate Divisor register (= 0x2) */
+ mddi_host_reg_out(REV_RATE_DIV, MDDI_HOST_REV_RATE_DIV);
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ /* Reverse Pointer Size */
+ mddi_host_reg_out(REV_SIZE, MDDI_REV_BUFFER_SIZE);
+
+ /* Rev Encap Size */
+ mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size);
+#endif
+
+ /* Periodic Rev Encap */
+ /* don't send periodically */
+ mddi_host_reg_out(CMD, MDDI_CMD_PERIODIC_REV_ENCAP);
+
+ pad_reg_val = mddi_host_reg_in(PAD_CTL);
+ if (pad_reg_val == 0) {
+ /* If we are turning on band gap, need to wait 5us before turning
+ * on the rest of the PAD */
+ mddi_host_reg_out(PAD_CTL, 0x08000);
+ udelay(5);
+ }
+#ifdef T_MSM7200
+ /* Recommendation from PAD hw team */
+ mddi_host_reg_out(PAD_CTL, 0xa850a);
+#else
+ /* Recommendation from PAD hw team */
+ mddi_host_reg_out(PAD_CTL, 0xa850f);
+#endif
+
+#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
+ mddi_host_reg_out(PAD_IO_CTL, 0x00320000);
+ mddi_host_reg_out(PAD_CAL, 0x00220020);
+#endif
+
+ mddi_host_core_version = mddi_host_reg_inm(CORE_VER, 0xffff);
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ if (mddi_host_core_version >= 8)
+ mddi_rev_ptr_workaround = FALSE;
+ pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+#endif
+
+ if ((mddi_host_core_version > 8) && (mddi_host_core_version < 0x19))
+ mddi_host_reg_out(TEST, 0x2);
+
+ /* Need an even number for counts */
+ mddi_host_reg_out(DRIVER_START_CNT, 0x60006);
+
+#ifndef T_MSM7500
+ /* Setup defaults for MDP related register */
+ mddi_host_reg_out(MDP_VID_FMT_DES, 0x5666);
+ mddi_host_reg_out(MDP_VID_PIX_ATTR, 0x00C3);
+ mddi_host_reg_out(MDP_VID_CLIENTID, 0);
+#endif
+
+ /* automatically hibernate after 1 empty subframe */
+ if (pmhctl->disable_hibernation)
+ mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE);
+ else
+ mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1);
+
+ /* Bring up link if display (client) requests it */
+#ifdef MDDI_HOST_DISP_LISTEN
+ mddi_host_reg_out(CMD, MDDI_CMD_DISP_LISTEN);
+#else
+ mddi_host_reg_out(CMD, MDDI_CMD_DISP_IGNORE);
+#endif
+
+}
+
+void mddi_host_configure_interrupts(mddi_host_type host_idx, boolean enable)
+{
+ unsigned long flags;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ spin_lock_irqsave(&mddi_host_spin_lock, flags);
+
+ /* turn on HCLK to MDDI host core if it has been disabled */
+ mddi_host_enable_hclk();
+ /* Clear MDDI Interrupt enable reg */
+ mddi_host_reg_out(INTEN, 0);
+
+ spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+ if (enable) {
+ pmhctl->driver_state = MDDI_DRIVER_ENABLED;
+
+ if (host_idx == MDDI_HOST_PRIM) {
+ if (request_irq
+ (INT_MDDI_PRI, mddi_pmdh_isr_proxy, IRQF_DISABLED,
+ "PMDH", 0) != 0)
+ printk(KERN_ERR
+ "a mddi: unable to request_irq\n");
+ else
+ int_mddi_pri_flag = TRUE;
+ } else {
+ if (request_irq
+ (INT_MDDI_EXT, mddi_emdh_isr_proxy, IRQF_DISABLED,
+ "EMDH", 0) != 0)
+ printk(KERN_ERR
+ "b mddi: unable to request_irq\n");
+ else
+ int_mddi_ext_flag = TRUE;
+ }
+
+ /* Set MDDI Interrupt enable reg -- Enable Reverse data avail */
+#ifdef FEATURE_MDDI_DISABLE_REVERSE
+ mddi_host_reg_out(INTEN,
+ MDDI_INT_ERROR_CONDITIONS |
+ MDDI_INT_LINK_STATE_CHANGES);
+#else
+ /* Reverse Pointer register */
+ pmhctl->rev_ptr_written = FALSE;
+
+ mddi_host_reg_out(INTEN,
+ MDDI_INT_REV_DATA_AVAIL |
+ MDDI_INT_ERROR_CONDITIONS |
+ MDDI_INT_LINK_STATE_CHANGES);
+ pmhctl->rtd_counter = mddi_rtd_frequency;
+ pmhctl->client_status_cnt = 0;
+#endif
+ } else {
+ if (pmhctl->driver_state == MDDI_DRIVER_ENABLED)
+ pmhctl->driver_state = MDDI_DRIVER_DISABLED;
+ }
+
+}
+
+static void mddi_host_powerup(mddi_host_type host_idx)
+{
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ if (pmhctl->link_state != MDDI_LINK_DISABLED)
+ return;
+
+ /* enable IO_CLK and hclk to MDDI host core */
+ mddi_host_enable_io_clock();
+
+ mddi_host_initialize_registers(host_idx);
+ mddi_host_configure_interrupts(host_idx, TRUE);
+
+ pmhctl->link_state = MDDI_LINK_ACTIVATING;
+
+ /* Link activate command */
+ mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
+
+#ifdef CLKRGM_MDDI_IO_CLOCK_IN_MHZ
+ MDDI_MSG_NOTICE("MDDI Host: Activating Link %d Mbps\n",
+ CLKRGM_MDDI_IO_CLOCK_IN_MHZ * 2);
+#else
+ MDDI_MSG_NOTICE("MDDI Host: Activating Link\n");
+#endif
+
+ /* Initialize the timer */
+ if (host_idx == MDDI_HOST_PRIM)
+ mddi_host_timer_service(0);
+}
+
+void mddi_host_init(mddi_host_type host_idx)
+/* Write out the MDDI configuration registers */
+{
+ static boolean initialized = FALSE;
+ mddi_host_cntl_type *pmhctl;
+
+ if (host_idx >= MDDI_NUM_HOST_CORES) {
+ MDDI_MSG_ERR("Invalid host core index\n");
+ return;
+ }
+
+ if (!initialized) {
+ uint16 idx;
+ mddi_host_type host;
+ for (host = MDDI_HOST_PRIM; host < MDDI_NUM_HOST_CORES; host++) {
+ pmhctl = &(mhctl[host]);
+ initialized = TRUE;
+
+ pmhctl->llist_ptr =
+ dma_alloc_coherent(NULL, MDDI_LLIST_POOL_SIZE,
+ &(pmhctl->llist_dma_addr),
+ GFP_KERNEL);
+ pmhctl->llist_dma_ptr =
+ (mddi_linked_list_type *) (void *)pmhctl->
+ llist_dma_addr;
+#ifdef FEATURE_MDDI_DISABLE_REVERSE
+ pmhctl->rev_data_buf = NULL;
+ if (pmhctl->llist_ptr == NULL)
+#else
+ mddi_rev_user.waiting = FALSE;
+ init_completion(&(mddi_rev_user.done_comp));
+ pmhctl->rev_data_buf =
+ dma_alloc_coherent(NULL, MDDI_MAX_REV_DATA_SIZE,
+ &(pmhctl->rev_data_dma_addr),
+ GFP_KERNEL);
+ if ((pmhctl->llist_ptr == NULL)
+ || (pmhctl->rev_data_buf == NULL))
+#endif
+ {
+ MDDI_MSG_CRIT
+ ("unable to alloc non-cached memory\n");
+ }
+ llist_extern[host] = pmhctl->llist_ptr;
+ llist_dma_extern[host] = pmhctl->llist_dma_ptr;
+ llist_extern_notify[host] = pmhctl->llist_notify;
+
+ for (idx = 0; idx < UNASSIGNED_INDEX; idx++) {
+ init_completion(&
+ (pmhctl->llist_notify[idx].
+ done_comp));
+ }
+ init_completion(&(pmhctl->mddi_llist_avail_comp));
+ spin_lock_init(&mddi_host_spin_lock);
+ pmhctl->mddi_waiting_for_llist_avail = FALSE;
+ pmhctl->mddi_rev_ptr_write_val =
+ (uint32) (void *)(pmhctl->rev_data_dma_addr);
+ pmhctl->rev_ptr_start = (void *)pmhctl->rev_data_buf;
+
+ pmhctl->rev_pkt_size = MDDI_DEFAULT_REV_PKT_SIZE;
+ pmhctl->rev_state = MDDI_REV_IDLE;
+#ifdef IMAGE_MODEM_PROC
+ /* assume hibernation state is last state from APPS proc, so that
+ * we don't reinitialize the host core */
+ pmhctl->link_state = MDDI_LINK_HIBERNATING;
+#else
+ pmhctl->link_state = MDDI_LINK_DISABLED;
+#endif
+ pmhctl->driver_state = MDDI_DRIVER_DISABLED;
+ pmhctl->disable_hibernation = FALSE;
+
+ /* initialize llist variables */
+ pmhctl->llist_info.transmitting_start_idx =
+ UNASSIGNED_INDEX;
+ pmhctl->llist_info.transmitting_end_idx =
+ UNASSIGNED_INDEX;
+ pmhctl->llist_info.waiting_start_idx = UNASSIGNED_INDEX;
+ pmhctl->llist_info.waiting_end_idx = UNASSIGNED_INDEX;
+ pmhctl->llist_info.reg_read_idx = UNASSIGNED_INDEX;
+ pmhctl->llist_info.next_free_idx =
+ MDDI_FIRST_DYNAMIC_LLIST_IDX;
+ pmhctl->llist_info.reg_read_waiting = FALSE;
+
+ mddi_vsync_detect_enabled = FALSE;
+ mddi_gpio.polling_enabled = FALSE;
+
+ pmhctl->int_type.count = 0;
+ pmhctl->int_type.in_count = 0;
+ pmhctl->int_type.disp_req_count = 0;
+ pmhctl->int_type.state_change_count = 0;
+ pmhctl->int_type.ll_done_count = 0;
+ pmhctl->int_type.rev_avail_count = 0;
+ pmhctl->int_type.error_count = 0;
+ pmhctl->int_type.rev_encap_count = 0;
+ pmhctl->int_type.llist_ptr_write_1 = 0;
+ pmhctl->int_type.llist_ptr_write_2 = 0;
+
+ pmhctl->stats.fwd_crc_count = 0;
+ pmhctl->stats.rev_crc_count = 0;
+ pmhctl->stats.pri_underflow = 0;
+ pmhctl->stats.sec_underflow = 0;
+ pmhctl->stats.rev_overflow = 0;
+ pmhctl->stats.pri_overwrite = 0;
+ pmhctl->stats.sec_overwrite = 0;
+ pmhctl->stats.rev_overwrite = 0;
+ pmhctl->stats.dma_failure = 0;
+ pmhctl->stats.rtd_failure = 0;
+ pmhctl->stats.reg_read_failure = 0;
+#ifdef FEATURE_MDDI_UNDERRUN_RECOVERY
+ pmhctl->stats.pri_underrun_detected = 0;
+#endif
+
+ pmhctl->log_parms.rtd_cnt = 0;
+ pmhctl->log_parms.rev_enc_cnt = 0;
+ pmhctl->log_parms.vid_cnt = 0;
+ pmhctl->log_parms.reg_acc_cnt = 0;
+ pmhctl->log_parms.cli_stat_cnt = 0;
+ pmhctl->log_parms.cli_cap_cnt = 0;
+ pmhctl->log_parms.reg_read_cnt = 0;
+ pmhctl->log_parms.link_active_cnt = 0;
+ pmhctl->log_parms.link_hibernate_cnt = 0;
+ pmhctl->log_parms.fwd_crc_cnt = 0;
+ pmhctl->log_parms.rev_crc_cnt = 0;
+ pmhctl->log_parms.vsync_response_cnt = 0;
+
+ prev_parms[host_idx] = pmhctl->log_parms;
+ mddi_client_capability_pkt.packet_length = 0;
+ }
+
+#ifndef T_MSM7500
+ /* tell clock driver we are user of this PLL */
+ MDDI_HOST_ENABLE_IO_CLOCK;
+#endif
+ }
+
+ mddi_host_powerup(host_idx);
+ pmhctl = &(mhctl[host_idx]);
+}
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+static uint32 mddi_client_id;
+
+uint32 mddi_get_client_id(void)
+{
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ mddi_host_type host_idx = MDDI_HOST_PRIM;
+ static boolean client_detection_try = FALSE;
+ mddi_host_cntl_type *pmhctl;
+ unsigned long flags;
+ uint16 saved_rev_pkt_size;
+
+ if (!client_detection_try) {
+ /* Toshiba display requires larger drive_lo value */
+ mddi_host_reg_out(DRIVE_LO, 0x0050);
+
+ pmhctl = &(mhctl[MDDI_HOST_PRIM]);
+
+ saved_rev_pkt_size = pmhctl->rev_pkt_size;
+
+ /* Increase Rev Encap Size */
+ pmhctl->rev_pkt_size = MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE;
+ mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size);
+
+ /* disable hibernation temporarily */
+ if (!pmhctl->disable_hibernation)
+ mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE);
+
+ mddi_rev_user.waiting = TRUE;
+ INIT_COMPLETION(mddi_rev_user.done_comp);
+
+ spin_lock_irqsave(&mddi_host_spin_lock, flags);
+
+ /* turn on clock(s), if they have been disabled */
+ mddi_host_enable_hclk();
+ mddi_host_enable_io_clock();
+
+ mddi_client_capability_request = TRUE;
+
+ if (pmhctl->rev_state == MDDI_REV_IDLE) {
+ /* attempt to send the reverse encapsulation now */
+ mddi_issue_reverse_encapsulation();
+ }
+ spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+ wait_for_completion_killable(&(mddi_rev_user.done_comp));
+
+ /* Set Rev Encap Size back to its original value */
+ pmhctl->rev_pkt_size = saved_rev_pkt_size;
+ mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size);
+
+ /* reenable auto-hibernate */
+ if (!pmhctl->disable_hibernation)
+ mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1);
+
+ mddi_host_reg_out(DRIVE_LO, 0x0032);
+ client_detection_try = TRUE;
+
+ mddi_client_id = (mddi_client_capability_pkt.Mfr_Name<<16) |
+ mddi_client_capability_pkt.Product_Code;
+
+ if (!mddi_client_id)
+ mddi_disable(1);
+ }
+
+#if 0
+ switch (mddi_client_capability_pkt.Mfr_Name) {
+ case 0x4474:
+ if ((mddi_client_capability_pkt.Product_Code != 0x8960) &&
+ (target == DISPLAY_1)) {
+ ret = PRISM_WVGA;
+ }
+ break;
+
+ case 0xD263:
+ if (target == DISPLAY_1)
+ ret = TOSHIBA_VGA_PRIM;
+ else if (target == DISPLAY_2)
+ ret = TOSHIBA_QCIF_SECD;
+ break;
+
+ case 0:
+ if (mddi_client_capability_pkt.Product_Code == 0x8835) {
+ if (target == DISPLAY_1)
+ ret = SHARP_QVGA_PRIM;
+ else if (target == DISPLAY_2)
+ ret = SHARP_128x128_SECD;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if ((!client_detection_try) && (ret != TOSHIBA_VGA_PRIM)
+ && (ret != TOSHIBA_QCIF_SECD)) {
+ /* Not a Toshiba display, so change drive_lo back to default value */
+ mddi_host_reg_out(DRIVE_LO, 0x0032);
+ }
+#endif
+
+#endif
+
+ return mddi_client_id;
+}
+#endif
+
+void mddi_host_powerdown(mddi_host_type host_idx)
+{
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ if (host_idx >= MDDI_NUM_HOST_CORES) {
+ MDDI_MSG_ERR("Invalid host core index\n");
+ return;
+ }
+
+ if (pmhctl->driver_state == MDDI_DRIVER_RESET) {
+ return;
+ }
+
+ if (host_idx == MDDI_HOST_PRIM) {
+ /* disable timer */
+ del_timer(&mddi_host_timer);
+ }
+
+ mddi_host_configure_interrupts(host_idx, FALSE);
+
+ /* turn on HCLK to MDDI host core if it has been disabled */
+ mddi_host_enable_hclk();
+
+ /* MDDI Reset command */
+ mddi_host_reg_out(CMD, MDDI_CMD_RESET);
+
+ /* Pad Control Register */
+ mddi_host_reg_out(PAD_CTL, 0x0);
+
+ /* disable IO_CLK and hclk to MDDI host core */
+ mddi_host_disable_io_clock();
+ mddi_host_disable_hclk();
+
+ pmhctl->link_state = MDDI_LINK_DISABLED;
+ pmhctl->driver_state = MDDI_DRIVER_RESET;
+
+ MDDI_MSG_NOTICE("MDDI Host: Disabling Link\n");
+
+}
+
+uint16 mddi_get_next_free_llist_item(mddi_host_type host_idx, boolean wait)
+{
+ unsigned long flags;
+ uint16 ret_idx;
+ boolean forced_wait = FALSE;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ ret_idx = pmhctl->llist_info.next_free_idx;
+
+ pmhctl->llist_info.next_free_idx++;
+ if (pmhctl->llist_info.next_free_idx >= MDDI_NUM_DYNAMIC_LLIST_ITEMS)
+ pmhctl->llist_info.next_free_idx = MDDI_FIRST_DYNAMIC_LLIST_IDX;
+ spin_lock_irqsave(&mddi_host_spin_lock, flags);
+ if (pmhctl->llist_notify[ret_idx].in_use) {
+ if (!wait) {
+ pmhctl->llist_info.next_free_idx = ret_idx;
+ ret_idx = UNASSIGNED_INDEX;
+ } else {
+ forced_wait = TRUE;
+ INIT_COMPLETION(pmhctl->mddi_llist_avail_comp);
+ }
+ }
+ spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+ if (forced_wait) {
+ wait_for_completion_killable(&
+ (pmhctl->
+ mddi_llist_avail_comp));
+ MDDI_MSG_ERR("task waiting on mddi llist item\n");
+ }
+
+ if (ret_idx != UNASSIGNED_INDEX) {
+ pmhctl->llist_notify[ret_idx].waiting = FALSE;
+ pmhctl->llist_notify[ret_idx].done_cb = NULL;
+ pmhctl->llist_notify[ret_idx].in_use = TRUE;
+ pmhctl->llist_notify[ret_idx].next_idx = UNASSIGNED_INDEX;
+ }
+
+ return ret_idx;
+}
+
+uint16 mddi_get_reg_read_llist_item(mddi_host_type host_idx, boolean wait)
+{
+#ifdef FEATURE_MDDI_DISABLE_REVERSE
+ MDDI_MSG_CRIT("No reverse link available\n");
+ (void)wait;
+ return FALSE;
+#else
+ unsigned long flags;
+ uint16 ret_idx;
+ boolean error = FALSE;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ spin_lock_irqsave(&mddi_host_spin_lock, flags);
+ if (pmhctl->llist_info.reg_read_idx != UNASSIGNED_INDEX) {
+ /* need to block here or is this an error condition? */
+ error = TRUE;
+ ret_idx = UNASSIGNED_INDEX;
+ }
+ spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+ if (!error) {
+ ret_idx = pmhctl->llist_info.reg_read_idx =
+ mddi_get_next_free_llist_item(host_idx, wait);
+ /* clear the reg_read_waiting flag */
+ pmhctl->llist_info.reg_read_waiting = FALSE;
+ }
+
+ if (error)
+ MDDI_MSG_ERR("***** Reg read still in progress! ****\n");
+ return ret_idx;
+#endif
+
+}
+
+void mddi_queue_forward_packets(uint16 first_llist_idx,
+ uint16 last_llist_idx,
+ boolean wait,
+ mddi_llist_done_cb_type llist_done_cb,
+ mddi_host_type host_idx)
+{
+ unsigned long flags;
+ mddi_linked_list_type *llist;
+ mddi_linked_list_type *llist_dma;
+ mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+ if ((first_llist_idx >= UNASSIGNED_INDEX) ||
+ (last_llist_idx >= UNASSIGNED_INDEX)) {
+ MDDI_MSG_ERR("MDDI queueing invalid linked list\n");
+ return;
+ }
+
+ if (pmhctl->link_state == MDDI_LINK_DISABLED)
+ MDDI_MSG_CRIT("MDDI host powered down!\n");
+
+ llist = pmhctl->llist_ptr;
+ llist_dma = pmhctl->llist_dma_ptr;
+
+ /* clean cache so MDDI host can read data */
+ memory_barrier();
+
+ pmhctl->llist_notify[last_llist_idx].waiting = wait;
+ if (wait)
+ INIT_COMPLETION(pmhctl->llist_notify[last_llist_idx].done_comp);
+ pmhctl->llist_notify[last_llist_idx].done_cb = llist_done_cb;
+
+ spin_lock_irqsave(&mddi_host_spin_lock, flags);
+
+ if ((pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) &&
+ (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) &&
+ (pmhctl->rev_state == MDDI_REV_IDLE)) {
+ /* no packets are currently transmitting */
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ if (first_llist_idx == pmhctl->llist_info.reg_read_idx) {
+ /* This is the special case where the packet is a register read. */
+ pmhctl->rev_state = MDDI_REV_REG_READ_ISSUED;
+ mddi_reg_read_retry = 0;
+ /* mddi_rev_reg_read_attempt = 1; */
+ }
+#endif
+ /* assign transmitting index values */
+ pmhctl->llist_info.transmitting_start_idx = first_llist_idx;
+ pmhctl->llist_info.transmitting_end_idx = last_llist_idx;
+
+ /* turn on clock(s), if they have been disabled */
+ mddi_host_enable_hclk();
+ mddi_host_enable_io_clock();
+ pmhctl->int_type.llist_ptr_write_1++;
+ /* Write to primary pointer register */
+ dma_coherent_pre_ops();
+ mddi_host_reg_out(PRI_PTR, &llist_dma[first_llist_idx]);
+
+ /* enable interrupt when complete */
+ mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE,
+ MDDI_INT_PRI_LINK_LIST_DONE);
+
+ } else if (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) {
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ if (first_llist_idx == pmhctl->llist_info.reg_read_idx) {
+ /*
+ * we have a register read to send but need to wait
+ * for current reverse activity to end or there are
+ * packets currently transmitting
+ */
+ /* mddi_rev_reg_read_attempt = 0; */
+ pmhctl->llist_info.reg_read_waiting = TRUE;
+ }
+#endif
+
+ /* assign waiting index values */
+ pmhctl->llist_info.waiting_start_idx = first_llist_idx;
+ pmhctl->llist_info.waiting_end_idx = last_llist_idx;
+ } else {
+ uint16 prev_end_idx = pmhctl->llist_info.waiting_end_idx;
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+ if (first_llist_idx == pmhctl->llist_info.reg_read_idx) {
+ /*
+ * we have a register read to send but need to wait
+ * for current reverse activity to end or there are
+ * packets currently transmitting
+ */
+ /* mddi_rev_reg_read_attempt = 0; */
+ pmhctl->llist_info.reg_read_waiting = TRUE;
+ }
+#endif
+
+ llist = pmhctl->llist_ptr;
+
+ /* clear end flag in previous last packet */
+ llist[prev_end_idx].link_controller_flags = 0;
+ pmhctl->llist_notify[prev_end_idx].next_idx = first_llist_idx;
+
+ /* set the next_packet_pointer of the previous last packet */
+ llist[prev_end_idx].next_packet_pointer =
+ (void *)(&llist_dma[first_llist_idx]);
+
+ /* clean cache so MDDI host can read data */
+ memory_barrier();
+
+ /* assign new waiting last index value */
+ pmhctl->llist_info.waiting_end_idx = last_llist_idx;
+ }
+
+ spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+}
+
+void mddi_host_write_pix_attr_reg(uint32 value)
+{
+ (void)value;
+}
+
+void mddi_queue_reverse_encapsulation(boolean wait)
+{
+#ifdef FEATURE_MDDI_DISABLE_REVERSE
+ MDDI_MSG_CRIT("No reverse link available\n");
+ (void)wait;
+#else
+ unsigned long flags;
+ boolean error = FALSE;
+ mddi_host_type host_idx = MDDI_HOST_PRIM;
+ mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]);
+
+ spin_lock_irqsave(&mddi_host_spin_lock, flags);
+
+ /* turn on clock(s), if they have been disabled */
+ mddi_host_enable_hclk();
+ mddi_host_enable_io_clock();
+
+ if (wait) {
+ if (!mddi_rev_user.waiting) {
+ mddi_rev_user.waiting = TRUE;
+ INIT_COMPLETION(mddi_rev_user.done_comp);
+ } else
+ error = TRUE;
+ }
+ mddi_rev_encap_user_request = TRUE;
+
+ if (pmhctl->rev_state == MDDI_REV_IDLE) {
+ /* attempt to send the reverse encapsulation now */
+ mddi_host_type orig_host_idx = mddi_curr_host;
+ mddi_curr_host = host_idx;
+ mddi_issue_reverse_encapsulation();
+ mddi_curr_host = orig_host_idx;
+ }
+ spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+ if (error) {
+ MDDI_MSG_ERR("Reverse Encap request already in progress\n");
+ } else if (wait)
+ wait_for_completion_killable(&(mddi_rev_user.done_comp));
+#endif
+}
+
+/* ISR to be executed */
+boolean mddi_set_rev_handler(mddi_rev_handler_type handler, uint16 pkt_type)
+{
+#ifdef FEATURE_MDDI_DISABLE_REVERSE
+ MDDI_MSG_CRIT("No reverse link available\n");
+ (void)handler;
+ (void)pkt_type;
+ return (FALSE);
+#else
+ unsigned long flags;
+ uint16 hdlr;
+ boolean handler_set = FALSE;
+ boolean overwrite = FALSE;
+ mddi_host_type host_idx = MDDI_HOST_PRIM;
+ mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]);
+
+ /* Disable interrupts */
+ spin_lock_irqsave(&mddi_host_spin_lock, flags);
+
+ for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS; hdlr++) {
+ if (mddi_rev_pkt_handler[hdlr].pkt_type == pkt_type) {
+ mddi_rev_pkt_handler[hdlr].handler = handler;
+ if (handler == NULL) {
+ /* clearing handler from table */
+ mddi_rev_pkt_handler[hdlr].pkt_type =
+ INVALID_PKT_TYPE;
+ handler_set = TRUE;
+ if (pkt_type == 0x10) { /* video stream packet */
+ /* ensure HCLK on to MDDI host core before register write */
+ mddi_host_enable_hclk();
+ /* No longer getting video, so reset rev encap size to default */
+ pmhctl->rev_pkt_size =
+ MDDI_DEFAULT_REV_PKT_SIZE;
+ mddi_host_reg_out(REV_ENCAP_SZ,
+ pmhctl->rev_pkt_size);
+ }
+ } else {
+ /* already a handler for this packet */
+ overwrite = TRUE;
+ }
+ break;
+ }
+ }
+ if ((hdlr >= MAX_MDDI_REV_HANDLERS) && (handler != NULL)) {
+ /* assigning new handler */
+ for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS; hdlr++) {
+ if (mddi_rev_pkt_handler[hdlr].pkt_type ==
+ INVALID_PKT_TYPE) {
+ if ((pkt_type == 0x10) && /* video stream packet */
+ (pmhctl->rev_pkt_size <
+ MDDI_VIDEO_REV_PKT_SIZE)) {
+ /* ensure HCLK on to MDDI host core before register write */
+ mddi_host_enable_hclk();
+ /* Increase Rev Encap Size */
+ pmhctl->rev_pkt_size =
+ MDDI_VIDEO_REV_PKT_SIZE;
+ mddi_host_reg_out(REV_ENCAP_SZ,
+ pmhctl->rev_pkt_size);
+ }
+ mddi_rev_pkt_handler[hdlr].handler = handler;
+ mddi_rev_pkt_handler[hdlr].pkt_type = pkt_type;
+ handler_set = TRUE;
+ break;
+ }
+ }
+ }
+
+ /* Restore interrupts */
+ spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+ if (overwrite)
+ MDDI_MSG_ERR("Overwriting previous rev packet handler\n");
+
+ return handler_set;
+
+#endif
+} /* mddi_set_rev_handler */
+
+void mddi_host_disable_hibernation(boolean disable)
+{
+ mddi_host_type host_idx = MDDI_HOST_PRIM;
+ mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]);
+
+ if (disable) {
+ pmhctl->disable_hibernation = TRUE;
+ /* hibernation will be turned off by isr next time it is entered */
+ } else {
+ if (pmhctl->disable_hibernation) {
+ unsigned long flags;
+ spin_lock_irqsave(&mddi_host_spin_lock, flags);
+ if (!MDDI_HOST_IS_HCLK_ON)
+ MDDI_HOST_ENABLE_HCLK;
+ mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1);
+ spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+ pmhctl->disable_hibernation = FALSE;
+ }
+ }
+}
+
+void mddi_mhctl_remove(mddi_host_type host_idx)
+{
+ mddi_host_cntl_type *pmhctl;
+
+ pmhctl = &(mhctl[host_idx]);
+
+ dma_free_coherent(NULL, MDDI_LLIST_POOL_SIZE, (void *)pmhctl->llist_ptr,
+ pmhctl->llist_dma_addr);
+
+ dma_free_coherent(NULL, MDDI_MAX_REV_DATA_SIZE,
+ (void *)pmhctl->rev_data_buf,
+ pmhctl->rev_data_dma_addr);
+}
diff --git a/drivers/staging/msm/mddihosti.h b/drivers/staging/msm/mddihosti.h
new file mode 100644
index 0000000..7b26a42
--- /dev/null
+++ b/drivers/staging/msm/mddihosti.h
@@ -0,0 +1,547 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 Code Aurora 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, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT 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 MDDIHOSTI_H
+#define MDDIHOSTI_H
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include <linux/clk.h>
+
+/* Register offsets in MDDI, applies to both msm_pmdh_base and
+ * (u32)msm_emdh_base. */
+#define MDDI_CMD 0x0000
+#define MDDI_VERSION 0x0004
+#define MDDI_PRI_PTR 0x0008
+#define MDDI_BPS 0x0010
+#define MDDI_SPM 0x0014
+#define MDDI_INT 0x0018
+#define MDDI_INTEN 0x001c
+#define MDDI_REV_PTR 0x0020
+#define MDDI_REV_SIZE 0x0024
+#define MDDI_STAT 0x0028
+#define MDDI_REV_RATE_DIV 0x002c
+#define MDDI_REV_CRC_ERR 0x0030
+#define MDDI_TA1_LEN 0x0034
+#define MDDI_TA2_LEN 0x0038
+#define MDDI_TEST 0x0040
+#define MDDI_REV_PKT_CNT 0x0044
+#define MDDI_DRIVE_HI 0x0048
+#define MDDI_DRIVE_LO 0x004c
+#define MDDI_DISP_WAKE 0x0050
+#define MDDI_REV_ENCAP_SZ 0x0054
+#define MDDI_RTD_VAL 0x0058
+#define MDDI_PAD_CTL 0x0068
+#define MDDI_DRIVER_START_CNT 0x006c
+#define MDDI_CORE_VER 0x008c
+#define MDDI_FIFO_ALLOC 0x0090
+#define MDDI_PAD_IO_CTL 0x00a0
+#define MDDI_PAD_CAL 0x00a4
+
+extern u32 mddi_msg_level;
+
+/* No longer need to write to clear these registers */
+#define xxxx_mddi_host_reg_outm(reg, mask, val) \
+do { \
+ if (host_idx == MDDI_HOST_PRIM) \
+ mddi_host_reg_outm_pmdh(reg, mask, val); \
+ else \
+ mddi_host_reg_outm_emdh(reg, mask, val); \
+} while (0)
+
+#define mddi_host_reg_outm(reg, mask, val) \
+do { \
+ unsigned long __addr; \
+ if (host_idx == MDDI_HOST_PRIM) \
+ __addr = (u32)msm_pmdh_base + MDDI_##reg; \
+ else \
+ __addr = (u32)msm_emdh_base + MDDI_##reg; \
+ writel((readl(__addr) & ~(mask)) | ((val) & (mask)), __addr); \
+} while (0)
+
+#define xxxx_mddi_host_reg_out(reg, val) \
+do { \
+ if (host_idx == MDDI_HOST_PRIM) \
+ mddi_host_reg_out_pmdh(reg, val); \
+ else \
+ mddi_host_reg_out_emdh(reg, val); \
+ } while (0)
+
+#define mddi_host_reg_out(reg, val) \
+do { \
+ if (host_idx == MDDI_HOST_PRIM) \
+ writel(val, (u32)msm_pmdh_base + MDDI_##reg); \
+ else \
+ writel(val, (u32)msm_emdh_base + MDDI_##reg); \
+} while (0)
+
+#define xxxx_mddi_host_reg_in(reg) \
+ ((host_idx) ? \
+ mddi_host_reg_in_emdh(reg) : mddi_host_reg_in_pmdh(reg));
+
+#define mddi_host_reg_in(reg) \
+((host_idx) ? \
+ readl((u32)msm_emdh_base + MDDI_##reg) : \
+ readl((u32)msm_pmdh_base + MDDI_##reg)) \
+
+#define xxxx_mddi_host_reg_inm(reg, mask) \
+ ((host_idx) ? \
+ mddi_host_reg_inm_emdh(reg, mask) : \
+ mddi_host_reg_inm_pmdh(reg, mask);)
+
+#define mddi_host_reg_inm(reg, mask) \
+((host_idx) ? \
+ readl((u32)msm_emdh_base + MDDI_##reg) & (mask) : \
+ readl((u32)msm_pmdh_base + MDDI_##reg) & (mask)) \
+
+/* Using non-cacheable pmem, so do nothing */
+#define mddi_invalidate_cache_lines(addr_start, num_bytes)
+/*
+ * Using non-cacheable pmem, so do nothing with cache
+ * but, ensure write goes out to memory
+ */
+#define mddi_flush_cache_lines(addr_start, num_bytes) \
+ (void) addr_start; \
+ (void) num_bytes; \
+ memory_barrier()
+
+/* Since this translates to Remote Procedure Calls to check on clock status
+* just use a local variable to keep track of io_clock */
+#define MDDI_HOST_IS_IO_CLOCK_ON mddi_host_io_clock_on
+#define MDDI_HOST_ENABLE_IO_CLOCK
+#define MDDI_HOST_DISABLE_IO_CLOCK
+#define MDDI_HOST_IS_HCLK_ON mddi_host_hclk_on
+#define MDDI_HOST_ENABLE_HCLK
+#define MDDI_HOST_DISABLE_HCLK
+#define FEATURE_MDDI_HOST_IO_CLOCK_CONTROL_DISABLE
+#define FEATURE_MDDI_HOST_HCLK_CONTROL_DISABLE
+
+#define TRAMP_MDDI_HOST_ISR TRAMP_MDDI_PRI_ISR
+#define TRAMP_MDDI_HOST_EXT_ISR TRAMP_MDDI_EXT_ISR
+#define MDP_LINE_COUNT_BMSK 0x3ff
+#define MDP_SYNC_STATUS 0x000c
+#define MDP_LINE_COUNT \
+(readl(msm_mdp_base + MDP_SYNC_STATUS) & MDP_LINE_COUNT_BMSK)
+
+/* MDP sends 256 pixel packets, so lower value hibernates more without
+* significantly increasing latency of waiting for next subframe */
+#define MDDI_HOST_BYTES_PER_SUBFRAME 0x3C00
+
+#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
+#define MDDI_HOST_TA2_LEN 0x001a
+#define MDDI_HOST_REV_RATE_DIV 0x0004
+#else
+#define MDDI_HOST_TA2_LEN 0x000c
+#define MDDI_HOST_REV_RATE_DIV 0x0002
+#endif
+
+#define MDDI_MSG_EMERG(msg, ...) \
+ if (mddi_msg_level > 0) \
+ printk(KERN_EMERG msg, ## __VA_ARGS__);
+#define MDDI_MSG_ALERT(msg, ...) \
+ if (mddi_msg_level > 1) \
+ printk(KERN_ALERT msg, ## __VA_ARGS__);
+#define MDDI_MSG_CRIT(msg, ...) \
+ if (mddi_msg_level > 2) \
+ printk(KERN_CRIT msg, ## __VA_ARGS__);
+#define MDDI_MSG_ERR(msg, ...) \
+ if (mddi_msg_level > 3) \
+ printk(KERN_ERR msg, ## __VA_ARGS__);
+#define MDDI_MSG_WARNING(msg, ...) \
+ if (mddi_msg_level > 4) \
+ printk(KERN_WARNING msg, ## __VA_ARGS__);
+#define MDDI_MSG_NOTICE(msg, ...) \
+ if (mddi_msg_level > 5) \
+ printk(KERN_NOTICE msg, ## __VA_ARGS__);
+#define MDDI_MSG_INFO(msg, ...) \
+ if (mddi_msg_level > 6) \
+ printk(KERN_INFO msg, ## __VA_ARGS__);
+#define MDDI_MSG_DEBUG(msg, ...) \
+ if (mddi_msg_level > 7) \
+ printk(KERN_DEBUG msg, ## __VA_ARGS__);
+
+#define GCC_PACKED __attribute__((packed))
+typedef struct GCC_PACKED {
+ uint16 packet_length;
+ /* total # of bytes in the packet not including
+ the packet_length field. */
+
+ uint16 packet_type;
+ /* A Packet Type of 70 identifies the packet as
+ a Client status Packet. */
+
+ uint16 bClient_ID;
+ /* This field is reserved for future use and shall
+ be set to zero. */
+
+} mddi_rev_packet_type;
+
+typedef struct GCC_PACKED {
+ uint16 packet_length;
+ /* total # of bytes in the packet not including
+ the packet_length field. */
+
+ uint16 packet_type;
+ /* A Packet Type of 70 identifies the packet as
+ a Client status Packet. */
+
+ uint16 bClient_ID;
+ /* This field is reserved for future use and shall
+ be set to zero. */
+
+ uint16 reverse_link_request;
+ /* 16 bit unsigned integer with number of bytes client
+ needs in the * reverse encapsulation message
+ to transmit data. */
+
+ uint8 crc_error_count;
+ uint8 capability_change;
+ uint16 graphics_busy_flags;
+
+ uint16 parameter_CRC;
+ /* 16-bit CRC of all the bytes in the packet
+ including Packet Length. */
+
+} mddi_client_status_type;
+
+typedef struct GCC_PACKED {
+ uint16 packet_length;
+ /* total # of bytes in the packet not including
+ the packet_length field. */
+
+ uint16 packet_type;
+ /* A Packet Type of 66 identifies the packet as
+ a Client Capability Packet. */
+
+ uint16 bClient_ID;
+ /* This field is reserved for future use and
+ shall be set to zero. */
+
+ uint16 Protocol_Version;
+ uint16 Minimum_Protocol_Version;
+ uint16 Data_Rate_Capability;
+ uint8 Interface_Type_Capability;
+ uint8 Number_of_Alt_Displays;
+ uint16 PostCal_Data_Rate;
+ uint16 Bitmap_Width;
+ uint16 Bitmap_Height;
+ uint16 Display_Window_Width;
+ uint16 Display_Window_Height;
+ uint32 Color_Map_Size;
+ uint16 Color_Map_RGB_Width;
+ uint16 RGB_Capability;
+ uint8 Monochrome_Capability;
+ uint8 Reserved_1;
+ uint16 Y_Cb_Cr_Capability;
+ uint16 Bayer_Capability;
+ uint16 Alpha_Cursor_Image_Planes;
+ uint32 Client_Feature_Capability_Indicators;
+ uint8 Maximum_Video_Frame_Rate_Capability;
+ uint8 Minimum_Video_Frame_Rate_Capability;
+ uint16 Minimum_Sub_frame_Rate;
+ uint16 Audio_Buffer_Depth;
+ uint16 Audio_Channel_Capability;
+ uint16 Audio_Sample_Rate_Capability;
+ uint8 Audio_Sample_Resolution;
+ uint8 Mic_Audio_Sample_Resolution;
+ uint16 Mic_Sample_Rate_Capability;
+ uint8 Keyboard_Data_Format;
+ uint8 pointing_device_data_format;
+ uint16 content_protection_type;
+ uint16 Mfr_Name;
+ uint16 Product_Code;
+ uint16 Reserved_3;
+ uint32 Serial_Number;
+ uint8 Week_of_Manufacture;
+ uint8 Year_of_Manufacture;
+
+ uint16 parameter_CRC;
+ /* 16-bit CRC of all the bytes in the packet including Packet Length. */
+
+} mddi_client_capability_type;
+
+typedef struct GCC_PACKED {
+ uint16 packet_length;
+ /* total # of bytes in the packet not including the packet_length field. */
+
+ uint16 packet_type;
+ /* A Packet Type of 16 identifies the packet as a Video Stream Packet. */
+
+ uint16 bClient_ID;
+ /* This field is reserved for future use and shall be set to zero. */
+
+ uint16 video_data_format_descriptor;
+ /* format of each pixel in the Pixel Data in the present stream in the
+ * present packet.
+ * If bits [15:13] = 000 monochrome
+ * If bits [15:13] = 001 color pixels (palette).
+ * If bits [15:13] = 010 color pixels in raw RGB
+ * If bits [15:13] = 011 data in 4:2:2 Y Cb Cr format
+ * If bits [15:13] = 100 Bayer pixels
+ */
+
+ uint16 pixel_data_attributes;
+ /* interpreted as follows:
+ * Bits [1:0] = 11 pixel data is displayed to both eyes
+ * Bits [1:0] = 10 pixel data is routed to the left eye only.
+ * Bits [1:0] = 01 pixel data is routed to the right eye only.
+ * Bits [1:0] = 00 pixel data is routed to the alternate display.
+ * Bit 2 is 0 Pixel Data is in the standard progressive format.
+ * Bit 2 is 1 Pixel Data is in interlace format.
+ * Bit 3 is 0 Pixel Data is in the standard progressive format.
+ * Bit 3 is 1 Pixel Data is in alternate pixel format.
+ * Bit 4 is 0 Pixel Data is to or from the display frame buffer.
+ * Bit 4 is 1 Pixel Data is to or from the camera.
+ * Bit 5 is 0 pixel data contains the next consecutive row of pixels.
+ * Bit 5 is 1 X Left Edge, Y Top Edge, X Right Edge, Y Bottom Edge,
+ * X Start, and Y Start parameters are not defined and
+ * shall be ignored by the client.
+ * Bits [7:6] = 01 Pixel data is written to the offline image buffer.
+ * Bits [7:6] = 00 Pixel data is written to the buffer to refresh display.
+ * Bits [7:6] = 11 Pixel data is written to all image buffers.
+ * Bits [7:6] = 10 Invalid. Reserved for future use.
+ * Bits 8 through 11 alternate display number.
+ * Bits 12 through 14 are reserved for future use and shall be set to zero.
+ * Bit 15 is 1 the row of pixels is the last row of pixels in a frame.
+ */
+
+ uint16 x_left_edge;
+ uint16 y_top_edge;
+ /* X,Y coordinate of the top left edge of the screen window */
+
+ uint16 x_right_edge;
+ uint16 y_bottom_edge;
+ /* X,Y coordinate of the bottom right edge of the window being updated. */
+
+ uint16 x_start;
+ uint16 y_start;
+ /* (X Start, Y Start) is the first pixel in the Pixel Data field below. */
+
+ uint16 pixel_count;
+ /* number of pixels in the Pixel Data field below. */
+
+ uint16 parameter_CRC;
+ /* 16-bit CRC of all bytes from the Packet Length to the Pixel Count. */
+
+ uint16 reserved;
+ /* 16-bit variable to make structure align on 4 byte boundary */
+
+} mddi_video_stream_packet_type;
+
+typedef struct GCC_PACKED {
+ uint16 packet_length;
+ /* total # of bytes in the packet not including the packet_length field. */
+
+ uint16 packet_type;
+ /* A Packet Type of 146 identifies the packet as a Register Access Packet. */
+
+ uint16 bClient_ID;
+ /* This field is reserved for future use and shall be set to zero. */
+
+ uint16 read_write_info;
+ /* Bits 13:0 a 14-bit unsigned integer that specifies the number of
+ * 32-bit Register Data List items to be transferred in the
+ * Register Data List field.
+ * Bits[15:14] = 00 Write to register(s);
+ * Bits[15:14] = 10 Read from register(s);
+ * Bits[15:14] = 11 Response to a Read.
+ * Bits[15:14] = 01 this value is reserved for future use. */
+
+ uint32 register_address;
+ /* the register address that is to be written to or read from. */
+
+ uint16 parameter_CRC;
+ /* 16-bit CRC of all bytes from the Packet Length to the Register Address. */
+
+ uint32 register_data_list;
+ /* list of 4-byte register data values for/from client registers */
+
+} mddi_register_access_packet_type;
+
+typedef union GCC_PACKED {
+ mddi_video_stream_packet_type video_pkt;
+ mddi_register_access_packet_type register_pkt;
+ /* add 48 byte pad to ensure 64 byte llist struct, that can be
+ * manipulated easily with cache */
+ uint32 alignment_pad[12]; /* 48 bytes */
+} mddi_packet_header_type;
+
+typedef struct GCC_PACKED mddi_host_llist_struct {
+ uint16 link_controller_flags;
+ uint16 packet_header_count;
+ uint16 packet_data_count;
+ void *packet_data_pointer;
+ struct mddi_host_llist_struct *next_packet_pointer;
+ uint16 reserved;
+ mddi_packet_header_type packet_header;
+} mddi_linked_list_type;
+
+typedef struct {
+ struct completion done_comp;
+ mddi_llist_done_cb_type done_cb;
+ uint16 next_idx;
+ boolean waiting;
+ boolean in_use;
+} mddi_linked_list_notify_type;
+
+#define MDDI_LLIST_POOL_SIZE 0x1000
+#define MDDI_MAX_NUM_LLIST_ITEMS (MDDI_LLIST_POOL_SIZE / \
+ sizeof(mddi_linked_list_type))
+#define UNASSIGNED_INDEX MDDI_MAX_NUM_LLIST_ITEMS
+#define MDDI_FIRST_DYNAMIC_LLIST_IDX 0
+
+/* Static llist items can be used for applications that frequently send
+ * the same set of packets using the linked list interface. */
+/* Here we configure for 6 static linked list items:
+ * The 1st is used for a the adaptive backlight setting.
+ * and the remaining 5 are used for sending window adjustments for
+ * MDDI clients that need windowing info sent separate from video
+ * packets. */
+#define MDDI_NUM_STATIC_ABL_ITEMS 1
+#define MDDI_NUM_STATIC_WINDOW_ITEMS 5
+#define MDDI_NUM_STATIC_LLIST_ITEMS (MDDI_NUM_STATIC_ABL_ITEMS + \
+ MDDI_NUM_STATIC_WINDOW_ITEMS)
+#define MDDI_NUM_DYNAMIC_LLIST_ITEMS (MDDI_MAX_NUM_LLIST_ITEMS - \
+ MDDI_NUM_STATIC_LLIST_ITEMS)
+
+#define MDDI_FIRST_STATIC_LLIST_IDX MDDI_NUM_DYNAMIC_LLIST_ITEMS
+#define MDDI_FIRST_STATIC_ABL_IDX MDDI_FIRST_STATIC_LLIST_IDX
+#define MDDI_FIRST_STATIC_WINDOW_IDX (MDDI_FIRST_STATIC_LLIST_IDX + \
+ MDDI_NUM_STATIC_ABL_ITEMS)
+
+/* GPIO registers */
+#define VSYNC_WAKEUP_REG 0x80
+#define GPIO_REG 0x81
+#define GPIO_OUTPUT_REG 0x82
+#define GPIO_INTERRUPT_REG 0x83
+#define GPIO_INTERRUPT_ENABLE_REG 0x84
+#define GPIO_POLARITY_REG 0x85
+
+/* Interrupt Bits */
+#define MDDI_INT_PRI_PTR_READ 0x0001
+#define MDDI_INT_SEC_PTR_READ 0x0002
+#define MDDI_INT_REV_DATA_AVAIL 0x0004
+#define MDDI_INT_DISP_REQ 0x0008
+#define MDDI_INT_PRI_UNDERFLOW 0x0010
+#define MDDI_INT_SEC_UNDERFLOW 0x0020
+#define MDDI_INT_REV_OVERFLOW 0x0040
+#define MDDI_INT_CRC_ERROR 0x0080
+#define MDDI_INT_MDDI_IN 0x0100
+#define MDDI_INT_PRI_OVERWRITE 0x0200
+#define MDDI_INT_SEC_OVERWRITE 0x0400
+#define MDDI_INT_REV_OVERWRITE 0x0800
+#define MDDI_INT_DMA_FAILURE 0x1000
+#define MDDI_INT_LINK_ACTIVE 0x2000
+#define MDDI_INT_IN_HIBERNATION 0x4000
+#define MDDI_INT_PRI_LINK_LIST_DONE 0x8000
+#define MDDI_INT_SEC_LINK_LIST_DONE 0x10000
+#define MDDI_INT_NO_CMD_PKTS_PEND 0x20000
+#define MDDI_INT_RTD_FAILURE 0x40000
+
+#define MDDI_INT_ERROR_CONDITIONS ( \
+ MDDI_INT_PRI_UNDERFLOW | MDDI_INT_SEC_UNDERFLOW | \
+ MDDI_INT_REV_OVERFLOW | MDDI_INT_CRC_ERROR | \
+ MDDI_INT_PRI_OVERWRITE | MDDI_INT_SEC_OVERWRITE | \
+ MDDI_INT_RTD_FAILURE | \
+ MDDI_INT_REV_OVERWRITE | MDDI_INT_DMA_FAILURE)
+
+#define MDDI_INT_LINK_STATE_CHANGES ( \
+ MDDI_INT_LINK_ACTIVE | MDDI_INT_IN_HIBERNATION)
+
+/* Status Bits */
+#define MDDI_STAT_LINK_ACTIVE 0x0001
+#define MDDI_STAT_NEW_REV_PTR 0x0002
+#define MDDI_STAT_NEW_PRI_PTR 0x0004
+#define MDDI_STAT_NEW_SEC_PTR 0x0008
+#define MDDI_STAT_IN_HIBERNATION 0x0010
+#define MDDI_STAT_PRI_LINK_LIST_DONE 0x0020
+#define MDDI_STAT_SEC_LINK_LIST_DONE 0x0040
+#define MDDI_STAT_PENDING_TIMING_PKT 0x0080
+#define MDDI_STAT_PENDING_REV_ENCAP 0x0100
+#define MDDI_STAT_PENDING_POWERDOWN 0x0200
+#define MDDI_STAT_RTD_MEAS_FAIL 0x0800
+#define MDDI_STAT_CLIENT_WAKEUP_REQ 0x1000
+
+/* Command Bits */
+#define MDDI_CMD_POWERDOWN 0x0100
+#define MDDI_CMD_POWERUP 0x0200
+#define MDDI_CMD_HIBERNATE 0x0300
+#define MDDI_CMD_RESET 0x0400
+#define MDDI_CMD_DISP_IGNORE 0x0501
+#define MDDI_CMD_DISP_LISTEN 0x0500
+#define MDDI_CMD_SEND_REV_ENCAP 0x0600
+#define MDDI_CMD_GET_CLIENT_CAP 0x0601
+#define MDDI_CMD_GET_CLIENT_STATUS 0x0602
+#define MDDI_CMD_SEND_RTD 0x0700
+#define MDDI_CMD_LINK_ACTIVE 0x0900
+#define MDDI_CMD_PERIODIC_REV_ENCAP 0x0A00
+
+extern void mddi_host_init(mddi_host_type host);
+extern void mddi_host_powerdown(mddi_host_type host);
+extern uint16 mddi_get_next_free_llist_item(mddi_host_type host, boolean wait);
+extern uint16 mddi_get_reg_read_llist_item(mddi_host_type host, boolean wait);
+extern void mddi_queue_forward_packets(uint16 first_llist_idx,
+ uint16 last_llist_idx,
+ boolean wait,
+ mddi_llist_done_cb_type llist_done_cb,
+ mddi_host_type host);
+
+extern void mddi_host_write_pix_attr_reg(uint32 value);
+extern void mddi_client_lcd_gpio_poll(uint32 poll_reg_val);
+extern void mddi_client_lcd_vsync_detected(boolean detected);
+extern void mddi_host_disable_hibernation(boolean disable);
+
+extern mddi_linked_list_type *llist_extern[];
+extern mddi_linked_list_type *llist_dma_extern[];
+extern mddi_linked_list_notify_type *llist_extern_notify[];
+extern struct timer_list mddi_host_timer;
+
+typedef struct {
+ uint16 transmitting_start_idx;
+ uint16 transmitting_end_idx;
+ uint16 waiting_start_idx;
+ uint16 waiting_end_idx;
+ uint16 reg_read_idx;
+ uint16 next_free_idx;
+ boolean reg_read_waiting;
+} mddi_llist_info_type;
+
+extern mddi_llist_info_type mddi_llist;
+
+#define MDDI_GPIO_DEFAULT_POLLING_INTERVAL 200
+typedef struct {
+ uint32 polling_reg;
+ uint32 polling_val;
+ uint32 polling_interval;
+ boolean polling_enabled;
+} mddi_gpio_info_type;
+
+uint32 mddi_get_client_id(void);
+void mddi_mhctl_remove(mddi_host_type host_idx);
+void mddi_host_timer_service(unsigned long data);
+#endif /* MDDIHOSTI_H */
diff --git a/drivers/staging/msm/mdp.c b/drivers/staging/msm/mdp.c
new file mode 100644
index 0000000..36053af
--- /dev/null
+++ b/drivers/staging/msm/mdp.c
@@ -0,0 +1,1113 @@
+/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
+#include <linux/clk.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#ifdef CONFIG_FB_MSM_MDP40
+#include "mdp4.h"
+#endif
+
+static struct clk *mdp_clk;
+static struct clk *mdp_pclk;
+
+struct completion mdp_ppp_comp;
+struct semaphore mdp_ppp_mutex;
+struct semaphore mdp_pipe_ctrl_mutex;
+
+unsigned long mdp_timer_duration = (HZ); /* 1 sec */
+/* unsigned long mdp_mdp_timer_duration=0; */
+
+boolean mdp_ppp_waiting = FALSE;
+uint32 mdp_tv_underflow_cnt;
+uint32 mdp_lcdc_underflow_cnt;
+
+boolean mdp_current_clk_on = FALSE;
+boolean mdp_is_in_isr = FALSE;
+
+/*
+ * legacy mdp_in_processing is only for DMA2-MDDI
+ * this applies to DMA2 block only
+ */
+uint32 mdp_in_processing = FALSE;
+
+#ifdef CONFIG_FB_MSM_MDP40
+uint32 mdp_intr_mask = MDP4_ANY_INTR_MASK;
+#else
+uint32 mdp_intr_mask = MDP_ANY_INTR_MASK;
+#endif
+
+MDP_BLOCK_TYPE mdp_debug[MDP_MAX_BLOCK];
+
+int32 mdp_block_power_cnt[MDP_MAX_BLOCK];
+
+spinlock_t mdp_spin_lock;
+struct workqueue_struct *mdp_dma_wq; /*mdp dma wq */
+struct workqueue_struct *mdp_vsync_wq; /*mdp vsync wq */
+
+static struct workqueue_struct *mdp_pipe_ctrl_wq; /* mdp mdp pipe ctrl wq */
+static struct delayed_work mdp_pipe_ctrl_worker;
+
+#ifdef CONFIG_FB_MSM_MDP40
+struct mdp_dma_data dma2_data;
+struct mdp_dma_data dma_s_data;
+struct mdp_dma_data dma_e_data;
+#else
+static struct mdp_dma_data dma2_data;
+static struct mdp_dma_data dma_s_data;
+static struct mdp_dma_data dma_e_data;
+#endif
+static struct mdp_dma_data dma3_data;
+
+extern ktime_t mdp_dma2_last_update_time;
+
+extern uint32 mdp_dma2_update_time_in_usec;
+extern int mdp_lcd_rd_cnt_offset_slow;
+extern int mdp_lcd_rd_cnt_offset_fast;
+extern int mdp_usec_diff_threshold;
+
+#ifdef CONFIG_FB_MSM_LCDC
+extern int mdp_lcdc_pclk_clk_rate;
+extern int mdp_lcdc_pad_pclk_clk_rate;
+extern int first_pixel_start_x;
+extern int first_pixel_start_y;
+#endif
+
+#ifdef MSM_FB_ENABLE_DBGFS
+struct dentry *mdp_dir;
+#endif
+
+#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
+static int mdp_suspend(struct platform_device *pdev, pm_message_t state);
+#else
+#define mdp_suspend NULL
+#endif
+
+struct timeval mdp_dma2_timeval;
+struct timeval mdp_ppp_timeval;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static struct early_suspend early_suspend;
+#endif
+
+#ifndef CONFIG_FB_MSM_MDP22
+DEFINE_MUTEX(mdp_lut_push_sem);
+static int mdp_lut_i;
+static int mdp_lut_hw_update(struct fb_cmap *cmap)
+{
+ int i;
+ u16 *c[3];
+ u16 r, g, b;
+
+ c[0] = cmap->green;
+ c[1] = cmap->blue;
+ c[2] = cmap->red;
+
+ for (i = 0; i < cmap->len; i++) {
+ if (copy_from_user(&r, cmap->red++, sizeof(r)) ||
+ copy_from_user(&g, cmap->green++, sizeof(g)) ||
+ copy_from_user(&b, cmap->blue++, sizeof(b)))
+ return -EFAULT;
+
+#ifdef CONFIG_FB_MSM_MDP40
+ MDP_OUTP(MDP_BASE + 0x94800 +
+#else
+ MDP_OUTP(MDP_BASE + 0x93800 +
+#endif
+ (0x400*mdp_lut_i) + cmap->start*4 + i*4,
+ ((g & 0xff) |
+ ((b & 0xff) << 8) |
+ ((r & 0xff) << 16)));
+ }
+
+ return 0;
+}
+
+static int mdp_lut_push;
+static int mdp_lut_push_i;
+static int mdp_lut_update_nonlcdc(struct fb_info *info, struct fb_cmap *cmap)
+{
+ int ret;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ ret = mdp_lut_hw_update(cmap);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ if (ret)
+ return ret;
+
+ mutex_lock(&mdp_lut_push_sem);
+ mdp_lut_push = 1;
+ mdp_lut_push_i = mdp_lut_i;
+ mutex_unlock(&mdp_lut_push_sem);
+
+ mdp_lut_i = (mdp_lut_i + 1)%2;
+
+ return 0;
+}
+
+static int mdp_lut_update_lcdc(struct fb_info *info, struct fb_cmap *cmap)
+{
+ int ret;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ ret = mdp_lut_hw_update(cmap);
+
+ if (ret) {
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ return ret;
+ }
+
+ MDP_OUTP(MDP_BASE + 0x90070, (mdp_lut_i << 10) | 0x17);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ mdp_lut_i = (mdp_lut_i + 1)%2;
+
+ return 0;
+}
+
+#define MDP_HIST_MAX_BIN 32
+static __u32 mdp_hist_r[MDP_HIST_MAX_BIN];
+static __u32 mdp_hist_g[MDP_HIST_MAX_BIN];
+static __u32 mdp_hist_b[MDP_HIST_MAX_BIN];
+
+#ifdef CONFIG_FB_MSM_MDP40
+struct mdp_histogram mdp_hist;
+struct completion mdp_hist_comp;
+#else
+static struct mdp_histogram mdp_hist;
+static struct completion mdp_hist_comp;
+#endif
+
+static int mdp_do_histogram(struct fb_info *info, struct mdp_histogram *hist)
+{
+ int ret = 0;
+
+ if (!hist->frame_cnt || (hist->bin_cnt == 0) ||
+ (hist->bin_cnt > MDP_HIST_MAX_BIN))
+ return -EINVAL;
+
+ INIT_COMPLETION(mdp_hist_comp);
+
+ mdp_hist.bin_cnt = hist->bin_cnt;
+ mdp_hist.r = (hist->r) ? mdp_hist_r : 0;
+ mdp_hist.g = (hist->g) ? mdp_hist_g : 0;
+ mdp_hist.b = (hist->b) ? mdp_hist_b : 0;
+
+#ifdef CONFIG_FB_MSM_MDP40
+ MDP_OUTP(MDP_BASE + 0x95004, hist->frame_cnt);
+ MDP_OUTP(MDP_BASE + 0x95000, 1);
+#else
+ MDP_OUTP(MDP_BASE + 0x94004, hist->frame_cnt);
+ MDP_OUTP(MDP_BASE + 0x94000, 1);
+#endif
+ wait_for_completion_killable(&mdp_hist_comp);
+
+ if (hist->r) {
+ ret = copy_to_user(hist->r, mdp_hist.r, hist->bin_cnt*4);
+ if (ret)
+ goto hist_err;
+ }
+ if (hist->g) {
+ ret = copy_to_user(hist->g, mdp_hist.g, hist->bin_cnt*4);
+ if (ret)
+ goto hist_err;
+ }
+ if (hist->b) {
+ ret = copy_to_user(hist->b, mdp_hist.b, hist->bin_cnt*4);
+ if (ret)
+ goto hist_err;
+ }
+ return 0;
+
+hist_err:
+ printk(KERN_ERR "%s: invalid hist buffer\n", __func__);
+ return ret;
+}
+#endif
+
+/* Returns < 0 on error, 0 on timeout, or > 0 on successful wait */
+
+int mdp_ppp_pipe_wait(void)
+{
+ int ret = 1;
+
+ /* wait 5 seconds for the operation to complete before declaring
+ the MDP hung */
+
+ if (mdp_ppp_waiting == TRUE) {
+ ret = wait_for_completion_interruptible_timeout(&mdp_ppp_comp,
+ 5 * HZ);
+
+ if (!ret)
+ printk(KERN_ERR "%s: Timed out waiting for the MDP.\n",
+ __func__);
+ }
+
+ return ret;
+}
+
+static DEFINE_SPINLOCK(mdp_lock);
+static int mdp_irq_mask;
+static int mdp_irq_enabled;
+
+void mdp_enable_irq(uint32 term)
+{
+ unsigned long irq_flags;
+
+ spin_lock_irqsave(&mdp_lock, irq_flags);
+ if (mdp_irq_mask & term) {
+ printk(KERN_ERR "MDP IRQ term-0x%x is already set\n", term);
+ } else {
+ mdp_irq_mask |= term;
+ if (mdp_irq_mask && !mdp_irq_enabled) {
+ mdp_irq_enabled = 1;
+ enable_irq(INT_MDP);
+ }
+ }
+ spin_unlock_irqrestore(&mdp_lock, irq_flags);
+}
+
+void mdp_disable_irq(uint32 term)
+{
+ unsigned long irq_flags;
+
+ spin_lock_irqsave(&mdp_lock, irq_flags);
+ if (!(mdp_irq_mask & term)) {
+ printk(KERN_ERR "MDP IRQ term-0x%x is not set\n", term);
+ } else {
+ mdp_irq_mask &= ~term;
+ if (!mdp_irq_mask && mdp_irq_enabled) {
+ mdp_irq_enabled = 0;
+ disable_irq(INT_MDP);
+ }
+ }
+ spin_unlock_irqrestore(&mdp_lock, irq_flags);
+}
+
+void mdp_disable_irq_nolock(uint32 term)
+{
+
+ if (!(mdp_irq_mask & term)) {
+ printk(KERN_ERR "MDP IRQ term-0x%x is not set\n", term);
+ } else {
+ mdp_irq_mask &= ~term;
+ if (!mdp_irq_mask && mdp_irq_enabled) {
+ mdp_irq_enabled = 0;
+ disable_irq(INT_MDP);
+ }
+ }
+}
+
+void mdp_pipe_kickoff(uint32 term, struct msm_fb_data_type *mfd)
+{
+
+ dmb(); /* memory barrier */
+
+ /* kick off PPP engine */
+ if (term == MDP_PPP_TERM) {
+ if (mdp_debug[MDP_PPP_BLOCK])
+ jiffies_to_timeval(jiffies, &mdp_ppp_timeval);
+
+ /* let's turn on PPP block */
+ mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ mdp_enable_irq(term);
+ INIT_COMPLETION(mdp_ppp_comp);
+ mdp_ppp_waiting = TRUE;
+ outpdw(MDP_BASE + 0x30, 0x1000);
+ wait_for_completion_killable(&mdp_ppp_comp);
+ mdp_disable_irq(term);
+
+ if (mdp_debug[MDP_PPP_BLOCK]) {
+ struct timeval now;
+
+ jiffies_to_timeval(jiffies, &now);
+ mdp_ppp_timeval.tv_usec =
+ now.tv_usec - mdp_ppp_timeval.tv_usec;
+ MSM_FB_INFO("MDP-PPP: %d\n",
+ (int)mdp_ppp_timeval.tv_usec);
+ }
+ } else if (term == MDP_DMA2_TERM) {
+ if (mdp_debug[MDP_DMA2_BLOCK]) {
+ MSM_FB_INFO("MDP-DMA2: %d\n",
+ (int)mdp_dma2_timeval.tv_usec);
+ jiffies_to_timeval(jiffies, &mdp_dma2_timeval);
+ }
+ /* DMA update timestamp */
+ mdp_dma2_last_update_time = ktime_get_real();
+ /* let's turn on DMA2 block */
+#if 0
+ mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+#endif
+#ifdef CONFIG_FB_MSM_MDP22
+ outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x0044, 0x0);/* start DMA */
+#else
+ if (mdp_lut_push) {
+ mutex_lock(&mdp_lut_push_sem);
+ mdp_lut_push = 0;
+ MDP_OUTP(MDP_BASE + 0x90070,
+ (mdp_lut_push_i << 10) | 0x17);
+ mutex_unlock(&mdp_lut_push_sem);
+ }
+#ifdef CONFIG_FB_MSM_MDP40
+ outpdw(MDP_BASE + 0x000c, 0x0); /* start DMA */
+#else
+ outpdw(MDP_BASE + 0x0044, 0x0); /* start DMA */
+#endif
+#endif
+#ifdef CONFIG_FB_MSM_MDP40
+ } else if (term == MDP_DMA_S_TERM) {
+ mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ outpdw(MDP_BASE + 0x0010, 0x0); /* start DMA */
+ } else if (term == MDP_DMA_E_TERM) {
+ mdp_pipe_ctrl(MDP_DMA_E_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ outpdw(MDP_BASE + 0x0014, 0x0); /* start DMA */
+ } else if (term == MDP_OVERLAY0_TERM) {
+ mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ outpdw(MDP_BASE + 0x0004, 0);
+ } else if (term == MDP_OVERLAY1_TERM) {
+ mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ outpdw(MDP_BASE + 0x0008, 0);
+ }
+#else
+ } else if (term == MDP_DMA_S_TERM) {
+ mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ outpdw(MDP_BASE + 0x0048, 0x0); /* start DMA */
+ }
+#endif
+}
+
+static void mdp_pipe_ctrl_workqueue_handler(struct work_struct *work)
+{
+ mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
+ boolean isr)
+{
+ boolean mdp_all_blocks_off = TRUE;
+ int i;
+ unsigned long flag;
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ if (MDP_BLOCK_POWER_ON == state) {
+ mdp_block_power_cnt[block]++;
+
+ if (MDP_DMA2_BLOCK == block)
+ mdp_in_processing = TRUE;
+ } else {
+ mdp_block_power_cnt[block]--;
+
+ if (mdp_block_power_cnt[block] < 0) {
+ /*
+ * Master has to serve a request to power off MDP always
+ * It also has a timer to power off. So, in case of
+ * timer expires first and DMA2 finishes later,
+ * master has to power off two times
+ * There shouldn't be multiple power-off request for
+ * other blocks
+ */
+ if (block != MDP_MASTER_BLOCK) {
+ MSM_FB_INFO("mdp_block_power_cnt[block=%d] \
+ multiple power-off request\n", block);
+ }
+ mdp_block_power_cnt[block] = 0;
+ }
+
+ if (MDP_DMA2_BLOCK == block)
+ mdp_in_processing = FALSE;
+ }
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+ /*
+ * If it's in isr, we send our request to workqueue.
+ * Otherwise, processing happens in the current context
+ */
+ if (isr) {
+ /* checking all blocks power state */
+ for (i = 0; i < MDP_MAX_BLOCK; i++) {
+ if (mdp_block_power_cnt[i] > 0)
+ mdp_all_blocks_off = FALSE;
+ }
+
+ if ((mdp_all_blocks_off) && (mdp_current_clk_on)) {
+ /* send workqueue to turn off mdp power */
+ queue_delayed_work(mdp_pipe_ctrl_wq,
+ &mdp_pipe_ctrl_worker,
+ mdp_timer_duration);
+ }
+ } else {
+ down(&mdp_pipe_ctrl_mutex);
+ /* checking all blocks power state */
+ for (i = 0; i < MDP_MAX_BLOCK; i++) {
+ if (mdp_block_power_cnt[i] > 0)
+ mdp_all_blocks_off = FALSE;
+ }
+
+ /*
+ * find out whether a delayable work item is currently
+ * pending
+ */
+
+ if (delayed_work_pending(&mdp_pipe_ctrl_worker)) {
+ /*
+ * try to cancel the current work if it fails to
+ * stop (which means del_timer can't delete it
+ * from the list, it's about to expire and run),
+ * we have to let it run. queue_delayed_work won't
+ * accept the next job which is same as
+ * queue_delayed_work(mdp_timer_duration = 0)
+ */
+ cancel_delayed_work(&mdp_pipe_ctrl_worker);
+ }
+
+ if ((mdp_all_blocks_off) && (mdp_current_clk_on)) {
+ if (block == MDP_MASTER_BLOCK) {
+ mdp_current_clk_on = FALSE;
+ /* turn off MDP clks */
+ if (mdp_clk != NULL) {
+ clk_disable(mdp_clk);
+ MSM_FB_DEBUG("MDP CLK OFF\n");
+ }
+ if (mdp_pclk != NULL) {
+ clk_disable(mdp_pclk);
+ MSM_FB_DEBUG("MDP PCLK OFF\n");
+ }
+ } else {
+ /* send workqueue to turn off mdp power */
+ queue_delayed_work(mdp_pipe_ctrl_wq,
+ &mdp_pipe_ctrl_worker,
+ mdp_timer_duration);
+ }
+ } else if ((!mdp_all_blocks_off) && (!mdp_current_clk_on)) {
+ mdp_current_clk_on = TRUE;
+ /* turn on MDP clks */
+ if (mdp_clk != NULL) {
+ clk_enable(mdp_clk);
+ MSM_FB_DEBUG("MDP CLK ON\n");
+ }
+ if (mdp_pclk != NULL) {
+ clk_enable(mdp_pclk);
+ MSM_FB_DEBUG("MDP PCLK ON\n");
+ }
+ }
+ up(&mdp_pipe_ctrl_mutex);
+ }
+}
+
+#ifndef CONFIG_FB_MSM_MDP40
+irqreturn_t mdp_isr(int irq, void *ptr)
+{
+ uint32 mdp_interrupt = 0;
+ struct mdp_dma_data *dma;
+
+ mdp_is_in_isr = TRUE;
+ do {
+ mdp_interrupt = inp32(MDP_INTR_STATUS);
+ outp32(MDP_INTR_CLEAR, mdp_interrupt);
+
+ mdp_interrupt &= mdp_intr_mask;
+
+ if (mdp_interrupt & TV_ENC_UNDERRUN) {
+ mdp_interrupt &= ~(TV_ENC_UNDERRUN);
+ mdp_tv_underflow_cnt++;
+ }
+
+ if (!mdp_interrupt)
+ break;
+
+ /* DMA3 TV-Out Start */
+ if (mdp_interrupt & TV_OUT_DMA3_START) {
+ /* let's disable TV out interrupt */
+ mdp_intr_mask &= ~TV_OUT_DMA3_START;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+
+ dma = &dma3_data;
+ if (dma->waiting) {
+ dma->waiting = FALSE;
+ complete(&dma->comp);
+ }
+ }
+#ifndef CONFIG_FB_MSM_MDP22
+ if (mdp_interrupt & MDP_HIST_DONE) {
+ outp32(MDP_BASE + 0x94018, 0x3);
+ outp32(MDP_INTR_CLEAR, MDP_HIST_DONE);
+ if (mdp_hist.r)
+ memcpy(mdp_hist.r, MDP_BASE + 0x94100,
+ mdp_hist.bin_cnt*4);
+ if (mdp_hist.g)
+ memcpy(mdp_hist.g, MDP_BASE + 0x94200,
+ mdp_hist.bin_cnt*4);
+ if (mdp_hist.b)
+ memcpy(mdp_hist.b, MDP_BASE + 0x94300,
+ mdp_hist.bin_cnt*4);
+ complete(&mdp_hist_comp);
+ }
+
+ /* LCDC UnderFlow */
+ if (mdp_interrupt & LCDC_UNDERFLOW) {
+ mdp_lcdc_underflow_cnt++;
+ }
+ /* LCDC Frame Start */
+ if (mdp_interrupt & LCDC_FRAME_START) {
+ /* let's disable LCDC interrupt */
+ mdp_intr_mask &= ~LCDC_FRAME_START;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+
+ dma = &dma2_data;
+ if (dma->waiting) {
+ dma->waiting = FALSE;
+ complete(&dma->comp);
+ }
+ }
+
+ /* DMA2 LCD-Out Complete */
+ if (mdp_interrupt & MDP_DMA_S_DONE) {
+ dma = &dma_s_data;
+ dma->busy = FALSE;
+ mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_OFF,
+ TRUE);
+ complete(&dma->comp);
+ }
+#endif
+
+ /* DMA2 LCD-Out Complete */
+ if (mdp_interrupt & MDP_DMA_P_DONE) {
+ struct timeval now;
+ ktime_t now_k;
+
+ now_k = ktime_get_real();
+ mdp_dma2_last_update_time.tv.sec =
+ now_k.tv.sec - mdp_dma2_last_update_time.tv.sec;
+ mdp_dma2_last_update_time.tv.nsec =
+ now_k.tv.nsec - mdp_dma2_last_update_time.tv.nsec;
+
+ if (mdp_debug[MDP_DMA2_BLOCK]) {
+ jiffies_to_timeval(jiffies, &now);
+ mdp_dma2_timeval.tv_usec =
+ now.tv_usec - mdp_dma2_timeval.tv_usec;
+ }
+
+ dma = &dma2_data;
+ dma->busy = FALSE;
+ mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF,
+ TRUE);
+ complete(&dma->comp);
+ }
+ /* PPP Complete */
+ if (mdp_interrupt & MDP_PPP_DONE) {
+#ifdef CONFIG_MDP_PPP_ASYNC_OP
+ mdp_ppp_djob_done();
+#else
+ mdp_pipe_ctrl(MDP_PPP_BLOCK,
+ MDP_BLOCK_POWER_OFF, TRUE);
+ if (mdp_ppp_waiting) {
+ mdp_ppp_waiting = FALSE;
+ complete(&mdp_ppp_comp);
+ }
+#endif
+ }
+ } while (1);
+
+ mdp_is_in_isr = FALSE;
+
+ return IRQ_HANDLED;
+}
+#endif
+
+static void mdp_drv_init(void)
+{
+ int i;
+
+ for (i = 0; i < MDP_MAX_BLOCK; i++) {
+ mdp_debug[i] = 0;
+ }
+
+ /* initialize spin lock and workqueue */
+ spin_lock_init(&mdp_spin_lock);
+ mdp_dma_wq = create_singlethread_workqueue("mdp_dma_wq");
+ mdp_vsync_wq = create_singlethread_workqueue("mdp_vsync_wq");
+ mdp_pipe_ctrl_wq = create_singlethread_workqueue("mdp_pipe_ctrl_wq");
+ INIT_DELAYED_WORK(&mdp_pipe_ctrl_worker,
+ mdp_pipe_ctrl_workqueue_handler);
+#ifdef CONFIG_MDP_PPP_ASYNC_OP
+ mdp_ppp_dq_init();
+#endif
+
+ /* initialize semaphore */
+ init_completion(&mdp_ppp_comp);
+ init_MUTEX(&mdp_ppp_mutex);
+ init_MUTEX(&mdp_pipe_ctrl_mutex);
+
+ dma2_data.busy = FALSE;
+ dma2_data.waiting = FALSE;
+ init_completion(&dma2_data.comp);
+ init_MUTEX(&dma2_data.mutex);
+ mutex_init(&dma2_data.ov_mutex);
+
+ dma3_data.busy = FALSE;
+ dma3_data.waiting = FALSE;
+ init_completion(&dma3_data.comp);
+ init_MUTEX(&dma3_data.mutex);
+
+ dma_s_data.busy = FALSE;
+ dma_s_data.waiting = FALSE;
+ init_completion(&dma_s_data.comp);
+ init_MUTEX(&dma_s_data.mutex);
+
+ dma_e_data.busy = FALSE;
+ dma_e_data.waiting = FALSE;
+ init_completion(&dma_e_data.comp);
+
+#ifndef CONFIG_FB_MSM_MDP22
+ init_completion(&mdp_hist_comp);
+#endif
+
+ /* initializing mdp power block counter to 0 */
+ for (i = 0; i < MDP_MAX_BLOCK; i++) {
+ mdp_block_power_cnt[i] = 0;
+ }
+
+#ifdef MSM_FB_ENABLE_DBGFS
+ {
+ struct dentry *root;
+ char sub_name[] = "mdp";
+
+ root = msm_fb_get_debugfs_root();
+ if (root != NULL) {
+ mdp_dir = debugfs_create_dir(sub_name, root);
+
+ if (mdp_dir) {
+ msm_fb_debugfs_file_create(mdp_dir,
+ "dma2_update_time_in_usec",
+ (u32 *) &mdp_dma2_update_time_in_usec);
+ msm_fb_debugfs_file_create(mdp_dir,
+ "vs_rdcnt_slow",
+ (u32 *) &mdp_lcd_rd_cnt_offset_slow);
+ msm_fb_debugfs_file_create(mdp_dir,
+ "vs_rdcnt_fast",
+ (u32 *) &mdp_lcd_rd_cnt_offset_fast);
+ msm_fb_debugfs_file_create(mdp_dir,
+ "mdp_usec_diff_threshold",
+ (u32 *) &mdp_usec_diff_threshold);
+ msm_fb_debugfs_file_create(mdp_dir,
+ "mdp_current_clk_on",
+ (u32 *) &mdp_current_clk_on);
+#ifdef CONFIG_FB_MSM_LCDC
+ msm_fb_debugfs_file_create(mdp_dir,
+ "lcdc_start_x",
+ (u32 *) &first_pixel_start_x);
+ msm_fb_debugfs_file_create(mdp_dir,
+ "lcdc_start_y",
+ (u32 *) &first_pixel_start_y);
+ msm_fb_debugfs_file_create(mdp_dir,
+ "mdp_lcdc_pclk_clk_rate",
+ (u32 *) &mdp_lcdc_pclk_clk_rate);
+ msm_fb_debugfs_file_create(mdp_dir,
+ "mdp_lcdc_pad_pclk_clk_rate",
+ (u32 *) &mdp_lcdc_pad_pclk_clk_rate);
+#endif
+ }
+ }
+ }
+#endif
+}
+
+static int mdp_probe(struct platform_device *pdev);
+static int mdp_remove(struct platform_device *pdev);
+
+static struct platform_driver mdp_driver = {
+ .probe = mdp_probe,
+ .remove = mdp_remove,
+#ifndef CONFIG_HAS_EARLYSUSPEND
+ .suspend = mdp_suspend,
+ .resume = NULL,
+#endif
+ .shutdown = NULL,
+ .driver = {
+ /*
+ * Driver name must match the device name added in
+ * platform.c.
+ */
+ .name = "mdp",
+ },
+};
+
+static int mdp_off(struct platform_device *pdev)
+{
+ int ret = 0;
+
+#ifdef MDP_HW_VSYNC
+ struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
+#endif
+
+ ret = panel_next_off(pdev);
+
+#ifdef MDP_HW_VSYNC
+ mdp_hw_vsync_clk_disable(mfd);
+#endif
+
+ return ret;
+}
+
+static int mdp_on(struct platform_device *pdev)
+{
+#ifdef MDP_HW_VSYNC
+ struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
+#endif
+
+ int ret = 0;
+
+#ifdef MDP_HW_VSYNC
+ mdp_hw_vsync_clk_enable(mfd);
+#endif
+
+ ret = panel_next_on(pdev);
+
+ return ret;
+}
+
+static int mdp_irq_clk_setup(void)
+{
+ int ret;
+
+#ifdef CONFIG_FB_MSM_MDP40
+ ret = request_irq(INT_MDP, mdp4_isr, IRQF_DISABLED, "MDP", 0);
+#else
+ ret = request_irq(INT_MDP, mdp_isr, IRQF_DISABLED, "MDP", 0);
+#endif
+ if (ret) {
+ printk(KERN_ERR "mdp request_irq() failed!\n");
+ return ret;
+ }
+ disable_irq(INT_MDP);
+
+ mdp_clk = clk_get(NULL, "mdp_clk");
+
+ if (IS_ERR(mdp_clk)) {
+ ret = PTR_ERR(mdp_clk);
+ printk(KERN_ERR "can't get mdp_clk error:%d!\n", ret);
+ free_irq(INT_MDP, 0);
+ return ret;
+ }
+
+ mdp_pclk = clk_get(NULL, "mdp_pclk");
+ if (IS_ERR(mdp_pclk))
+ mdp_pclk = NULL;
+
+
+#ifdef CONFIG_FB_MSM_MDP40
+ /*
+ * mdp_clk should greater than mdp_pclk always
+ */
+ clk_set_rate(mdp_clk, 122880000); /* 122.88 Mhz */
+ printk(KERN_INFO "mdp_clk: mdp_clk=%d mdp_pclk=%d\n",
+ (int)clk_get_rate(mdp_clk), (int)clk_get_rate(mdp_pclk));
+#endif
+
+ return 0;
+}
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+static int mdp_resource_initialized;
+static struct msm_panel_common_pdata *mdp_pdata;
+
+static int mdp_probe(struct platform_device *pdev)
+{
+ struct platform_device *msm_fb_dev = NULL;
+ struct msm_fb_data_type *mfd;
+ struct msm_fb_panel_data *pdata = NULL;
+ int rc;
+ resource_size_t size ;
+#ifdef CONFIG_FB_MSM_MDP40
+ int intf, if_no;
+#else
+ unsigned long flag;
+#endif
+
+ if ((pdev->id == 0) && (pdev->num_resources > 0)) {
+ mdp_pdata = pdev->dev.platform_data;
+
+ size = resource_size(&pdev->resource[0]);
+ msm_mdp_base = ioremap(pdev->resource[0].start, size);
+
+ MSM_FB_INFO("MDP HW Base phy_Address = 0x%x virt = 0x%x\n",
+ (int)pdev->resource[0].start, (int)msm_mdp_base);
+
+ if (unlikely(!msm_mdp_base))
+ return -ENOMEM;
+
+ printk("irq clk setup\n");
+ rc = mdp_irq_clk_setup();
+ printk("irq clk setup done\n");
+ if (rc)
+ return rc;
+
+ /* initializing mdp hw */
+#ifdef CONFIG_FB_MSM_MDP40
+ mdp4_hw_init();
+#else
+ mdp_hw_init();
+#endif
+
+ mdp_resource_initialized = 1;
+ return 0;
+ }
+
+ if (!mdp_resource_initialized)
+ return -EPERM;
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+ return -ENOMEM;
+
+ msm_fb_dev = platform_device_alloc("msm_fb", pdev->id);
+ if (!msm_fb_dev)
+ return -ENOMEM;
+
+ /* link to the latest pdev */
+ mfd->pdev = msm_fb_dev;
+
+ /* add panel data */
+ if (platform_device_add_data
+ (msm_fb_dev, pdev->dev.platform_data,
+ sizeof(struct msm_fb_panel_data))) {
+ printk(KERN_ERR "mdp_probe: platform_device_add_data failed!\n");
+ rc = -ENOMEM;
+ goto mdp_probe_err;
+ }
+ /* data chain */
+ pdata = msm_fb_dev->dev.platform_data;
+ pdata->on = mdp_on;
+ pdata->off = mdp_off;
+ pdata->next = pdev;
+
+ switch (mfd->panel.type) {
+ case EXT_MDDI_PANEL:
+ case MDDI_PANEL:
+ case EBI2_PANEL:
+ INIT_WORK(&mfd->dma_update_worker,
+ mdp_lcd_update_workqueue_handler);
+ INIT_WORK(&mfd->vsync_resync_worker,
+ mdp_vsync_resync_workqueue_handler);
+ mfd->hw_refresh = FALSE;
+
+ if (mfd->panel.type == EXT_MDDI_PANEL) {
+ /* 15 fps -> 66 msec */
+ mfd->refresh_timer_duration = (66 * HZ / 1000);
+ } else {
+ /* 24 fps -> 42 msec */
+ mfd->refresh_timer_duration = (42 * HZ / 1000);
+ }
+
+#ifdef CONFIG_FB_MSM_MDP22
+ mfd->dma_fnc = mdp_dma2_update;
+ mfd->dma = &dma2_data;
+#else
+ if (mfd->panel_info.pdest == DISPLAY_1) {
+#ifdef CONFIG_FB_MSM_OVERLAY
+ mfd->dma_fnc = mdp4_mddi_overlay;
+#else
+ mfd->dma_fnc = mdp_dma2_update;
+#endif
+ mfd->dma = &dma2_data;
+ mfd->lut_update = mdp_lut_update_nonlcdc;
+ mfd->do_histogram = mdp_do_histogram;
+ } else {
+ mfd->dma_fnc = mdp_dma_s_update;
+ mfd->dma = &dma_s_data;
+ }
+#endif
+ if (mdp_pdata)
+ mfd->vsync_gpio = mdp_pdata->gpio;
+ else
+ mfd->vsync_gpio = -1;
+
+#ifdef CONFIG_FB_MSM_MDP40
+ if (mfd->panel.type == EBI2_PANEL)
+ intf = EBI2_INTF;
+ else
+ intf = MDDI_INTF;
+
+ if (mfd->panel_info.pdest == DISPLAY_1)
+ if_no = PRIMARY_INTF_SEL;
+ else
+ if_no = SECONDARY_INTF_SEL;
+
+ mdp4_display_intf_sel(if_no, intf);
+#endif
+ mdp_config_vsync(mfd);
+ break;
+
+ case HDMI_PANEL:
+ case LCDC_PANEL:
+ pdata->on = mdp_lcdc_on;
+ pdata->off = mdp_lcdc_off;
+ mfd->hw_refresh = TRUE;
+ mfd->cursor_update = mdp_hw_cursor_update;
+#ifndef CONFIG_FB_MSM_MDP22
+ mfd->lut_update = mdp_lut_update_lcdc;
+ mfd->do_histogram = mdp_do_histogram;
+#endif
+#ifdef CONFIG_FB_MSM_OVERLAY
+ mfd->dma_fnc = mdp4_lcdc_overlay;
+#else
+ mfd->dma_fnc = mdp_lcdc_update;
+#endif
+
+#ifdef CONFIG_FB_MSM_MDP40
+ if (mfd->panel.type == HDMI_PANEL) {
+ mfd->dma = &dma_e_data;
+ mdp4_display_intf_sel(EXTERNAL_INTF_SEL, LCDC_RGB_INTF);
+ } else {
+ mfd->dma = &dma2_data;
+ mdp4_display_intf_sel(PRIMARY_INTF_SEL, LCDC_RGB_INTF);
+ }
+#else
+ mfd->dma = &dma2_data;
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ mdp_intr_mask &= ~MDP_DMA_P_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+#endif
+ break;
+
+ case TV_PANEL:
+ pdata->on = mdp_dma3_on;
+ pdata->off = mdp_dma3_off;
+ mfd->hw_refresh = TRUE;
+ mfd->dma_fnc = mdp_dma3_update;
+ mfd->dma = &dma3_data;
+ break;
+
+ default:
+ printk(KERN_ERR "mdp_probe: unknown device type!\n");
+ rc = -ENODEV;
+ goto mdp_probe_err;
+ }
+
+ /* set driver data */
+ platform_set_drvdata(msm_fb_dev, mfd);
+
+ rc = platform_device_add(msm_fb_dev);
+ if (rc) {
+ goto mdp_probe_err;
+ }
+
+ pdev_list[pdev_list_cnt++] = pdev;
+ return 0;
+
+ mdp_probe_err:
+ platform_device_put(msm_fb_dev);
+ return rc;
+}
+
+static void mdp_suspend_sub(void)
+{
+ /* cancel pipe ctrl worker */
+ cancel_delayed_work(&mdp_pipe_ctrl_worker);
+
+ /* for workder can't be cancelled... */
+ flush_workqueue(mdp_pipe_ctrl_wq);
+
+ /* let's wait for PPP completion */
+ while (mdp_block_power_cnt[MDP_PPP_BLOCK] > 0) ;
+
+ /* try to power down */
+ mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
+static int mdp_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ mdp_suspend_sub();
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mdp_early_suspend(struct early_suspend *h)
+{
+ mdp_suspend_sub();
+}
+#endif
+
+static int mdp_remove(struct platform_device *pdev)
+{
+ iounmap(msm_mdp_base);
+ return 0;
+}
+
+static int mdp_register_driver(void)
+{
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1;
+ early_suspend.suspend = mdp_early_suspend;
+ register_early_suspend(&early_suspend);
+#endif
+
+ return platform_driver_register(&mdp_driver);
+}
+
+static int __init mdp_driver_init(void)
+{
+ int ret;
+
+ mdp_drv_init();
+
+ ret = mdp_register_driver();
+ if (ret) {
+ printk(KERN_ERR "mdp_register_driver() failed!\n");
+ return ret;
+ }
+
+#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_FB_MSM_MDP40)
+ mdp4_debugfs_init();
+#endif
+
+ return 0;
+
+}
+
+module_init(mdp_driver_init);
diff --git a/drivers/staging/msm/mdp.h b/drivers/staging/msm/mdp.h
new file mode 100644
index 0000000..0a5d6ac
--- /dev/null
+++ b/drivers/staging/msm/mdp.h
@@ -0,0 +1,695 @@
+/* Copyright (c) 2008-2010, Code Aurora Forum. 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 Code Aurora 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, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT 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 MDP_H
+#define MDP_H
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/hrtimer.h>
+#include "msm_mdp.h"
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+#include "msm_fb_panel.h"
+
+#ifdef CONFIG_MDP_PPP_ASYNC_OP
+#include "mdp_ppp_dq.h"
+#endif
+
+#ifdef BIT
+#undef BIT
+#endif
+
+#define BIT(x) (1<<(x))
+
+#define MDPOP_NOP 0
+#define MDPOP_LR BIT(0) /* left to right flip */
+#define MDPOP_UD BIT(1) /* up and down flip */
+#define MDPOP_ROT90 BIT(2) /* rotate image to 90 degree */
+#define MDPOP_ROT180 (MDPOP_UD|MDPOP_LR)
+#define MDPOP_ROT270 (MDPOP_ROT90|MDPOP_UD|MDPOP_LR)
+#define MDPOP_ASCALE BIT(7)
+#define MDPOP_ALPHAB BIT(8) /* enable alpha blending */
+#define MDPOP_TRANSP BIT(9) /* enable transparency */
+#define MDPOP_DITHER BIT(10) /* enable dither */
+#define MDPOP_SHARPENING BIT(11) /* enable sharpening */
+#define MDPOP_BLUR BIT(12) /* enable blur */
+#define MDPOP_FG_PM_ALPHA BIT(13)
+
+struct mdp_table_entry {
+ uint32_t reg;
+ uint32_t val;
+};
+
+extern struct mdp_ccs mdp_ccs_yuv2rgb ;
+extern struct mdp_ccs mdp_ccs_rgb2yuv ;
+
+/*
+ * MDP Image Structure
+ */
+typedef struct mdpImg_ {
+ uint32 imgType; /* Image type */
+ uint32 *bmy_addr; /* bitmap or y addr */
+ uint32 *cbcr_addr; /* cbcr addr */
+ uint32 width; /* image width */
+ uint32 mdpOp; /* image opertion (rotation,flip up/down, alpha/tp) */
+ uint32 tpVal; /* transparency color */
+ uint32 alpha; /* alpha percentage 0%(0x0) ~ 100%(0x100) */
+ int sp_value; /* sharpening strength */
+} MDPIMG;
+
+#ifdef CONFIG_MDP_PPP_ASYNC_OP
+#define MDP_OUTP(addr, data) mdp_ppp_outdw((uint32_t)(addr), \
+ (uint32_t)(data))
+#else
+#define MDP_OUTP(addr, data) outpdw((addr), (data))
+#endif
+
+#define MDP_KTIME2USEC(kt) (kt.tv.sec*1000000 + kt.tv.nsec/1000)
+
+#define MDP_BASE msm_mdp_base
+
+typedef enum {
+ MDP_BC_SCALE_POINT2_POINT4,
+ MDP_BC_SCALE_POINT4_POINT6,
+ MDP_BC_SCALE_POINT6_POINT8,
+ MDP_BC_SCALE_POINT8_1,
+ MDP_BC_SCALE_UP,
+ MDP_PR_SCALE_POINT2_POINT4,
+ MDP_PR_SCALE_POINT4_POINT6,
+ MDP_PR_SCALE_POINT6_POINT8,
+ MDP_PR_SCALE_POINT8_1,
+ MDP_PR_SCALE_UP,
+ MDP_SCALE_BLUR,
+ MDP_INIT_SCALE
+} MDP_SCALE_MODE;
+
+typedef enum {
+ MDP_BLOCK_POWER_OFF,
+ MDP_BLOCK_POWER_ON
+} MDP_BLOCK_POWER_STATE;
+
+typedef enum {
+ MDP_MASTER_BLOCK,
+ MDP_CMD_BLOCK,
+ MDP_PPP_BLOCK,
+ MDP_DMA2_BLOCK,
+ MDP_DMA3_BLOCK,
+ MDP_DMA_S_BLOCK,
+ MDP_DMA_E_BLOCK,
+ MDP_OVERLAY0_BLOCK,
+ MDP_OVERLAY1_BLOCK,
+ MDP_MAX_BLOCK
+} MDP_BLOCK_TYPE;
+
+/* Let's keep Q Factor power of 2 for optimization */
+#define MDP_SCALE_Q_FACTOR 512
+
+#ifdef CONFIG_FB_MSM_MDP31
+#define MDP_MAX_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*8)
+#define MDP_MIN_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/8)
+#define MDP_MAX_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*8)
+#define MDP_MIN_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/8)
+#else
+#define MDP_MAX_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*4)
+#define MDP_MIN_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/4)
+#define MDP_MAX_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*4)
+#define MDP_MIN_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/4)
+#endif
+
+/* SHIM Q Factor */
+#define PHI_Q_FACTOR 29
+#define PQF_PLUS_5 (PHI_Q_FACTOR + 5) /* due to 32 phases */
+#define PQF_PLUS_4 (PHI_Q_FACTOR + 4)
+#define PQF_PLUS_2 (PHI_Q_FACTOR + 2) /* to get 4.0 */
+#define PQF_MINUS_2 (PHI_Q_FACTOR - 2) /* to get 0.25 */
+#define PQF_PLUS_5_PLUS_2 (PQF_PLUS_5 + 2)
+#define PQF_PLUS_5_MINUS_2 (PQF_PLUS_5 - 2)
+
+#define MDP_CONVTP(tpVal) (((tpVal&0xF800)<<8)|((tpVal&0x7E0)<<5)|((tpVal&0x1F)<<3))
+
+#define MDPOP_ROTATION (MDPOP_ROT90|MDPOP_LR|MDPOP_UD)
+#define MDP_CHKBIT(val, bit) ((bit) == ((val) & (bit)))
+
+/* overlay interface API defines */
+typedef enum {
+ MORE_IBUF,
+ FINAL_IBUF,
+ COMPLETE_IBUF
+} MDP_IBUF_STATE;
+
+struct mdp_dirty_region {
+ __u32 xoffset; /* source origin in the x-axis */
+ __u32 yoffset; /* source origin in the y-axis */
+ __u32 width; /* number of pixels in the x-axis */
+ __u32 height; /* number of pixels in the y-axis */
+};
+
+/*
+ * MDP extended data types
+ */
+typedef struct mdp_roi_s {
+ uint32 x;
+ uint32 y;
+ uint32 width;
+ uint32 height;
+ int32 lcd_x;
+ int32 lcd_y;
+ uint32 dst_width;
+ uint32 dst_height;
+} MDP_ROI;
+
+typedef struct mdp_ibuf_s {
+ uint8 *buf;
+ uint32 bpp;
+ uint32 ibuf_type;
+ uint32 ibuf_width;
+ uint32 ibuf_height;
+
+ MDP_ROI roi;
+ MDPIMG mdpImg;
+
+ int32 dma_x;
+ int32 dma_y;
+ uint32 dma_w;
+ uint32 dma_h;
+
+ uint32 vsync_enable;
+ uint32 visible_swapped;
+} MDPIBUF;
+
+struct mdp_dma_data {
+ boolean busy;
+ boolean waiting;
+ struct mutex ov_mutex;
+ struct semaphore mutex;
+ struct completion comp;
+};
+
+#define MDP_CMD_DEBUG_ACCESS_BASE (MDP_BASE+0x10000)
+
+#define MDP_DMA2_TERM 0x1
+#define MDP_DMA3_TERM 0x2
+#define MDP_PPP_TERM 0x4
+#define MDP_DMA_S_TERM 0x8
+#ifdef CONFIG_FB_MSM_MDP40
+#define MDP_DMA_E_TERM 0x10
+#define MDP_OVERLAY0_TERM 0x20
+#define MDP_OVERLAY1_TERM 0x40
+#endif
+
+#define ACTIVE_START_X_EN BIT(31)
+#define ACTIVE_START_Y_EN BIT(31)
+#define ACTIVE_HIGH 0
+#define ACTIVE_LOW 1
+#define MDP_DMA_S_DONE BIT(2)
+#define LCDC_FRAME_START BIT(15)
+#define LCDC_UNDERFLOW BIT(16)
+
+#ifdef CONFIG_FB_MSM_MDP22
+#define MDP_DMA_P_DONE BIT(2)
+#else
+#define MDP_DMA_P_DONE BIT(14)
+#endif
+
+#define MDP_PPP_DONE BIT(0)
+#define TV_OUT_DMA3_DONE BIT(6)
+#define TV_ENC_UNDERRUN BIT(7)
+#define TV_OUT_DMA3_START BIT(13)
+#define MDP_HIST_DONE BIT(20)
+
+#ifdef CONFIG_FB_MSM_MDP22
+#define MDP_ANY_INTR_MASK (MDP_PPP_DONE| \
+ MDP_DMA_P_DONE| \
+ TV_ENC_UNDERRUN)
+#else
+#define MDP_ANY_INTR_MASK (MDP_PPP_DONE| \
+ MDP_DMA_P_DONE| \
+ MDP_DMA_S_DONE| \
+ LCDC_UNDERFLOW| \
+ MDP_HIST_DONE| \
+ TV_ENC_UNDERRUN)
+#endif
+
+#define MDP_TOP_LUMA 16
+#define MDP_TOP_CHROMA 0
+#define MDP_BOTTOM_LUMA 19
+#define MDP_BOTTOM_CHROMA 3
+#define MDP_LEFT_LUMA 22
+#define MDP_LEFT_CHROMA 6
+#define MDP_RIGHT_LUMA 25
+#define MDP_RIGHT_CHROMA 9
+
+#define CLR_G 0x0
+#define CLR_B 0x1
+#define CLR_R 0x2
+#define CLR_ALPHA 0x3
+
+#define CLR_Y CLR_G
+#define CLR_CB CLR_B
+#define CLR_CR CLR_R
+
+/* from lsb to msb */
+#define MDP_GET_PACK_PATTERN(a,x,y,z,bit) (((a)<<(bit*3))|((x)<<(bit*2))|((y)<<bit)|(z))
+
+/*
+ * 0x0000 0x0004 0x0008 MDP sync config
+ */
+#ifdef CONFIG_FB_MSM_MDP22
+#define MDP_SYNCFG_HGT_LOC 22
+#define MDP_SYNCFG_VSYNC_EXT_EN BIT(21)
+#define MDP_SYNCFG_VSYNC_INT_EN BIT(20)
+#else
+#define MDP_SYNCFG_HGT_LOC 21
+#define MDP_SYNCFG_VSYNC_EXT_EN BIT(20)
+#define MDP_SYNCFG_VSYNC_INT_EN BIT(19)
+#define MDP_HW_VSYNC
+#endif
+
+/*
+ * 0x0018 MDP VSYNC THREASH
+ */
+#define MDP_PRIM_BELOW_LOC 0
+#define MDP_PRIM_ABOVE_LOC 8
+
+/*
+ * MDP_PRIMARY_VSYNC_OUT_CTRL
+ * 0x0080,84,88 internal vsync pulse config
+ */
+#define VSYNC_PULSE_EN BIT(31)
+#define VSYNC_PULSE_INV BIT(30)
+
+/*
+ * 0x008c MDP VSYNC CONTROL
+ */
+#define DISP0_VSYNC_MAP_VSYNC0 0
+#define DISP0_VSYNC_MAP_VSYNC1 BIT(0)
+#define DISP0_VSYNC_MAP_VSYNC2 BIT(0)|BIT(1)
+
+#define DISP1_VSYNC_MAP_VSYNC0 0
+#define DISP1_VSYNC_MAP_VSYNC1 BIT(2)
+#define DISP1_VSYNC_MAP_VSYNC2 BIT(2)|BIT(3)
+
+#define PRIMARY_LCD_SYNC_EN BIT(4)
+#define PRIMARY_LCD_SYNC_DISABLE 0
+
+#define SECONDARY_LCD_SYNC_EN BIT(5)
+#define SECONDARY_LCD_SYNC_DISABLE 0
+
+#define EXTERNAL_LCD_SYNC_EN BIT(6)
+#define EXTERNAL_LCD_SYNC_DISABLE 0
+
+/*
+ * 0x101f0 MDP VSYNC Threshold
+ */
+#define VSYNC_THRESHOLD_ABOVE_LOC 0
+#define VSYNC_THRESHOLD_BELOW_LOC 16
+#define VSYNC_ANTI_TEAR_EN BIT(31)
+
+/*
+ * 0x10004 command config
+ */
+#define MDP_CMD_DBGBUS_EN BIT(0)
+
+/*
+ * 0x10124 or 0x101d4PPP source config
+ */
+#define PPP_SRC_C0G_8BITS (BIT(1)|BIT(0))
+#define PPP_SRC_C1B_8BITS (BIT(3)|BIT(2))
+#define PPP_SRC_C2R_8BITS (BIT(5)|BIT(4))
+#define PPP_SRC_C3A_8BITS (BIT(7)|BIT(6))
+
+#define PPP_SRC_C0G_6BITS BIT(1)
+#define PPP_SRC_C1B_6BITS BIT(3)
+#define PPP_SRC_C2R_6BITS BIT(5)
+
+#define PPP_SRC_C0G_5BITS BIT(0)
+#define PPP_SRC_C1B_5BITS BIT(2)
+#define PPP_SRC_C2R_5BITS BIT(4)
+
+#define PPP_SRC_C3_ALPHA_EN BIT(8)
+
+#define PPP_SRC_BPP_INTERLVD_1BYTES 0
+#define PPP_SRC_BPP_INTERLVD_2BYTES BIT(9)
+#define PPP_SRC_BPP_INTERLVD_3BYTES BIT(10)
+#define PPP_SRC_BPP_INTERLVD_4BYTES (BIT(10)|BIT(9))
+
+#define PPP_SRC_BPP_ROI_ODD_X BIT(11)
+#define PPP_SRC_BPP_ROI_ODD_Y BIT(12)
+#define PPP_SRC_INTERLVD_2COMPONENTS BIT(13)
+#define PPP_SRC_INTERLVD_3COMPONENTS BIT(14)
+#define PPP_SRC_INTERLVD_4COMPONENTS (BIT(14)|BIT(13))
+
+/*
+ * RGB666 unpack format
+ * TIGHT means R6+G6+B6 together
+ * LOOSE means R6+2 +G6+2+ B6+2 (with MSB)
+ * or 2+R6 +2+G6 +2+B6 (with LSB)
+ */
+#define PPP_SRC_UNPACK_TIGHT BIT(17)
+#define PPP_SRC_UNPACK_LOOSE 0
+#define PPP_SRC_UNPACK_ALIGN_LSB 0
+#define PPP_SRC_UNPACK_ALIGN_MSB BIT(18)
+
+#define PPP_SRC_FETCH_PLANES_INTERLVD 0
+#define PPP_SRC_FETCH_PLANES_PSEUDOPLNR BIT(20)
+
+#define PPP_SRC_WMV9_MODE BIT(21) /* window media version 9 */
+
+/*
+ * 0x10138 PPP operation config
+ */
+#define PPP_OP_SCALE_X_ON BIT(0)
+#define PPP_OP_SCALE_Y_ON BIT(1)
+
+#define PPP_OP_CONVERT_RGB2YCBCR 0
+#define PPP_OP_CONVERT_YCBCR2RGB BIT(2)
+#define PPP_OP_CONVERT_ON BIT(3)
+
+#define PPP_OP_CONVERT_MATRIX_PRIMARY 0
+#define PPP_OP_CONVERT_MATRIX_SECONDARY BIT(4)
+
+#define PPP_OP_LUT_C0_ON BIT(5)
+#define PPP_OP_LUT_C1_ON BIT(6)
+#define PPP_OP_LUT_C2_ON BIT(7)
+
+/* rotate or blend enable */
+#define PPP_OP_ROT_ON BIT(8)
+
+#define PPP_OP_ROT_90 BIT(9)
+#define PPP_OP_FLIP_LR BIT(10)
+#define PPP_OP_FLIP_UD BIT(11)
+
+#define PPP_OP_BLEND_ON BIT(12)
+
+#define PPP_OP_BLEND_SRCPIXEL_ALPHA 0
+#define PPP_OP_BLEND_DSTPIXEL_ALPHA BIT(13)
+#define PPP_OP_BLEND_CONSTANT_ALPHA BIT(14)
+#define PPP_OP_BLEND_SRCPIXEL_TRANSP (BIT(13)|BIT(14))
+
+#define PPP_OP_BLEND_ALPHA_BLEND_NORMAL 0
+#define PPP_OP_BLEND_ALPHA_BLEND_REVERSE BIT(15)
+
+#define PPP_OP_DITHER_EN BIT(16)
+
+#define PPP_OP_COLOR_SPACE_RGB 0
+#define PPP_OP_COLOR_SPACE_YCBCR BIT(17)
+
+#define PPP_OP_SRC_CHROMA_RGB 0
+#define PPP_OP_SRC_CHROMA_H2V1 BIT(18)
+#define PPP_OP_SRC_CHROMA_H1V2 BIT(19)
+#define PPP_OP_SRC_CHROMA_420 (BIT(18)|BIT(19))
+#define PPP_OP_SRC_CHROMA_COSITE 0
+#define PPP_OP_SRC_CHROMA_OFFSITE BIT(20)
+
+#define PPP_OP_DST_CHROMA_RGB 0
+#define PPP_OP_DST_CHROMA_H2V1 BIT(21)
+#define PPP_OP_DST_CHROMA_H1V2 BIT(22)
+#define PPP_OP_DST_CHROMA_420 (BIT(21)|BIT(22))
+#define PPP_OP_DST_CHROMA_COSITE 0
+#define PPP_OP_DST_CHROMA_OFFSITE BIT(23)
+
+#define PPP_BLEND_CALPHA_TRNASP BIT(24)
+
+#define PPP_OP_BG_CHROMA_RGB 0
+#define PPP_OP_BG_CHROMA_H2V1 BIT(25)
+#define PPP_OP_BG_CHROMA_H1V2 BIT(26)
+#define PPP_OP_BG_CHROMA_420 BIT(25)|BIT(26)
+#define PPP_OP_BG_CHROMA_SITE_COSITE 0
+#define PPP_OP_BG_CHROMA_SITE_OFFSITE BIT(27)
+#define PPP_OP_DEINT_EN BIT(29)
+
+#define PPP_BLEND_BG_USE_ALPHA_SEL (1 << 0)
+#define PPP_BLEND_BG_ALPHA_REVERSE (1 << 3)
+#define PPP_BLEND_BG_SRCPIXEL_ALPHA (0 << 1)
+#define PPP_BLEND_BG_DSTPIXEL_ALPHA (1 << 1)
+#define PPP_BLEND_BG_CONSTANT_ALPHA (2 << 1)
+#define PPP_BLEND_BG_CONST_ALPHA_VAL(x) ((x) << 24)
+
+#define PPP_OP_DST_RGB 0
+#define PPP_OP_DST_YCBCR BIT(30)
+/*
+ * 0x10150 PPP destination config
+ */
+#define PPP_DST_C0G_8BIT (BIT(0)|BIT(1))
+#define PPP_DST_C1B_8BIT (BIT(3)|BIT(2))
+#define PPP_DST_C2R_8BIT (BIT(5)|BIT(4))
+#define PPP_DST_C3A_8BIT (BIT(7)|BIT(6))
+
+#define PPP_DST_C0G_6BIT BIT(1)
+#define PPP_DST_C1B_6BIT BIT(3)
+#define PPP_DST_C2R_6BIT BIT(5)
+
+#define PPP_DST_C0G_5BIT BIT(0)
+#define PPP_DST_C1B_5BIT BIT(2)
+#define PPP_DST_C2R_5BIT BIT(4)
+
+#define PPP_DST_C3A_8BIT (BIT(7)|BIT(6))
+#define PPP_DST_C3ALPHA_EN BIT(8)
+
+#define PPP_DST_PACKET_CNT_INTERLVD_2ELEM BIT(9)
+#define PPP_DST_PACKET_CNT_INTERLVD_3ELEM BIT(10)
+#define PPP_DST_PACKET_CNT_INTERLVD_4ELEM (BIT(10)|BIT(9))
+#define PPP_DST_PACKET_CNT_INTERLVD_6ELEM (BIT(11)|BIT(9))
+
+#define PPP_DST_PACK_LOOSE 0
+#define PPP_DST_PACK_TIGHT BIT(13)
+#define PPP_DST_PACK_ALIGN_LSB 0
+#define PPP_DST_PACK_ALIGN_MSB BIT(14)
+
+#define PPP_DST_OUT_SEL_AXI 0
+#define PPP_DST_OUT_SEL_MDDI BIT(15)
+
+#define PPP_DST_BPP_2BYTES BIT(16)
+#define PPP_DST_BPP_3BYTES BIT(17)
+#define PPP_DST_BPP_4BYTES (BIT(17)|BIT(16))
+
+#define PPP_DST_PLANE_INTERLVD 0
+#define PPP_DST_PLANE_PLANAR BIT(18)
+#define PPP_DST_PLANE_PSEUDOPLN BIT(19)
+
+#define PPP_DST_TO_TV BIT(20)
+
+#define PPP_DST_MDDI_PRIMARY 0
+#define PPP_DST_MDDI_SECONDARY BIT(21)
+#define PPP_DST_MDDI_EXTERNAL BIT(22)
+
+/*
+ * 0x10180 DMA config
+ */
+#define DMA_DSTC0G_8BITS (BIT(1)|BIT(0))
+#define DMA_DSTC1B_8BITS (BIT(3)|BIT(2))
+#define DMA_DSTC2R_8BITS (BIT(5)|BIT(4))
+
+#define DMA_DSTC0G_6BITS BIT(1)
+#define DMA_DSTC1B_6BITS BIT(3)
+#define DMA_DSTC2R_6BITS BIT(5)
+
+#define DMA_DSTC0G_5BITS BIT(0)
+#define DMA_DSTC1B_5BITS BIT(2)
+#define DMA_DSTC2R_5BITS BIT(4)
+
+#define DMA_PACK_TIGHT BIT(6)
+#define DMA_PACK_LOOSE 0
+#define DMA_PACK_ALIGN_LSB 0
+/*
+ * use DMA_PACK_ALIGN_MSB if the upper 6 bits from 8 bits output
+ * from LCDC block maps into 6 pins out to the panel
+ */
+#define DMA_PACK_ALIGN_MSB BIT(7)
+#define DMA_PACK_PATTERN_RGB \
+ (MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 2)<<8)
+#define DMA_PACK_PATTERN_BGR \
+ (MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 2)<<8)
+#define DMA_OUT_SEL_AHB 0
+#define DMA_OUT_SEL_LCDC BIT(20)
+#define DMA_IBUF_FORMAT_RGB888 0
+#define DMA_IBUF_FORMAT_xRGB8888_OR_ARGB8888 BIT(26)
+
+#ifdef CONFIG_FB_MSM_MDP22
+#define DMA_OUT_SEL_MDDI BIT(14)
+#define DMA_AHBM_LCD_SEL_PRIMARY 0
+#define DMA_AHBM_LCD_SEL_SECONDARY BIT(15)
+#define DMA_IBUF_C3ALPHA_EN BIT(16)
+#define DMA_DITHER_EN BIT(17)
+#define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY 0
+#define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY BIT(18)
+#define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL BIT(19)
+#define DMA_IBUF_FORMAT_RGB565 BIT(20)
+#define DMA_IBUF_FORMAT_RGB888_OR_ARGB8888 0
+#define DMA_IBUF_NONCONTIGUOUS BIT(21)
+#else
+#define DMA_OUT_SEL_MDDI BIT(19)
+#define DMA_AHBM_LCD_SEL_PRIMARY 0
+#define DMA_AHBM_LCD_SEL_SECONDARY 0
+#define DMA_IBUF_C3ALPHA_EN 0
+#define DMA_DITHER_EN BIT(24)
+#define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY 0
+#define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY 0
+#define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL 0
+#define DMA_IBUF_FORMAT_RGB565 BIT(25)
+#define DMA_IBUF_NONCONTIGUOUS 0
+#endif
+
+/*
+ * MDDI Register
+ */
+#define MDDI_VDO_PACKET_DESC 0x5666
+
+#ifdef CONFIG_FB_MSM_MDP40
+#define MDP_INTR_ENABLE (msm_mdp_base + 0x0050)
+#define MDP_INTR_STATUS (msm_mdp_base + 0x0054)
+#define MDP_INTR_CLEAR (msm_mdp_base + 0x0058)
+#define MDP_EBI2_LCD0 (msm_mdp_base + 0x0060)
+#define MDP_EBI2_LCD1 (msm_mdp_base + 0x0064)
+#define MDP_EBI2_PORTMAP_MODE (msm_mdp_base + 0x0070)
+
+#define MDP_DMA_P_HIST_INTR_STATUS (msm_mdp_base + 0x95014)
+#define MDP_DMA_P_HIST_INTR_CLEAR (msm_mdp_base + 0x95018)
+#define MDP_DMA_P_HIST_INTR_ENABLE (msm_mdp_base + 0x9501C)
+#else
+#define MDP_INTR_ENABLE (msm_mdp_base + 0x0020)
+#define MDP_INTR_STATUS (msm_mdp_base + 0x0024)
+#define MDP_INTR_CLEAR (msm_mdp_base + 0x0028)
+#define MDP_EBI2_LCD0 (msm_mdp_base + 0x003c)
+#define MDP_EBI2_LCD1 (msm_mdp_base + 0x0040)
+#define MDP_EBI2_PORTMAP_MODE (msm_mdp_base + 0x005c)
+#endif
+
+#define MDP_FULL_BYPASS_WORD43 (msm_mdp_base + 0x101ac)
+
+#define MDP_CSC_PFMVn(n) (msm_mdp_base + 0x40400 + 4 * (n))
+#define MDP_CSC_PRMVn(n) (msm_mdp_base + 0x40440 + 4 * (n))
+#define MDP_CSC_PRE_BV1n(n) (msm_mdp_base + 0x40500 + 4 * (n))
+#define MDP_CSC_PRE_BV2n(n) (msm_mdp_base + 0x40540 + 4 * (n))
+#define MDP_CSC_POST_BV1n(n) (msm_mdp_base + 0x40580 + 4 * (n))
+#define MDP_CSC_POST_BV2n(n) (msm_mdp_base + 0x405c0 + 4 * (n))
+
+#ifdef CONFIG_FB_MSM_MDP31
+#define MDP_CSC_PRE_LV1n(n) (msm_mdp_base + 0x40600 + 4 * (n))
+#define MDP_CSC_PRE_LV2n(n) (msm_mdp_base + 0x40640 + 4 * (n))
+#define MDP_CSC_POST_LV1n(n) (msm_mdp_base + 0x40680 + 4 * (n))
+#define MDP_CSC_POST_LV2n(n) (msm_mdp_base + 0x406c0 + 4 * (n))
+#define MDP_PPP_SCALE_COEFF_LSBn(n) (msm_mdp_base + 0x50400 + 8 * (n))
+#define MDP_PPP_SCALE_COEFF_MSBn(n) (msm_mdp_base + 0x50404 + 8 * (n))
+
+#define SCALE_D0_SET 0
+#define SCALE_D1_SET BIT(0)
+#define SCALE_D2_SET BIT(1)
+#define SCALE_U1_SET (BIT(0)|BIT(1))
+
+#else
+#define MDP_CSC_PRE_LV1n(n) (msm_mdp_base + 0x40580 + 4 * (n))
+#endif
+
+#define MDP_CURSOR_WIDTH 64
+#define MDP_CURSOR_HEIGHT 64
+#define MDP_CURSOR_SIZE (MDP_CURSOR_WIDTH*MDP_CURSOR_WIDTH*4)
+
+#define MDP_DMA_P_LUT_C0_EN BIT(0)
+#define MDP_DMA_P_LUT_C1_EN BIT(1)
+#define MDP_DMA_P_LUT_C2_EN BIT(2)
+#define MDP_DMA_P_LUT_POST BIT(4)
+
+void mdp_hw_init(void);
+int mdp_ppp_pipe_wait(void);
+void mdp_pipe_kickoff(uint32 term, struct msm_fb_data_type *mfd);
+void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
+ boolean isr);
+void mdp_set_dma_pan_info(struct fb_info *info, struct mdp_dirty_region *dirty,
+ boolean sync);
+void mdp_dma_pan_update(struct fb_info *info);
+void mdp_refresh_screen(unsigned long data);
+int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req,
+ struct file **pp_src, struct file **pp_dest);
+void mdp_lcd_update_workqueue_handler(struct work_struct *work);
+void mdp_vsync_resync_workqueue_handler(struct work_struct *work);
+void mdp_dma2_update(struct msm_fb_data_type *mfd);
+void mdp_config_vsync(struct msm_fb_data_type *);
+uint32 mdp_get_lcd_line_counter(struct msm_fb_data_type *mfd);
+enum hrtimer_restart mdp_dma2_vsync_hrtimer_handler(struct hrtimer *ht);
+void mdp_set_scale(MDPIBUF *iBuf,
+ uint32 dst_roi_width,
+ uint32 dst_roi_height,
+ boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr);
+void mdp_init_scale_table(void);
+void mdp_adjust_start_addr(uint8 **src0,
+ uint8 **src1,
+ int v_slice,
+ int h_slice,
+ int x,
+ int y,
+ uint32 width,
+ uint32 height, int bpp, MDPIBUF *iBuf, int layer);
+void mdp_set_blend_attr(MDPIBUF *iBuf,
+ uint32 *alpha,
+ uint32 *tpVal,
+ uint32 perPixelAlpha, uint32 *pppop_reg_ptr);
+
+int mdp_dma3_on(struct platform_device *pdev);
+int mdp_dma3_off(struct platform_device *pdev);
+void mdp_dma3_update(struct msm_fb_data_type *mfd);
+
+int mdp_lcdc_on(struct platform_device *pdev);
+int mdp_lcdc_off(struct platform_device *pdev);
+void mdp_lcdc_update(struct msm_fb_data_type *mfd);
+int mdp_hw_cursor_update(struct fb_info *info, struct fb_cursor *cursor);
+void mdp_enable_irq(uint32 term);
+void mdp_disable_irq(uint32 term);
+void mdp_disable_irq_nolock(uint32 term);
+uint32_t mdp_get_bytes_per_pixel(uint32_t format);
+
+#ifdef MDP_HW_VSYNC
+void mdp_hw_vsync_clk_enable(struct msm_fb_data_type *mfd);
+void mdp_hw_vsync_clk_disable(struct msm_fb_data_type *mfd);
+#endif
+
+void mdp_dma_s_update(struct msm_fb_data_type *mfd);
+
+/* Added to support flipping */
+void mdp_set_offset_info(struct fb_info *info, uint32 address, uint32 interval);
+
+int get_gem_img(struct mdp_img *img, unsigned long *start,
+ unsigned long *len);
+int get_img(struct mdp_img *img, struct fb_info *info,
+ unsigned long *start, unsigned long *len,
+ struct file **pp_file);
+
+
+/*int get_img(struct msmfb_data *img, struct fb_info *info,
+ unsigned long *start, unsigned long *len, struct file **pp_file);*/
+#endif /* MDP_H */
diff --git a/drivers/staging/msm/mdp4.h b/drivers/staging/msm/mdp4.h
new file mode 100644
index 0000000..26ec8f1
--- /dev/null
+++ b/drivers/staging/msm/mdp4.h
@@ -0,0 +1,352 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 Code Aurora 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, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT 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 MDP4_H
+#define MDP4_H
+
+extern struct mdp_dma_data dma2_data;
+extern struct mdp_dma_data dma_s_data;
+extern struct mdp_dma_data dma_e_data;
+extern struct mdp_histogram mdp_hist;
+extern struct completion mdp_hist_comp;
+extern boolean mdp_is_in_isr;
+extern uint32 mdp_intr_mask;
+extern spinlock_t mdp_spin_lock;
+
+
+#define MDP4_NONBLOCKING /* enable non blocking ioctl */
+
+#define MDP4_OVERLAYPROC0_BASE 0x10000
+#define MDP4_OVERLAYPROC1_BASE 0x18000
+
+#define MDP4_VIDEO_BASE 0x20000
+#define MDP4_VIDEO_OFF 0x10000
+
+#define MDP4_RGB_BASE 0x40000
+#define MDP4_RGB_OFF 0x10000
+
+enum { /* display */
+ PRIMARY_INTF_SEL,
+ SECONDARY_INTF_SEL,
+ EXTERNAL_INTF_SEL
+};
+
+enum {
+ LCDC_RGB_INTF,
+ DTV_INTF = LCDC_RGB_INTF,
+ MDDI_LCDC_INTF,
+ MDDI_INTF,
+ EBI2_INTF
+};
+
+enum {
+ MDDI_PRIMARY_SET,
+ MDDI_SECONDARY_SET,
+ MDDI_EXTERNAL_SET
+};
+
+enum {
+ EBI2_LCD0,
+ EBI2_LCD1
+};
+
+enum {
+ OVERLAY_MODE_NONE,
+ OVERLAY_MODE_BLT
+};
+
+enum {
+ OVERLAY_REFRESH_ON_DEMAND,
+ OVERLAY_REFRESH_VSYNC,
+ OVERLAY_REFRESH_VSYNC_HALF,
+ OVERLAY_REFRESH_VSYNC_QUARTER
+};
+
+enum {
+ OVERLAY_FRAMEBUF,
+ OVERLAY_DIRECTOUT
+};
+
+/* system interrupts */
+#define INTR_OVERLAY0_DONE BIT(0)
+#define INTR_OVERLAY1_DONE BIT(1)
+#define INTR_DMA_S_DONE BIT(2)
+#define INTR_DMA_E_DONE BIT(3)
+#define INTR_DMA_P_DONE BIT(4)
+#define INTR_VG1_HISTOGRAM BIT(5)
+#define INTR_VG2_HISTOGRAM BIT(6)
+#define INTR_PRIMARY_VSYNC BIT(7)
+#define INTR_PRIMARY_INTF_UDERRUN BIT(8)
+#define INTR_EXTERNAL_VSYNC BIT(9)
+#define INTR_EXTERNAL_INTF_UDERRUN BIT(10)
+#define INTR_DMA_P_HISTOGRAM BIT(17)
+
+/* histogram interrupts */
+#define INTR_HIST_DONE BIT(0)
+#define INTR_HIST_RESET_SEQ_DONE BIT(1)
+
+
+#ifdef CONFIG_FB_MSM_OVERLAY
+#define MDP4_ANY_INTR_MASK (INTR_OVERLAY0_DONE)
+#else
+#define MDP4_ANY_INTR_MASK (INTR_DMA_P_DONE)
+#endif
+
+enum {
+ OVERLAY_PIPE_RGB1,
+ OVERLAY_PIPE_RGB2,
+};
+
+enum {
+ OVERLAY_PIPE_VG1, /* video/graphic */
+ OVERLAY_PIPE_VG2
+};
+
+enum {
+ OVERLAY_TYPE_RGB,
+ OVERLAY_TYPE_VG /* video/graphic */
+};
+
+enum {
+ MDP4_MIXER0,
+ MDP4_MIXER1
+};
+
+#define MDP4_MAX_MIXER 2
+
+enum {
+ OVERLAY_PLANE_INTERLEAVED,
+ OVERLAY_PLANE_PLANAR,
+ OVERLAY_PLANE_PSEUDO_PLANAR
+};
+
+enum {
+ MDP4_MIXER_STAGE_UNUNSED, /* pipe not used */
+ MDP4_MIXER_STAGE_BASE,
+ MDP4_MIXER_STAGE0, /* zorder 0 */
+ MDP4_MIXER_STAGE1, /* zorder 1 */
+ MDP4_MIXER_STAGE2 /* zorder 2 */
+};
+
+#define MDP4_MAX_STAGE 4
+
+enum {
+ MDP4_FRAME_FORMAT_LINEAR,
+ MDP4_FRAME_FORMAT_ARGB_TILE,
+ MDP4_FRAME_FORMAT_VIDEO_SUPERTILE
+};
+
+enum {
+ MDP4_CHROMA_RGB,
+ MDP4_CHROMA_H2V1,
+ MDP4_CHROMA_H1V2,
+ MDP4_CHROMA_420
+};
+
+#define MDP4_BLEND_BG_TRANSP_EN BIT(9)
+#define MDP4_BLEND_FG_TRANSP_EN BIT(8)
+#define MDP4_BLEND_BG_MOD_ALPHA BIT(7)
+#define MDP4_BLEND_BG_INV_ALPHA BIT(6)
+#define MDP4_BLEND_BG_ALPHA_FG_CONST (0 << 4)
+#define MDP4_BLEND_BG_ALPHA_BG_CONST (1 << 4)
+#define MDP4_BLEND_BG_ALPHA_FG_PIXEL (2 << 4)
+#define MDP4_BLEND_BG_ALPHA_BG_PIXEL (3 << 4)
+#define MDP4_BLEND_FG_MOD_ALPHA BIT(3)
+#define MDP4_BLEND_FG_INV_ALPHA BIT(2)
+#define MDP4_BLEND_FG_ALPHA_FG_CONST (0 << 0)
+#define MDP4_BLEND_FG_ALPHA_BG_CONST (1 << 0)
+#define MDP4_BLEND_FG_ALPHA_FG_PIXEL (2 << 0)
+#define MDP4_BLEND_FG_ALPHA_BG_PIXEL (3 << 0)
+
+#define MDP4_FORMAT_SOLID_FILL BIT(22)
+#define MDP4_FORMAT_UNPACK_ALIGN_MSB BIT(18)
+#define MDP4_FORMAT_UNPACK_TIGHT BIT(17)
+#define MDP4_FORMAT_90_ROTATED BIT(12)
+#define MDP4_FORMAT_ALPHA_ENABLE BIT(8)
+
+#define MDP4_OP_DEINT_ODD_REF BIT(19)
+#define MDP4_OP_IGC_LUT_EN BIT(16)
+#define MDP4_OP_DITHER_EN BIT(15)
+#define MDP4_OP_FLIP_UD BIT(14)
+#define MDP4_OP_FLIP_LR BIT(13)
+#define MDP4_OP_CSC_EN BIT(11)
+#define MDP4_OP_SRC_DATA_YCBCR BIT(9)
+#define MDP4_OP_SCALEY_FIR (0 << 4)
+#define MDP4_OP_SCALEY_MN_PHASE (1 << 4)
+#define MDP4_OP_SCALEY_PIXEL_RPT (2 << 4)
+#define MDP4_OP_SCALEX_FIR (0 << 2)
+#define MDP4_OP_SCALEX_MN_PHASE (1 << 2)
+#define MDP4_OP_SCALEX_PIXEL_RPT (2 << 2)
+#define MDP4_OP_SCALEY_EN BIT(1)
+#define MDP4_OP_SCALEX_EN BIT(0)
+
+#define MDP4_PIPE_PER_MIXER 2
+
+#define MDP4_MAX_PLANE 4
+
+#define MDP4_MAX_VIDEO_PIPE 2
+#define MDP4_MAX_RGB_PIPE 2
+#define MDP4_MAX_OVERLAY_PIPE 16
+
+
+struct mdp4_overlay_pipe {
+ uint32 pipe_type; /* rgb, video/graphic */
+ uint32 pipe_num;
+ uint32 pipe_ndx;
+ uint32 mixer_num; /* which mixer used */
+ uint32 mixer_stage; /* which stage of mixer used */
+ uint32 src_format;
+ uint32 src_width; /* source img width */
+ uint32 src_height; /* source img height */
+ uint32 src_w; /* roi */
+ uint32 src_h; /* roi */
+ uint32 src_x; /* roi */
+ uint32 src_y; /* roi */
+ uint32 dst_w; /* roi */
+ uint32 dst_h; /* roi */
+ uint32 dst_x; /* roi */
+ uint32 dst_y; /* roi */
+ uint32 op_mode;
+ uint32 transp;
+ uint32 blend_op;
+ uint32 phasex_step;
+ uint32 phasey_step;
+ uint32 alpha;
+ uint32 is_fg; /* control alpha & color key */
+ uint32 srcp0_addr; /* interleave, luma */
+ uint32 srcp0_ystride;
+ uint32 srcp1_addr; /* pseudoplanar, chroma plane */
+ uint32 srcp1_ystride;
+ uint32 srcp2_addr; /* planar color 2*/
+ uint32 srcp2_ystride;
+ uint32 srcp3_addr; /* alpha/color 3 */
+ uint32 srcp3_ystride;
+ uint32 fetch_plane;
+ uint32 frame_format; /* video */
+ uint32 chroma_site; /* video */
+ uint32 chroma_sample; /* video */
+ uint32 solid_fill;
+ uint32 vc1_reduce; /* video */
+ uint32 fatch_planes; /* video */
+ uint32 unpack_align_msb;/* 0 to LSB, 1 to MSB */
+ uint32 unpack_tight;/* 0 for loose, 1 for tight */
+ uint32 unpack_count;/* 0 = 1 component, 1 = 2 component ... */
+ uint32 rotated_90; /* has been rotated 90 degree */
+ uint32 bpp; /* byte per pixel */
+ uint32 alpha_enable;/* source has alpha */
+ /*
+ * number of bits for source component,
+ * 0 = 1 bit, 1 = 2 bits, 2 = 6 bits, 3 = 8 bits
+ */
+ uint32 a_bit; /* component 3, alpha */
+ uint32 r_bit; /* component 2, R_Cr */
+ uint32 b_bit; /* component 1, B_Cb */
+ uint32 g_bit; /* component 0, G_lumz */
+ /*
+ * unpack pattern
+ * A = C3, R = C2, B = C1, G = C0
+ */
+ uint32 element3; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
+ uint32 element2; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
+ uint32 element1; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
+ uint32 element0; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
+ struct completion comp;
+ struct mdp_overlay req_data;
+};
+
+void mdp4_sw_reset(unsigned long bits);
+void mdp4_display_intf_sel(int output, unsigned long intf);
+void mdp4_overlay_cfg(int layer, int blt_mode, int refresh, int direct_out);
+void mdp4_ebi2_lcd_setup(int lcd, unsigned long base, int ystride);
+void mdp4_mddi_setup(int which, unsigned long id);
+unsigned long mdp4_display_status(void);
+void mdp4_enable_clk_irq(void);
+void mdp4_disable_clk_irq(void);
+void mdp4_dma_p_update(struct msm_fb_data_type *mfd);
+void mdp4_dma_s_update(struct msm_fb_data_type *mfd);
+void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
+ boolean isr);
+void mdp4_pipe_kickoff(uint32 pipe, struct msm_fb_data_type *mfd);
+int mdp4_lcdc_on(struct platform_device *pdev);
+int mdp4_lcdc_off(struct platform_device *pdev);
+void mdp4_lcdc_update(struct msm_fb_data_type *mfd);
+void mdp4_intr_clear_set(ulong clear, ulong set);
+void mdp4_dma_p_cfg(void);
+void mdp4_hw_init(void);
+void mdp4_isr_read(int);
+void mdp4_clear_lcdc(void);
+void mdp4_mixer_blend_init(int mixer_num);
+void mdp4_vg_qseed_init(int vg_num);
+void mdp4_vg_csc_mv_setup(int vp_num);
+void mdp4_vg_csc_pre_bv_setup(int vp_num);
+void mdp4_vg_csc_post_bv_setup(int vp_num);
+void mdp4_vg_csc_pre_lv_setup(int vp_num);
+void mdp4_vg_csc_post_lv_setup(int vp_num);
+irqreturn_t mdp4_isr(int irq, void *ptr);
+void mdp4_overlay_format_to_pipe(uint32 format, struct mdp4_overlay_pipe *pipe);
+uint32 mdp4_overlay_format(struct mdp4_overlay_pipe *pipe);
+uint32 mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe);
+uint32 mdp4_overlay_op_mode(struct mdp4_overlay_pipe *pipe);
+void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd);
+void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe);
+void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all);
+void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe);
+void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe);
+void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe);
+int mdp4_mixer_stage_can_run(struct mdp4_overlay_pipe *pipe);
+void mdp4_overlayproc_cfg(struct mdp4_overlay_pipe *pipe);
+void mdp4_mddi_overlay(struct msm_fb_data_type *mfd);
+int mdp4_overlay_format2type(uint32 format);
+int mdp4_overlay_format2pipe(struct mdp4_overlay_pipe *pipe);
+int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req);
+int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req);
+int mdp4_overlay_unset(struct fb_info *info, int ndx);
+int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req,
+ struct file **pp_src_file);
+struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(void);
+void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe);
+void mdp4_overlay_dmap_cfg(struct msm_fb_data_type *mfd, int lcdc);
+void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe);
+int mdp4_overlay_active(int mixer);
+void mdp4_overlay0_done_lcdc(void);
+void mdp4_overlay0_done_mddi(void);
+void mdp4_mddi_overlay_restore(void);
+void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe);
+void mdp4_rgb_igc_lut_setup(int num);
+void mdp4_vg_igc_lut_setup(int num);
+void mdp4_mixer_gc_lut_setup(int mixer_num);
+
+#ifdef CONFIG_DEBUG_FS
+int mdp4_debugfs_init(void);
+#endif
+
+int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req,
+ struct file **pp_src_file, struct file **pp_dst_file);
+
+#endif /* MDP_H */
diff --git a/drivers/staging/msm/mdp4_debugfs.c b/drivers/staging/msm/mdp4_debugfs.c
new file mode 100644
index 0000000..844d467
--- /dev/null
+++ b/drivers/staging/msm/mdp4_debugfs.c
@@ -0,0 +1,181 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
+#include <linux/clk.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+
+#define MDP4_DEBUG_BUF 128
+
+
+static char mdp4_debug_buf[MDP4_DEBUG_BUF];
+static ulong mdp4_debug_offset;
+static ulong mdp4_base_addr;
+
+static int mdp4_offset_set(void *data, u64 val)
+{
+ mdp4_debug_offset = (int)val;
+ return 0;
+}
+
+static int mdp4_offset_get(void *data, u64 *val)
+{
+ *val = (u64)mdp4_debug_offset;
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(
+ mdp4_offset_fops,
+ mdp4_offset_get,
+ mdp4_offset_set,
+ "%llx\n");
+
+
+static int mdp4_debugfs_open(struct inode *inode, struct file *file)
+{
+ /* non-seekable */
+ file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
+ return 0;
+}
+
+static int mdp4_debugfs_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static ssize_t mdp4_debugfs_write(
+ struct file *file,
+ const char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ int cnt;
+ unsigned int data;
+
+ printk(KERN_INFO "%s: offset=%d count=%d *ppos=%d\n",
+ __func__, (int)mdp4_debug_offset, (int)count, (int)*ppos);
+
+ if (count > sizeof(mdp4_debug_buf))
+ return -EFAULT;
+
+ if (copy_from_user(mdp4_debug_buf, buff, count))
+ return -EFAULT;
+
+
+ mdp4_debug_buf[count] = 0; /* end of string */
+
+ cnt = sscanf(mdp4_debug_buf, "%x", &data);
+ if (cnt < 1) {
+ printk(KERN_ERR "%s: sscanf failed cnt=%d" , __func__, cnt);
+ return -EINVAL;
+ }
+
+ writel(&data, mdp4_base_addr + mdp4_debug_offset);
+
+ return 0;
+}
+
+static ssize_t mdp4_debugfs_read(
+ struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ int len = 0;
+ unsigned int data;
+
+ printk(KERN_INFO "%s: offset=%d count=%d *ppos=%d\n",
+ __func__, (int)mdp4_debug_offset, (int)count, (int)*ppos);
+
+ if (*ppos)
+ return 0; /* the end */
+
+ data = readl(mdp4_base_addr + mdp4_debug_offset);
+
+ len = snprintf(mdp4_debug_buf, 4, "%x\n", data);
+
+ if (len > 0) {
+ if (len > count)
+ len = count;
+ if (copy_to_user(buff, mdp4_debug_buf, len))
+ return -EFAULT;
+ }
+
+ printk(KERN_INFO "%s: len=%d\n", __func__, len);
+
+ if (len < 0)
+ return 0;
+
+ *ppos += len; /* increase offset */
+
+ return len;
+}
+
+static const struct file_operations mdp4_debugfs_fops = {
+ .open = mdp4_debugfs_open,
+ .release = mdp4_debugfs_release,
+ .read = mdp4_debugfs_read,
+ .write = mdp4_debugfs_write,
+};
+
+int mdp4_debugfs_init(void)
+{
+ struct dentry *dent = debugfs_create_dir("mdp4", NULL);
+
+ if (IS_ERR(dent)) {
+ printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n",
+ __FILE__, __LINE__, PTR_ERR(dent));
+ return -1;
+ }
+
+ if (debugfs_create_file("offset", 0644, dent, 0, &mdp4_offset_fops)
+ == NULL) {
+ printk(KERN_ERR "%s(%d): debugfs_create_file: offset fail\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
+
+ if (debugfs_create_file("regs", 0644, dent, 0, &mdp4_debugfs_fops)
+ == NULL) {
+ printk(KERN_ERR "%s(%d): debugfs_create_file: regs fail\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
+
+ mdp4_debug_offset = 0;
+ mdp4_base_addr = (ulong) msm_mdp_base; /* defined at msm_fb_def.h */
+
+ return 0;
+}
diff --git a/drivers/staging/msm/mdp4_overlay.c b/drivers/staging/msm/mdp4_overlay.c
new file mode 100644
index 0000000..304bb82
--- /dev/null
+++ b/drivers/staging/msm/mdp4_overlay.c
@@ -0,0 +1,1259 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
+#include <linux/clk.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+#include <linux/fb.h>
+#include <msm_mdp.h>
+#include <linux/file.h>
+#include "android_pmem.h"
+#include <linux/major.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/mutex.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+
+struct mdp4_overlay_ctrl {
+ struct mdp4_overlay_pipe plist[MDP4_MAX_OVERLAY_PIPE];
+ struct mdp4_overlay_pipe *stage[MDP4_MAX_MIXER][MDP4_MAX_STAGE];
+} mdp4_overlay_db;
+
+static struct mdp4_overlay_ctrl *ctrl = &mdp4_overlay_db;
+
+
+void mdp4_overlay_dmap_cfg(struct msm_fb_data_type *mfd, int lcdc)
+{
+ uint32 dma2_cfg_reg;
+
+ dma2_cfg_reg = DMA_DITHER_EN;
+
+ if (mfd->fb_imgType == MDP_BGR_565)
+ dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
+ else
+ dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;
+
+
+ if (mfd->panel_info.bpp == 18) {
+ dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 666 18BPP */
+ DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
+ } else if (mfd->panel_info.bpp == 16) {
+ dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */
+ DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
+ } else {
+ dma2_cfg_reg |= DMA_DSTC0G_8BITS | /* 888 16BPP */
+ DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
+ }
+
+ if (lcdc)
+ dma2_cfg_reg |= DMA_PACK_ALIGN_MSB;
+
+ /* dma2 config register */
+ MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);
+
+}
+
+void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe)
+{
+
+ /* dma_p source */
+ MDP_OUTP(MDP_BASE + 0x90004,
+ (pipe->src_height << 16 | pipe->src_width));
+ MDP_OUTP(MDP_BASE + 0x90008, pipe->srcp0_addr);
+ MDP_OUTP(MDP_BASE + 0x9000c, pipe->srcp0_ystride);
+
+ /* dma_p dest */
+ MDP_OUTP(MDP_BASE + 0x90010, (pipe->dst_y << 16 | pipe->dst_x));
+}
+
+#define MDP4_VG_PHASE_STEP_DEFAULT 0x20000000
+#define MDP4_VG_PHASE_STEP_SHIFT 29
+
+static int mdp4_leading_0(uint32 num)
+{
+ uint32 bit = 0x80000000;
+ int i;
+
+ for (i = 0; i < 32; i++) {
+ if (bit & num)
+ return i;
+ bit >>= 1;
+ }
+
+ return i;
+}
+
+static uint32 mdp4_scale_phase_step(int f_num, uint32 src, uint32 dst)
+{
+ uint32 val;
+ int n;
+
+ n = mdp4_leading_0(src);
+ if (n > f_num)
+ n = f_num;
+ val = src << n; /* maximum to reduce lose of resolution */
+ val /= dst;
+ if (n < f_num) {
+ n = f_num - n;
+ val <<= n;
+ }
+
+ return val;
+}
+
+static void mdp4_scale_setup(struct mdp4_overlay_pipe *pipe)
+{
+
+ pipe->phasex_step = MDP4_VG_PHASE_STEP_DEFAULT;
+ pipe->phasey_step = MDP4_VG_PHASE_STEP_DEFAULT;
+
+ if (pipe->dst_h && pipe->src_h != pipe->dst_h) {
+ if (pipe->dst_h >= pipe->src_h * 8) /* too much */
+ return;
+ pipe->op_mode |= MDP4_OP_SCALEY_EN;
+
+ if (pipe->pipe_type == OVERLAY_TYPE_VG) {
+ if (pipe->dst_h <= (pipe->src_h / 4))
+ pipe->op_mode |= MDP4_OP_SCALEY_MN_PHASE;
+ else
+ pipe->op_mode |= MDP4_OP_SCALEY_FIR;
+ }
+
+ pipe->phasey_step = mdp4_scale_phase_step(29,
+ pipe->src_h, pipe->dst_h);
+ }
+
+ if (pipe->dst_w && pipe->src_w != pipe->dst_w) {
+ if (pipe->dst_w >= pipe->src_w * 8) /* too much */
+ return;
+ pipe->op_mode |= MDP4_OP_SCALEX_EN;
+
+ if (pipe->pipe_type == OVERLAY_TYPE_VG) {
+ if (pipe->dst_w <= (pipe->src_w / 4))
+ pipe->op_mode |= MDP4_OP_SCALEY_MN_PHASE;
+ else
+ pipe->op_mode |= MDP4_OP_SCALEY_FIR;
+ }
+
+ pipe->phasex_step = mdp4_scale_phase_step(29,
+ pipe->src_w, pipe->dst_w);
+ }
+}
+
+void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe)
+{
+ char *rgb_base;
+ uint32 src_size, src_xy, dst_size, dst_xy;
+ uint32 format, pattern;
+
+ rgb_base = MDP_BASE + MDP4_RGB_BASE;
+ rgb_base += (MDP4_RGB_OFF * pipe->pipe_num);
+
+ src_size = ((pipe->src_h << 16) | pipe->src_w);
+ src_xy = ((pipe->src_y << 16) | pipe->src_x);
+ dst_size = ((pipe->dst_h << 16) | pipe->dst_w);
+ dst_xy = ((pipe->dst_y << 16) | pipe->dst_x);
+
+ format = mdp4_overlay_format(pipe);
+ pattern = mdp4_overlay_unpack_pattern(pipe);
+
+ pipe->op_mode |= MDP4_OP_IGC_LUT_EN;
+
+ mdp4_scale_setup(pipe);
+
+ outpdw(rgb_base + 0x0000, src_size); /* MDP_RGB_SRC_SIZE */
+ outpdw(rgb_base + 0x0004, src_xy); /* MDP_RGB_SRC_XY */
+ outpdw(rgb_base + 0x0008, dst_size); /* MDP_RGB_DST_SIZE */
+ outpdw(rgb_base + 0x000c, dst_xy); /* MDP_RGB_DST_XY */
+
+ outpdw(rgb_base + 0x0010, pipe->srcp0_addr);
+ outpdw(rgb_base + 0x0040, pipe->srcp0_ystride);
+
+ outpdw(rgb_base + 0x0050, format);/* MDP_RGB_SRC_FORMAT */
+ outpdw(rgb_base + 0x0054, pattern);/* MDP_RGB_SRC_UNPACK_PATTERN */
+ outpdw(rgb_base + 0x0058, pipe->op_mode);/* MDP_RGB_OP_MODE */
+ outpdw(rgb_base + 0x005c, pipe->phasex_step);
+ outpdw(rgb_base + 0x0060, pipe->phasey_step);
+
+ /* 16 bytes-burst x 3 req <= 48 bytes */
+ outpdw(rgb_base + 0x1004, 0xc2); /* MDP_RGB_FETCH_CFG */
+}
+
+void mdp4_overlay_vg_setup(struct mdp4_overlay_pipe *pipe)
+{
+ char *vg_base;
+ uint32 frame_size, src_size, src_xy, dst_size, dst_xy;
+ uint32 format, pattern;
+
+ vg_base = MDP_BASE + MDP4_VIDEO_BASE;
+ vg_base += (MDP4_VIDEO_OFF * pipe->pipe_num);
+
+ frame_size = ((pipe->src_height << 16) | pipe->src_width);
+ src_size = ((pipe->src_h << 16) | pipe->src_w);
+ src_xy = ((pipe->src_y << 16) | pipe->src_x);
+ dst_size = ((pipe->dst_h << 16) | pipe->dst_w);
+ dst_xy = ((pipe->dst_y << 16) | pipe->dst_x);
+
+ format = mdp4_overlay_format(pipe);
+ pattern = mdp4_overlay_unpack_pattern(pipe);
+
+ pipe->op_mode |= (MDP4_OP_CSC_EN | MDP4_OP_SRC_DATA_YCBCR |
+ MDP4_OP_IGC_LUT_EN);
+
+ mdp4_scale_setup(pipe);
+
+ outpdw(vg_base + 0x0000, src_size); /* MDP_RGB_SRC_SIZE */
+ outpdw(vg_base + 0x0004, src_xy); /* MDP_RGB_SRC_XY */
+ outpdw(vg_base + 0x0008, dst_size); /* MDP_RGB_DST_SIZE */
+ outpdw(vg_base + 0x000c, dst_xy); /* MDP_RGB_DST_XY */
+ outpdw(vg_base + 0x0048, frame_size); /* TILE frame size */
+
+ /* luma component plane */
+ outpdw(vg_base + 0x0010, pipe->srcp0_addr);
+
+ /* chroma component plane */
+ outpdw(vg_base + 0x0014, pipe->srcp1_addr);
+
+ outpdw(vg_base + 0x0040,
+ pipe->srcp1_ystride << 16 | pipe->srcp0_ystride);
+
+ outpdw(vg_base + 0x0050, format); /* MDP_RGB_SRC_FORMAT */
+ outpdw(vg_base + 0x0054, pattern); /* MDP_RGB_SRC_UNPACK_PATTERN */
+ outpdw(vg_base + 0x0058, pipe->op_mode);/* MDP_RGB_OP_MODE */
+ outpdw(vg_base + 0x005c, pipe->phasex_step);
+ outpdw(vg_base + 0x0060, pipe->phasey_step);
+
+ if (pipe->op_mode & MDP4_OP_DITHER_EN) {
+ outpdw(vg_base + 0x0068,
+ pipe->r_bit << 4 | pipe->b_bit << 2 | pipe->g_bit);
+ }
+
+ /* 16 bytes-burst x 3 req <= 48 bytes */
+ outpdw(vg_base + 0x1004, 0xc2); /* MDP_VG_FETCH_CFG */
+}
+
+int mdp4_overlay_format2type(uint32 format)
+{
+ switch (format) {
+ case MDP_RGB_565:
+ case MDP_RGB_888:
+ case MDP_BGR_565:
+ case MDP_ARGB_8888:
+ case MDP_RGBA_8888:
+ case MDP_BGRA_8888:
+ return OVERLAY_TYPE_RGB;
+ case MDP_YCRYCB_H2V1:
+ case MDP_Y_CRCB_H2V1:
+ case MDP_Y_CBCR_H2V1:
+ case MDP_Y_CRCB_H2V2:
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CBCR_H2V2_TILE:
+ case MDP_Y_CRCB_H2V2_TILE:
+ return OVERLAY_TYPE_VG;
+ default:
+ return -ERANGE;
+ }
+
+}
+
+#define C3_ALPHA 3 /* alpha */
+#define C2_R_Cr 2 /* R/Cr */
+#define C1_B_Cb 1 /* B/Cb */
+#define C0_G_Y 0 /* G/luma */
+
+int mdp4_overlay_format2pipe(struct mdp4_overlay_pipe *pipe)
+{
+ switch (pipe->src_format) {
+ case MDP_RGB_565:
+ pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+ pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+ pipe->a_bit = 0;
+ pipe->r_bit = 1; /* R, 5 bits */
+ pipe->b_bit = 1; /* B, 5 bits */
+ pipe->g_bit = 2; /* G, 6 bits */
+ pipe->alpha_enable = 0;
+ pipe->unpack_tight = 1;
+ pipe->unpack_align_msb = 0;
+ pipe->unpack_count = 2;
+ pipe->element2 = C2_R_Cr; /* R */
+ pipe->element1 = C0_G_Y; /* G */
+ pipe->element0 = C1_B_Cb; /* B */
+ pipe->bpp = 2; /* 2 bpp */
+ break;
+ case MDP_RGB_888:
+ pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+ pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+ pipe->a_bit = 0;
+ pipe->r_bit = 3; /* R, 8 bits */
+ pipe->b_bit = 3; /* B, 8 bits */
+ pipe->g_bit = 3; /* G, 8 bits */
+ pipe->alpha_enable = 0;
+ pipe->unpack_tight = 1;
+ pipe->unpack_align_msb = 0;
+ pipe->unpack_count = 2;
+ pipe->element2 = C2_R_Cr; /* R */
+ pipe->element1 = C0_G_Y; /* G */
+ pipe->element0 = C1_B_Cb; /* B */
+ pipe->bpp = 3; /* 3 bpp */
+ break;
+ case MDP_BGR_565:
+ pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+ pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+ pipe->a_bit = 0;
+ pipe->r_bit = 1; /* R, 5 bits */
+ pipe->b_bit = 1; /* B, 5 bits */
+ pipe->g_bit = 2; /* G, 6 bits */
+ pipe->alpha_enable = 0;
+ pipe->unpack_tight = 1;
+ pipe->unpack_align_msb = 0;
+ pipe->unpack_count = 2;
+ pipe->element2 = C1_B_Cb; /* B */
+ pipe->element1 = C0_G_Y; /* G */
+ pipe->element0 = C2_R_Cr; /* R */
+ pipe->bpp = 2; /* 2 bpp */
+ break;
+ case MDP_ARGB_8888:
+ pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+ pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+ pipe->a_bit = 3; /* alpha, 4 bits */
+ pipe->r_bit = 3; /* R, 8 bits */
+ pipe->b_bit = 3; /* B, 8 bits */
+ pipe->g_bit = 3; /* G, 8 bits */
+ pipe->alpha_enable = 1;
+ pipe->unpack_tight = 1;
+ pipe->unpack_align_msb = 0;
+ pipe->unpack_count = 3;
+ pipe->element3 = C3_ALPHA; /* alpha */
+ pipe->element2 = C2_R_Cr; /* R */
+ pipe->element1 = C0_G_Y; /* G */
+ pipe->element0 = C1_B_Cb; /* B */
+ pipe->bpp = 4; /* 4 bpp */
+ break;
+ case MDP_RGBA_8888:
+ pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+ pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+ pipe->a_bit = 3; /* alpha, 4 bits */
+ pipe->r_bit = 3; /* R, 8 bits */
+ pipe->b_bit = 3; /* B, 8 bits */
+ pipe->g_bit = 3; /* G, 8 bits */
+ pipe->alpha_enable = 1;
+ pipe->unpack_tight = 1;
+ pipe->unpack_align_msb = 0;
+ pipe->unpack_count = 3;
+ pipe->element3 = C2_R_Cr; /* R */
+ pipe->element2 = C0_G_Y; /* G */
+ pipe->element1 = C1_B_Cb; /* B */
+ pipe->element0 = C3_ALPHA; /* alpha */
+ pipe->bpp = 4; /* 4 bpp */
+ break;
+ case MDP_BGRA_8888:
+ pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+ pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+ pipe->a_bit = 3; /* alpha, 4 bits */
+ pipe->r_bit = 3; /* R, 8 bits */
+ pipe->b_bit = 3; /* B, 8 bits */
+ pipe->g_bit = 3; /* G, 8 bits */
+ pipe->alpha_enable = 1;
+ pipe->unpack_tight = 1;
+ pipe->unpack_align_msb = 0;
+ pipe->unpack_count = 3;
+ pipe->element3 = C1_B_Cb; /* B */
+ pipe->element2 = C0_G_Y; /* G */
+ pipe->element1 = C2_R_Cr; /* R */
+ pipe->element0 = C3_ALPHA; /* alpha */
+ pipe->bpp = 4; /* 4 bpp */
+ break;
+ case MDP_YCRYCB_H2V1:
+ pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+ pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+ pipe->a_bit = 0; /* alpha, 4 bits */
+ pipe->r_bit = 3; /* R, 8 bits */
+ pipe->b_bit = 3; /* B, 8 bits */
+ pipe->g_bit = 3; /* G, 8 bits */
+ pipe->alpha_enable = 0;
+ pipe->unpack_tight = 1;
+ pipe->unpack_align_msb = 0;
+ pipe->unpack_count = 3;
+ pipe->element3 = C0_G_Y; /* G */
+ pipe->element2 = C2_R_Cr; /* R */
+ pipe->element1 = C0_G_Y; /* G */
+ pipe->element0 = C1_B_Cb; /* B */
+ pipe->bpp = 2; /* 2 bpp */
+ pipe->chroma_sample = MDP4_CHROMA_H2V1;
+ break;
+ case MDP_Y_CRCB_H2V1:
+ case MDP_Y_CBCR_H2V1:
+ case MDP_Y_CRCB_H2V2:
+ case MDP_Y_CBCR_H2V2:
+ pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+ pipe->fetch_plane = OVERLAY_PLANE_PSEUDO_PLANAR;
+ pipe->a_bit = 0;
+ pipe->r_bit = 3; /* R, 8 bits */
+ pipe->b_bit = 3; /* B, 8 bits */
+ pipe->g_bit = 3; /* G, 8 bits */
+ pipe->alpha_enable = 0;
+ pipe->unpack_tight = 1;
+ pipe->unpack_align_msb = 0;
+ pipe->unpack_count = 1; /* 2 */
+ pipe->element3 = C0_G_Y; /* not used */
+ pipe->element2 = C0_G_Y; /* not used */
+ if (pipe->src_format == MDP_Y_CRCB_H2V1) {
+ pipe->element1 = C2_R_Cr; /* R */
+ pipe->element0 = C1_B_Cb; /* B */
+ pipe->chroma_sample = MDP4_CHROMA_H2V1;
+ } else if (pipe->src_format == MDP_Y_CBCR_H2V1) {
+ pipe->element1 = C1_B_Cb; /* B */
+ pipe->element0 = C2_R_Cr; /* R */
+ pipe->chroma_sample = MDP4_CHROMA_H2V1;
+ } else if (pipe->src_format == MDP_Y_CRCB_H2V2) {
+ pipe->element1 = C2_R_Cr; /* R */
+ pipe->element0 = C1_B_Cb; /* B */
+ pipe->chroma_sample = MDP4_CHROMA_420;
+ } else if (pipe->src_format == MDP_Y_CBCR_H2V2) {
+ pipe->element1 = C1_B_Cb; /* B */
+ pipe->element0 = C2_R_Cr; /* R */
+ pipe->chroma_sample = MDP4_CHROMA_420;
+ }
+ pipe->bpp = 2; /* 2 bpp */
+ break;
+ case MDP_Y_CBCR_H2V2_TILE:
+ case MDP_Y_CRCB_H2V2_TILE:
+ pipe->frame_format = MDP4_FRAME_FORMAT_VIDEO_SUPERTILE;
+ pipe->fetch_plane = OVERLAY_PLANE_PSEUDO_PLANAR;
+ pipe->a_bit = 0;
+ pipe->r_bit = 3; /* R, 8 bits */
+ pipe->b_bit = 3; /* B, 8 bits */
+ pipe->g_bit = 3; /* G, 8 bits */
+ pipe->alpha_enable = 0;
+ pipe->unpack_tight = 1;
+ pipe->unpack_align_msb = 0;
+ pipe->unpack_count = 1; /* 2 */
+ pipe->element3 = C0_G_Y; /* not used */
+ pipe->element2 = C0_G_Y; /* not used */
+ if (pipe->src_format == MDP_Y_CRCB_H2V2_TILE) {
+ pipe->element1 = C2_R_Cr; /* R */
+ pipe->element0 = C1_B_Cb; /* B */
+ pipe->chroma_sample = MDP4_CHROMA_420;
+ } else if (pipe->src_format == MDP_Y_CBCR_H2V2_TILE) {
+ pipe->element1 = C1_B_Cb; /* B */
+ pipe->element0 = C2_R_Cr; /* R */
+ pipe->chroma_sample = MDP4_CHROMA_420;
+ }
+ pipe->bpp = 2; /* 2 bpp */
+ break;
+ default:
+ /* not likely */
+ return -ERANGE;
+ }
+
+ return 0;
+}
+
+/*
+ * color_key_convert: output with 12 bits color key
+ */
+static uint32 color_key_convert(int start, int num, uint32 color)
+{
+
+ uint32 data;
+
+ data = (color >> start) & ((1 << num) - 1);
+
+ if (num == 5)
+ data = (data << 7) + (data << 2) + (data >> 3);
+ else if (num == 6)
+ data = (data << 6) + data;
+ else /* 8 bits */
+ data = (data << 4) + (data >> 4);
+
+ return data;
+
+}
+
+void transp_color_key(int format, uint32 transp,
+ uint32 *c0, uint32 *c1, uint32 *c2)
+{
+ int b_start, g_start, r_start;
+ int b_num, g_num, r_num;
+
+ switch (format) {
+ case MDP_RGB_565:
+ b_start = 0;
+ g_start = 5;
+ r_start = 11;
+ r_num = 5;
+ g_num = 6;
+ b_num = 5;
+ break;
+ case MDP_RGB_888:
+ case MDP_XRGB_8888:
+ case MDP_ARGB_8888:
+ b_start = 0;
+ g_start = 8;
+ r_start = 16;
+ r_num = 8;
+ g_num = 8;
+ b_num = 8;
+ break;
+ case MDP_BGR_565:
+ b_start = 11;
+ g_start = 5;
+ r_start = 0;
+ r_num = 5;
+ g_num = 6;
+ b_num = 5;
+ break;
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CBCR_H2V1:
+ b_start = 8;
+ g_start = 16;
+ r_start = 0;
+ r_num = 8;
+ g_num = 8;
+ b_num = 8;
+ break;
+ case MDP_Y_CRCB_H2V2:
+ case MDP_Y_CRCB_H2V1:
+ b_start = 0;
+ g_start = 16;
+ r_start = 8;
+ r_num = 8;
+ g_num = 8;
+ b_num = 8;
+ break;
+ default:
+ b_start = 0;
+ g_start = 8;
+ r_start = 16;
+ r_num = 8;
+ g_num = 8;
+ b_num = 8;
+ break;
+ }
+
+ *c0 = color_key_convert(g_start, g_num, transp);
+ *c1 = color_key_convert(b_start, b_num, transp);
+ *c2 = color_key_convert(r_start, r_num, transp);
+}
+
+uint32 mdp4_overlay_format(struct mdp4_overlay_pipe *pipe)
+{
+ uint32 format;
+
+ format = 0;
+
+ if (pipe->solid_fill)
+ format |= MDP4_FORMAT_SOLID_FILL;
+
+ if (pipe->unpack_align_msb)
+ format |= MDP4_FORMAT_UNPACK_ALIGN_MSB;
+
+ if (pipe->unpack_tight)
+ format |= MDP4_FORMAT_UNPACK_TIGHT;
+
+ if (pipe->alpha_enable)
+ format |= MDP4_FORMAT_ALPHA_ENABLE;
+
+ format |= (pipe->unpack_count << 13);
+ format |= ((pipe->bpp - 1) << 9);
+ format |= (pipe->a_bit << 6);
+ format |= (pipe->r_bit << 4);
+ format |= (pipe->b_bit << 2);
+ format |= pipe->g_bit;
+
+ format |= (pipe->frame_format << 29);
+
+ if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) {
+ /* video/graphic */
+ format |= (pipe->fetch_plane << 19);
+ format |= (pipe->chroma_site << 28);
+ format |= (pipe->chroma_sample << 26);
+ }
+
+ return format;
+}
+
+uint32 mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe)
+{
+ return (pipe->element3 << 24) | (pipe->element2 << 16) |
+ (pipe->element1 << 8) | pipe->element0;
+}
+
+void mdp4_overlayproc_cfg(struct mdp4_overlay_pipe *pipe)
+{
+ uint32 data;
+ char *overlay_base;
+
+ if (pipe->mixer_num == MDP4_MIXER1)
+ overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
+ else
+ overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+
+ /* MDP_OVERLAYPROC_CFG */
+ outpdw(overlay_base + 0x0004, 0x01); /* directout */
+ data = pipe->src_height;
+ data <<= 16;
+ data |= pipe->src_width;
+ outpdw(overlay_base + 0x0008, data); /* ROI, height + width */
+ outpdw(overlay_base + 0x000c, pipe->srcp0_addr);
+ outpdw(overlay_base + 0x0010, pipe->srcp0_ystride);
+ outpdw(overlay_base + 0x0014, 0x4); /* GC_LUT_EN, 888 */
+}
+
+int mdp4_overlay_active(int mixer)
+{
+ uint32 data, mask, i;
+ int p1, p2;
+
+ data = inpdw(MDP_BASE + 0x10100);
+ p1 = 0;
+ p2 = 0;
+ for (i = 0; i < 8; i++) {
+ mask = data & 0x0f;
+ if (mask) {
+ if (mask <= 4)
+ p1++;
+ else
+ p2++;
+ }
+ data >>= 4;
+ }
+
+ if (mixer)
+ return p2;
+ else
+ return p1;
+}
+
+void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe)
+{
+ uint32 data, mask, snum, stage, mixer;
+
+ stage = pipe->mixer_stage;
+ mixer = pipe->mixer_num;
+
+ /* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1 */
+ data = inpdw(MDP_BASE + 0x10100);
+
+ if (mixer == MDP4_MIXER1)
+ stage += 8;
+
+ if (pipe->pipe_type == OVERLAY_TYPE_VG) {/* VG1 and VG2 */
+ snum = 0;
+ snum += (4 * pipe->pipe_num);
+ } else {
+ snum = 8;
+ snum += (4 * pipe->pipe_num); /* RGB1 and RGB2 */
+ }
+
+ mask = 0x0f;
+ mask <<= snum;
+ stage <<= snum;
+ data &= ~mask; /* clear old bits */
+
+ data |= stage;
+
+ outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */
+
+ data = inpdw(MDP_BASE + 0x10100);
+
+ ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = pipe; /* keep it */
+}
+
+void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe)
+{
+ uint32 data, mask, snum, stage, mixer;
+
+ stage = pipe->mixer_stage;
+ mixer = pipe->mixer_num;
+
+ if (pipe != ctrl->stage[mixer][stage]) /* not runing */
+ return;
+
+ /* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1 */
+ data = inpdw(MDP_BASE + 0x10100);
+
+ if (mixer == MDP4_MIXER1)
+ stage += 8;
+
+ if (pipe->pipe_type == OVERLAY_TYPE_VG) {/* VG1 and VG2 */
+ snum = 0;
+ snum += (4 * pipe->pipe_num);
+ } else {
+ snum = 8;
+ snum += (4 * pipe->pipe_num); /* RGB1 and RGB2 */
+ }
+
+ mask = 0x0f;
+ mask <<= snum;
+ data &= ~mask; /* clear old bits */
+
+ outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */
+
+ data = inpdw(MDP_BASE + 0x10100);
+
+ ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL; /* clear it */
+}
+
+void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe)
+{
+ unsigned char *overlay_base;
+ uint32 c0, c1, c2, blend_op;
+ int off;
+
+ if (pipe->mixer_num) /* mixer number, /dev/fb0, /dev/fb1 */
+ overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
+ else
+ overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+
+ /* stage 0 to stage 2 */
+ off = 0x20 * (pipe->mixer_stage - MDP4_MIXER_STAGE0);
+
+ blend_op = 0;
+ if (pipe->alpha_enable) /* ARGB */
+ blend_op = MDP4_BLEND_FG_ALPHA_FG_PIXEL |
+ MDP4_BLEND_BG_ALPHA_FG_PIXEL;
+ else
+ blend_op = (MDP4_BLEND_BG_ALPHA_BG_CONST |
+ MDP4_BLEND_FG_ALPHA_FG_CONST);
+
+
+ if (pipe->alpha_enable == 0) { /* not ARGB */
+ if (pipe->is_fg) {
+ outpdw(overlay_base + off + 0x108, pipe->alpha);
+ outpdw(overlay_base + off + 0x10c, 0xff - pipe->alpha);
+ } else {
+ outpdw(overlay_base + off + 0x108, 0xff - pipe->alpha);
+ outpdw(overlay_base + off + 0x10c, pipe->alpha);
+ }
+ }
+
+ if (pipe->transp != MDP_TRANSP_NOP) {
+ transp_color_key(pipe->src_format, pipe->transp, &c0, &c1, &c2);
+ if (pipe->is_fg) {
+ blend_op |= MDP4_BLEND_FG_TRANSP_EN; /* Fg blocked */
+ /* lower limit */
+ if (c0 > 0x10)
+ c0 -= 0x10;
+ if (c1 > 0x10)
+ c1 -= 0x10;
+ if (c2 > 0x10)
+ c2 -= 0x10;
+ outpdw(overlay_base + off + 0x110,
+ (c1 << 16 | c0));/* low */
+ outpdw(overlay_base + off + 0x114, c2);/* low */
+ /* upper limit */
+ if ((c0 + 0x20) < 0x0fff)
+ c0 += 0x20;
+ else
+ c0 = 0x0fff;
+ if ((c1 + 0x20) < 0x0fff)
+ c1 += 0x20;
+ else
+ c1 = 0x0fff;
+ if ((c2 + 0x20) < 0x0fff)
+ c2 += 0x20;
+ else
+ c2 = 0x0fff;
+ outpdw(overlay_base + off + 0x118,
+ (c1 << 16 | c0));/* high */
+ outpdw(overlay_base + off + 0x11c, c2);/* high */
+ } else {
+ blend_op |= MDP4_BLEND_BG_TRANSP_EN; /* bg blocked */
+ /* lower limit */
+ if (c0 > 0x10)
+ c0 -= 0x10;
+ if (c1 > 0x10)
+ c1 -= 0x10;
+ if (c2 > 0x10)
+ c2 -= 0x10;
+ outpdw(overlay_base + 0x180,
+ (c1 << 16 | c0));/* low */
+ outpdw(overlay_base + 0x184, c2);/* low */
+ /* upper limit */
+ if ((c0 + 0x20) < 0x0fff)
+ c0 += 0x20;
+ else
+ c0 = 0x0fff;
+ if ((c1 + 0x20) < 0x0fff)
+ c1 += 0x20;
+ else
+ c1 = 0x0fff;
+ if ((c2 + 0x20) < 0x0fff)
+ c2 += 0x20;
+ else
+ c2 = 0x0fff;
+ outpdw(overlay_base + 0x188,
+ (c1 << 16 | c0));/* high */
+ outpdw(overlay_base + 0x18c, c2);/* high */
+ }
+ }
+ outpdw(overlay_base + off + 0x104, blend_op);
+}
+
+void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all)
+{
+ uint32 bits = 0;
+
+ if (pipe->mixer_num == MDP4_MIXER1)
+ bits |= 0x02;
+ else
+ bits |= 0x01;
+
+ if (all) {
+ if (pipe->pipe_type == OVERLAY_TYPE_RGB) {
+ if (pipe->pipe_num == OVERLAY_PIPE_RGB2)
+ bits |= 0x20;
+ else
+ bits |= 0x10;
+ } else {
+ if (pipe->pipe_num == OVERLAY_PIPE_VG2)
+ bits |= 0x08;
+ else
+ bits |= 0x04;
+ }
+ }
+
+ outpdw(MDP_BASE + 0x18000, bits); /* MDP_OVERLAY_REG_FLUSH */
+
+ while (inpdw(MDP_BASE + 0x18000) & bits) /* self clear when complete */
+ ;
+}
+
+struct mdp4_overlay_pipe *mdp4_overlay_ndx2pipe(int ndx)
+{
+ struct mdp4_overlay_pipe *pipe;
+
+ if (ndx == 0 || ndx >= MDP4_MAX_OVERLAY_PIPE)
+ return NULL;
+
+ pipe = &ctrl->plist[ndx - 1]; /* ndx start from 1 */
+
+ if (pipe->pipe_ndx == 0)
+ return NULL;
+
+ return pipe;
+}
+
+struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(void)
+{
+ int i;
+ struct mdp4_overlay_pipe *pipe;
+
+ pipe = &ctrl->plist[0];
+ for (i = 0; i < MDP4_MAX_OVERLAY_PIPE; i++) {
+ if (pipe->pipe_ndx == 0) {
+ pipe->pipe_ndx = i + 1; /* start from 1 */
+ init_completion(&pipe->comp);
+ printk(KERN_INFO "mdp4_overlay_pipe_alloc: pipe=%x ndx=%d\n",
+ (int)pipe, pipe->pipe_ndx);
+ return pipe;
+ }
+ pipe++;
+ }
+
+ return NULL;
+}
+
+
+void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe)
+{
+ printk(KERN_INFO "mdp4_overlay_pipe_free: pipe=%x ndx=%d\n",
+ (int)pipe, pipe->pipe_ndx);
+ memset(pipe, 0, sizeof(*pipe));
+}
+
+static int get_pipe_num(int ptype, int stage)
+{
+ if (ptype == OVERLAY_TYPE_RGB) {
+ if (stage == MDP4_MIXER_STAGE_BASE)
+ return OVERLAY_PIPE_RGB1;
+ else
+ return OVERLAY_PIPE_RGB2;
+ } else {
+ if (stage == MDP4_MIXER_STAGE0)
+ return OVERLAY_PIPE_VG1;
+ else
+ return OVERLAY_PIPE_VG2;
+ }
+}
+
+int mdp4_overlay_req_check(uint32 id, uint32 z_order, uint32 mixer)
+{
+ struct mdp4_overlay_pipe *pipe;
+
+ pipe = ctrl->stage[mixer][z_order];
+
+ if (pipe == NULL)
+ return 0;
+
+ if (pipe->pipe_ndx == id) /* same req, recycle */
+ return 0;
+
+ return -EPERM;
+}
+
+static int mdp4_overlay_req2pipe(struct mdp_overlay *req, int mixer,
+ struct mdp4_overlay_pipe **ppipe)
+{
+ struct mdp4_overlay_pipe *pipe;
+ int ret, ptype;
+
+ if (mixer >= MDP4_MAX_MIXER) {
+ printk(KERN_ERR "mpd_overlay_req2pipe: mixer out of range!\n");
+ return -ERANGE;
+ }
+
+ if (req->z_order < 0 || req->z_order > 2) {
+ printk(KERN_ERR "mpd_overlay_req2pipe: z_order=%d out of range!\n",
+ req->z_order);
+ return -ERANGE;
+ }
+
+ if (req->src_rect.h == 0 || req->src_rect.w == 0) {
+ printk(KERN_ERR "mpd_overlay_req2pipe: src img of zero size!\n");
+ return -EINVAL;
+ }
+
+ ret = mdp4_overlay_req_check(req->id, req->z_order, mixer);
+ if (ret < 0)
+ return ret;
+
+ ptype = mdp4_overlay_format2type(req->src.format);
+ if (ptype < 0)
+ return ptype;
+
+ if (req->id == MSMFB_NEW_REQUEST) /* new request */
+ pipe = mdp4_overlay_pipe_alloc();
+ else
+ pipe = mdp4_overlay_ndx2pipe(req->id);
+
+ if (pipe == NULL)
+ return -ENOMEM;
+
+ pipe->src_format = req->src.format;
+ ret = mdp4_overlay_format2pipe(pipe);
+
+ if (ret < 0)
+ return ret;
+
+ /*
+ * base layer == 1, reserved for frame buffer
+ * zorder 0 == stage 0 == 2
+ * zorder 1 == stage 1 == 3
+ * zorder 2 == stage 2 == 4
+ */
+ if (req->id == MSMFB_NEW_REQUEST) { /* new request */
+ pipe->mixer_stage = req->z_order + MDP4_MIXER_STAGE0;
+ pipe->pipe_type = ptype;
+ pipe->pipe_num = get_pipe_num(ptype, pipe->mixer_stage);
+ printk(KERN_INFO "mpd4_overlay_req2pipe: zorder=%d pipe_num=%d\n",
+ req->z_order, pipe->pipe_num);
+ }
+
+ pipe->src_width = req->src.width & 0x07ff; /* source img width */
+ pipe->src_height = req->src.height & 0x07ff; /* source img height */
+ pipe->src_h = req->src_rect.h & 0x07ff;
+ pipe->src_w = req->src_rect.w & 0x07ff;
+ pipe->src_y = req->src_rect.y & 0x07ff;
+ pipe->src_x = req->src_rect.x & 0x07ff;
+ pipe->dst_h = req->dst_rect.h & 0x07ff;
+ pipe->dst_w = req->dst_rect.w & 0x07ff;
+ pipe->dst_y = req->dst_rect.y & 0x07ff;
+ pipe->dst_x = req->dst_rect.x & 0x07ff;
+
+ if (req->flags & MDP_FLIP_LR)
+ pipe->op_mode |= MDP4_OP_FLIP_LR;
+
+ if (req->flags & MDP_FLIP_UD)
+ pipe->op_mode |= MDP4_OP_FLIP_UD;
+
+ if (req->flags & MDP_DITHER)
+ pipe->op_mode |= MDP4_OP_DITHER_EN;
+
+ if (req->flags & MDP_DEINTERLACE)
+ pipe->op_mode |= MDP4_OP_DEINT_ODD_REF;
+
+ pipe->is_fg = req->is_fg;/* control alpha and color key */
+
+ pipe->alpha = req->alpha & 0x0ff;
+
+ pipe->transp = req->transp_mask;
+
+ *ppipe = pipe;
+
+ return 0;
+}
+
+int get_img(struct msmfb_data *img, struct fb_info *info,
+ unsigned long *start, unsigned long *len, struct file **pp_file)
+{
+ int put_needed, ret = 0;
+ struct file *file;
+#ifdef CONFIG_ANDROID_PMEM
+ unsigned long vstart;
+#endif
+
+#ifdef CONFIG_ANDROID_PMEM
+ if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file))
+ return 0;
+#endif
+ file = fget_light(img->memory_id, &put_needed);
+ if (file == NULL)
+ return -1;
+
+ if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
+ *start = info->fix.smem_start;
+ *len = info->fix.smem_len;
+ *pp_file = file;
+ } else {
+ ret = -1;
+ fput_light(file, put_needed);
+ }
+ return ret;
+}
+int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req)
+{
+ struct mdp4_overlay_pipe *pipe;
+
+ pipe = mdp4_overlay_ndx2pipe(req->id);
+ if (pipe == NULL)
+ return -ENODEV;
+
+ *req = pipe->req_data;
+
+ return 0;
+}
+
+int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ int ret, mixer;
+ struct mdp4_overlay_pipe *pipe;
+ int lcdc;
+
+ if (mfd == NULL)
+ return -ENODEV;
+
+ if (req->src.format == MDP_FB_FORMAT)
+ req->src.format = mfd->fb_imgType;
+
+ if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
+ return -EINTR;
+
+ mixer = info->node; /* minor number of char device */
+
+ ret = mdp4_overlay_req2pipe(req, mixer, &pipe);
+ if (ret < 0) {
+ mutex_unlock(&mfd->dma->ov_mutex);
+ return ret;
+ }
+
+ lcdc = inpdw(MDP_BASE + 0xc0000);
+
+ if (lcdc == 0) { /* mddi */
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ }
+
+ /* return id back to user */
+ req->id = pipe->pipe_ndx; /* pipe_ndx start from 1 */
+ pipe->req_data = *req; /* keep original req */
+
+ mutex_unlock(&mfd->dma->ov_mutex);
+
+ return 0;
+}
+
+int mdp4_overlay_unset(struct fb_info *info, int ndx)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ struct mdp4_overlay_pipe *pipe;
+ int lcdc;
+
+ if (mfd == NULL)
+ return -ENODEV;
+
+ if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
+ return -EINTR;
+
+ pipe = mdp4_overlay_ndx2pipe(ndx);
+
+ if (pipe == NULL) {
+ mutex_unlock(&mfd->dma->ov_mutex);
+ return -ENODEV;
+ }
+
+ lcdc = inpdw(MDP_BASE + 0xc0000);
+
+ mdp4_mixer_stage_down(pipe);
+
+ if (lcdc == 0) { /* mddi */
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ }
+
+ if (lcdc) /* LCDC mode */
+ mdp4_overlay_reg_flush(pipe, 0);
+
+ mdp4_overlay_pipe_free(pipe);
+
+ if (lcdc == 0) { /* mddi */
+ mdp4_mddi_overlay_restore();
+ }
+
+ mutex_unlock(&mfd->dma->ov_mutex);
+
+ return 0;
+}
+
+struct tile_desc {
+ uint32 width; /* tile's width */
+ uint32 height; /* tile's height */
+ uint32 row_tile_w; /* tiles per row's width */
+ uint32 row_tile_h; /* tiles per row's height */
+};
+
+void tile_samsung(struct tile_desc *tp)
+{
+ /*
+ * each row of samsung tile consists of two tiles in height
+ * and two tiles in width which means width should align to
+ * 64 x 2 bytes and height should align to 32 x 2 bytes.
+ * video decoder generate two tiles in width and one tile
+ * in height which ends up height align to 32 X 1 bytes.
+ */
+ tp->width = 64; /* 64 bytes */
+ tp->row_tile_w = 2; /* 2 tiles per row's width */
+ tp->height = 32; /* 32 bytes */
+ tp->row_tile_h = 1; /* 1 tiles per row's height */
+}
+
+uint32 tile_mem_size(struct mdp4_overlay_pipe *pipe, struct tile_desc *tp)
+{
+ uint32 tile_w, tile_h;
+ uint32 row_num_w, row_num_h;
+
+
+ tile_w = tp->width * tp->row_tile_w;
+ tile_h = tp->height * tp->row_tile_h;
+
+ row_num_w = (pipe->src_width + tile_w - 1) / tile_w;
+ row_num_h = (pipe->src_height + tile_h - 1) / tile_h;
+
+ return row_num_w * row_num_h * tile_w * tile_h;
+}
+
+int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req,
+ struct file **pp_src_file)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ struct msmfb_data *img;
+ struct mdp4_overlay_pipe *pipe;
+ ulong start, addr;
+ ulong len = 0;
+ struct file *p_src_file = 0;
+ int lcdc;
+
+ if (mfd == NULL)
+ return -ENODEV;
+
+ pipe = mdp4_overlay_ndx2pipe(req->id);
+ if (pipe == NULL)
+ return -ENODEV;
+
+ if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
+ return -EINTR;
+
+ img = &req->data;
+ get_img(img, info, &start, &len, &p_src_file);
+ if (len == 0) {
+ mutex_unlock(&mfd->dma->ov_mutex);
+ printk(KERN_ERR "mdp_overlay_play: could not retrieve"
+ " image from memory\n");
+ return -1;
+ }
+ *pp_src_file = p_src_file;
+
+ addr = start + img->offset;
+ pipe->srcp0_addr = addr;
+ pipe->srcp0_ystride = pipe->src_width * pipe->bpp;
+
+ if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) {
+ if (pipe->frame_format == MDP4_FRAME_FORMAT_VIDEO_SUPERTILE) {
+ struct tile_desc tile;
+
+ tile_samsung(&tile);
+ pipe->srcp1_addr = addr + tile_mem_size(pipe, &tile);
+ } else
+ pipe->srcp1_addr = addr +
+ pipe->src_width * pipe->src_height;
+
+ pipe->srcp0_ystride = pipe->src_width;
+ pipe->srcp1_ystride = pipe->src_width;
+ }
+
+ lcdc = inpdw(MDP_BASE + 0xc0000);
+ lcdc &= 0x01; /* LCDC mode */
+
+ if (pipe->pipe_type == OVERLAY_TYPE_VG)
+ mdp4_overlay_vg_setup(pipe); /* video/graphic pipe */
+ else
+ mdp4_overlay_rgb_setup(pipe); /* rgb pipe */
+
+ mdp4_mixer_blend_setup(pipe);
+ mdp4_mixer_stage_up(pipe);
+
+ if (lcdc) { /* LCDC mode */
+ mdp4_overlay_reg_flush(pipe, 1);
+ }
+
+ if (lcdc) { /* LCDC mode */
+ if (pipe->mixer_stage != MDP4_MIXER_STAGE_BASE) { /* done */
+ mutex_unlock(&mfd->dma->ov_mutex);
+ return 0;
+ }
+ }
+
+ if (lcdc == 0) { /* MDDI mode */
+#ifdef MDP4_NONBLOCKING
+ if (mfd->panel_power_on)
+#else
+ if (!mfd->dma->busy && mfd->panel_power_on)
+#endif
+ mdp4_mddi_overlay_kickoff(mfd, pipe);
+ }
+
+ mutex_unlock(&mfd->dma->ov_mutex);
+
+ return 0;
+}
diff --git a/drivers/staging/msm/mdp4_overlay_lcdc.c b/drivers/staging/msm/mdp4_overlay_lcdc.c
new file mode 100644
index 0000000..a6ab8ec
--- /dev/null
+++ b/drivers/staging/msm/mdp4_overlay_lcdc.c
@@ -0,0 +1,313 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+#ifdef CONFIG_FB_MSM_MDP40
+#define LCDC_BASE 0xC0000
+#else
+#define LCDC_BASE 0xE0000
+#endif
+
+int first_pixel_start_x;
+int first_pixel_start_y;
+
+static struct mdp4_overlay_pipe *lcdc_pipe;
+
+int mdp_lcdc_on(struct platform_device *pdev)
+{
+ int lcdc_width;
+ int lcdc_height;
+ int lcdc_bpp;
+ int lcdc_border_clr;
+ int lcdc_underflow_clr;
+ int lcdc_hsync_skew;
+
+ int hsync_period;
+ int hsync_ctrl;
+ int vsync_period;
+ int display_hctl;
+ int display_v_start;
+ int display_v_end;
+ int active_hctl;
+ int active_h_start;
+ int active_h_end;
+ int active_v_start;
+ int active_v_end;
+ int ctrl_polarity;
+ int h_back_porch;
+ int h_front_porch;
+ int v_back_porch;
+ int v_front_porch;
+ int hsync_pulse_width;
+ int vsync_pulse_width;
+ int hsync_polarity;
+ int vsync_polarity;
+ int data_en_polarity;
+ int hsync_start_x;
+ int hsync_end_x;
+ uint8 *buf;
+ int bpp, ptype;
+ uint32 format;
+ struct fb_info *fbi;
+ struct fb_var_screeninfo *var;
+ struct msm_fb_data_type *mfd;
+ struct mdp4_overlay_pipe *pipe;
+ int ret;
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ fbi = mfd->fbi;
+ var = &fbi->var;
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf += fbi->var.xoffset * bpp +
+ fbi->var.yoffset * fbi->fix.line_length;
+
+ if (bpp == 2)
+ format = MDP_RGB_565;
+ else if (bpp == 3)
+ format = MDP_RGB_888;
+ else
+ format = MDP_ARGB_8888;
+
+
+ if (lcdc_pipe == NULL) {
+ ptype = mdp4_overlay_format2type(format);
+ pipe = mdp4_overlay_pipe_alloc();
+ pipe->pipe_type = ptype;
+ /* use RGB1 pipe */
+ pipe->pipe_num = OVERLAY_PIPE_RGB1;
+ pipe->mixer_stage = MDP4_MIXER_STAGE_BASE;
+ pipe->mixer_num = MDP4_MIXER0;
+ pipe->src_format = format;
+ mdp4_overlay_format2pipe(pipe);
+
+ lcdc_pipe = pipe; /* keep it */
+ } else {
+ pipe = lcdc_pipe;
+ }
+
+ pipe->src_height = fbi->var.yres;
+ pipe->src_width = fbi->var.xres;
+ pipe->src_h = fbi->var.yres;
+ pipe->src_w = fbi->var.xres;
+ pipe->src_y = 0;
+ pipe->src_x = 0;
+ pipe->srcp0_addr = (uint32) buf;
+ pipe->srcp0_ystride = fbi->fix.line_length;
+
+ mdp4_overlay_dmap_xy(pipe);
+ mdp4_overlay_dmap_cfg(mfd, 1);
+
+ mdp4_overlay_rgb_setup(pipe);
+
+ mdp4_mixer_stage_up(pipe);
+
+ mdp4_overlayproc_cfg(pipe);
+
+ /*
+ * LCDC timing setting
+ */
+ h_back_porch = var->left_margin;
+ h_front_porch = var->right_margin;
+ v_back_porch = var->upper_margin;
+ v_front_porch = var->lower_margin;
+ hsync_pulse_width = var->hsync_len;
+ vsync_pulse_width = var->vsync_len;
+ lcdc_border_clr = mfd->panel_info.lcdc.border_clr;
+ lcdc_underflow_clr = mfd->panel_info.lcdc.underflow_clr;
+ lcdc_hsync_skew = mfd->panel_info.lcdc.hsync_skew;
+
+ lcdc_width = mfd->panel_info.xres;
+ lcdc_height = mfd->panel_info.yres;
+ lcdc_bpp = mfd->panel_info.bpp;
+
+ hsync_period =
+ hsync_pulse_width + h_back_porch + lcdc_width + h_front_porch;
+ hsync_ctrl = (hsync_period << 16) | hsync_pulse_width;
+ hsync_start_x = hsync_pulse_width + h_back_porch;
+ hsync_end_x = hsync_period - h_front_porch - 1;
+ display_hctl = (hsync_end_x << 16) | hsync_start_x;
+
+ vsync_period =
+ (vsync_pulse_width + v_back_porch + lcdc_height +
+ v_front_porch) * hsync_period;
+ display_v_start =
+ (vsync_pulse_width + v_back_porch) * hsync_period + lcdc_hsync_skew;
+ display_v_end =
+ vsync_period - (v_front_porch * hsync_period) + lcdc_hsync_skew - 1;
+
+ if (lcdc_width != var->xres) {
+ active_h_start = hsync_start_x + first_pixel_start_x;
+ active_h_end = active_h_start + var->xres - 1;
+ active_hctl =
+ ACTIVE_START_X_EN | (active_h_end << 16) | active_h_start;
+ } else {
+ active_hctl = 0;
+ }
+
+ if (lcdc_height != var->yres) {
+ active_v_start =
+ display_v_start + first_pixel_start_y * hsync_period;
+ active_v_end = active_v_start + (var->yres) * hsync_period - 1;
+ active_v_start |= ACTIVE_START_Y_EN;
+ } else {
+ active_v_start = 0;
+ active_v_end = 0;
+ }
+
+
+#ifdef CONFIG_FB_MSM_MDP40
+ hsync_polarity = 1;
+ vsync_polarity = 1;
+ lcdc_underflow_clr |= 0x80000000; /* enable recovery */
+#else
+ hsync_polarity = 0;
+ vsync_polarity = 0;
+#endif
+ data_en_polarity = 0;
+
+ ctrl_polarity =
+ (data_en_polarity << 2) | (vsync_polarity << 1) | (hsync_polarity);
+
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0x4, hsync_ctrl);
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0x8, vsync_period);
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0xc, vsync_pulse_width * hsync_period);
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0x10, display_hctl);
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0x14, display_v_start);
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0x18, display_v_end);
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0x28, lcdc_border_clr);
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0x2c, lcdc_underflow_clr);
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0x30, lcdc_hsync_skew);
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0x38, ctrl_polarity);
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0x1c, active_hctl);
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0x20, active_v_start);
+ MDP_OUTP(MDP_BASE + LCDC_BASE + 0x24, active_v_end);
+
+ ret = panel_next_on(pdev);
+ if (ret == 0) {
+ /* enable LCDC block */
+ MDP_OUTP(MDP_BASE + LCDC_BASE, 1);
+ mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ }
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ return ret;
+}
+
+int mdp_lcdc_off(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct mdp4_overlay_pipe *pipe;
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ MDP_OUTP(MDP_BASE + LCDC_BASE, 0);
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ ret = panel_next_off(pdev);
+
+ /* delay to make sure the last frame finishes */
+ mdelay(100);
+
+ /* dis-engage rgb0 from mixer */
+ pipe = lcdc_pipe;
+ mdp4_mixer_stage_down(pipe);
+
+ return ret;
+}
+
+/*
+ * mdp4_overlay0_done_lcdc: called from isr
+ */
+void mdp4_overlay0_done_lcdc()
+{
+ complete(&lcdc_pipe->comp);
+}
+
+void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd)
+{
+ struct fb_info *fbi = mfd->fbi;
+ uint8 *buf;
+ int bpp;
+ unsigned long flag;
+ struct mdp4_overlay_pipe *pipe;
+
+ if (!mfd->panel_power_on)
+ return;
+
+ /* no need to power on cmd block since it's lcdc mode */
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf += fbi->var.xoffset * bpp +
+ fbi->var.yoffset * fbi->fix.line_length;
+
+ mutex_lock(&mfd->dma->ov_mutex);
+
+ pipe = lcdc_pipe;
+ pipe->srcp0_addr = (uint32) buf;
+ mdp4_overlay_rgb_setup(pipe);
+ mdp4_overlay_reg_flush(pipe, 1); /* rgb1 and mixer0 */
+
+ /* enable irq */
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ mdp_enable_irq(MDP_OVERLAY0_TERM);
+ INIT_COMPLETION(lcdc_pipe->comp);
+ mfd->dma->waiting = TRUE;
+ outp32(MDP_INTR_CLEAR, INTR_OVERLAY0_DONE);
+ mdp_intr_mask |= INTR_OVERLAY0_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ wait_for_completion_killable(&lcdc_pipe->comp);
+ mdp_disable_irq(MDP_OVERLAY0_TERM);
+
+ mutex_unlock(&mfd->dma->ov_mutex);
+}
diff --git a/drivers/staging/msm/mdp4_overlay_mddi.c b/drivers/staging/msm/mdp4_overlay_mddi.c
new file mode 100644
index 0000000..be1b287
--- /dev/null
+++ b/drivers/staging/msm/mdp4_overlay_mddi.c
@@ -0,0 +1,254 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+static struct mdp4_overlay_pipe *mddi_pipe;
+static struct mdp4_overlay_pipe *pending_pipe;
+static struct msm_fb_data_type *mddi_mfd;
+
+#define WHOLESCREEN
+
+void mdp4_overlay_update_lcd(struct msm_fb_data_type *mfd)
+{
+ MDPIBUF *iBuf = &mfd->ibuf;
+ uint8 *src;
+ int bpp, ptype;
+ uint32 format;
+ uint32 mddi_ld_param;
+ uint16 mddi_vdo_packet_reg;
+ struct mdp4_overlay_pipe *pipe;
+
+ if (mfd->key != MFD_KEY)
+ return;
+
+ mddi_mfd = mfd; /* keep it */
+
+ bpp = iBuf->bpp;
+
+ if (bpp == 2)
+ format = MDP_RGB_565;
+ else if (bpp == 3)
+ format = MDP_RGB_888;
+ else
+ format = MDP_ARGB_8888;
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ if (mddi_pipe == NULL) {
+ ptype = mdp4_overlay_format2type(format);
+ pipe = mdp4_overlay_pipe_alloc();
+ pipe->pipe_type = ptype;
+ /* use RGB1 pipe */
+ pipe->pipe_num = OVERLAY_PIPE_RGB1;
+ pipe->mixer_num = MDP4_MIXER0;
+ pipe->src_format = format;
+ mdp4_overlay_format2pipe(pipe);
+
+ mddi_pipe = pipe; /* keep it */
+
+ mddi_ld_param = 0;
+ mddi_vdo_packet_reg = mfd->panel_info.mddi.vdopkt;
+
+ if (mfd->panel_info.type == MDDI_PANEL) {
+ if (mfd->panel_info.pdest == DISPLAY_1)
+ mddi_ld_param = 0;
+ else
+ mddi_ld_param = 1;
+ } else {
+ mddi_ld_param = 2;
+ }
+
+ MDP_OUTP(MDP_BASE + 0x00090, mddi_ld_param);
+ MDP_OUTP(MDP_BASE + 0x00094,
+ (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg);
+ } else {
+ pipe = mddi_pipe;
+ }
+
+
+ src = (uint8 *) iBuf->buf;
+
+#ifdef WHOLESCREEN
+ {
+ struct fb_info *fbi;
+
+ fbi = mfd->fbi;
+ pipe->src_height = fbi->var.yres;
+ pipe->src_width = fbi->var.xres;
+ pipe->src_h = fbi->var.yres;
+ pipe->src_w = fbi->var.xres;
+ pipe->src_y = 0;
+ pipe->src_x = 0;
+ pipe->dst_h = fbi->var.yres;
+ pipe->dst_w = fbi->var.xres;
+ pipe->dst_y = 0;
+ pipe->dst_x = 0;
+ pipe->srcp0_addr = (uint32)src;
+ pipe->srcp0_ystride = fbi->var.xres_virtual * bpp;
+ }
+
+#else
+ if (mdp4_overlay_active(MDP4_MIXER0)) {
+ struct fb_info *fbi;
+
+ fbi = mfd->fbi;
+ pipe->src_height = fbi->var.yres;
+ pipe->src_width = fbi->var.xres;
+ pipe->src_h = fbi->var.yres;
+ pipe->src_w = fbi->var.xres;
+ pipe->src_y = 0;
+ pipe->src_x = 0;
+ pipe->dst_h = fbi->var.yres;
+ pipe->dst_w = fbi->var.xres;
+ pipe->dst_y = 0;
+ pipe->dst_x = 0;
+ pipe->srcp0_addr = (uint32) src;
+ pipe->srcp0_ystride = fbi->var.xres_virtual * bpp;
+ } else {
+ /* starting input address */
+ src += (iBuf->dma_x + iBuf->dma_y * iBuf->ibuf_width) * bpp;
+
+ pipe->src_height = iBuf->dma_h;
+ pipe->src_width = iBuf->dma_w;
+ pipe->src_h = iBuf->dma_h;
+ pipe->src_w = iBuf->dma_w;
+ pipe->src_y = 0;
+ pipe->src_x = 0;
+ pipe->dst_h = iBuf->dma_h;
+ pipe->dst_w = iBuf->dma_w;
+ pipe->dst_y = iBuf->dma_y;
+ pipe->dst_x = iBuf->dma_x;
+ pipe->srcp0_addr = (uint32) src;
+ pipe->srcp0_ystride = iBuf->ibuf_width * bpp;
+ }
+#endif
+
+ pipe->mixer_stage = MDP4_MIXER_STAGE_BASE;
+
+ mdp4_overlay_rgb_setup(pipe);
+
+ mdp4_mixer_stage_up(pipe);
+
+ mdp4_overlayproc_cfg(pipe);
+
+ mdp4_overlay_dmap_xy(pipe);
+
+ mdp4_overlay_dmap_cfg(mfd, 0);
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+}
+
+/*
+ * mdp4_overlay0_done_mddi: called from isr
+ */
+void mdp4_overlay0_done_mddi()
+{
+ if (pending_pipe)
+ complete(&pending_pipe->comp);
+}
+
+void mdp4_mddi_overlay_restore(void)
+{
+ /* mutex holded by caller */
+ mdp4_overlay_update_lcd(mddi_mfd);
+ mdp4_mddi_overlay_kickoff(mddi_mfd, mddi_pipe);
+}
+
+void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+#ifdef MDP4_NONBLOCKING
+ unsigned long flag;
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ if (mfd->dma->busy == TRUE) {
+ INIT_COMPLETION(pipe->comp);
+ pending_pipe = pipe;
+ }
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+ if (pending_pipe != NULL) {
+ /* wait until DMA finishes the current job */
+ wait_for_completion_killable(&pipe->comp);
+ pending_pipe = NULL;
+ }
+ down(&mfd->sem);
+ mdp_enable_irq(MDP_OVERLAY0_TERM);
+ mfd->dma->busy = TRUE;
+ /* start OVERLAY pipe */
+ mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd);
+ up(&mfd->sem);
+#else
+ down(&mfd->sem);
+ mdp_enable_irq(MDP_OVERLAY0_TERM);
+ mfd->dma->busy = TRUE;
+ INIT_COMPLETION(pipe->comp);
+ pending_pipe = pipe;
+
+ /* start OVERLAY pipe */
+ mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd);
+ up(&mfd->sem);
+
+ /* wait until DMA finishes the current job */
+ wait_for_completion_killable(&pipe->comp);
+ mdp_disable_irq(MDP_OVERLAY0_TERM);
+#endif
+
+}
+
+void mdp4_mddi_overlay(struct msm_fb_data_type *mfd)
+{
+ mutex_lock(&mfd->dma->ov_mutex);
+
+ if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
+ mdp4_overlay_update_lcd(mfd);
+
+ mdp4_mddi_overlay_kickoff(mfd, mddi_pipe);
+
+ /* signal if pan function is waiting for the update completion */
+ if (mfd->pan_waiting) {
+ mfd->pan_waiting = FALSE;
+ complete(&mfd->pan_comp);
+ }
+ }
+
+ mutex_unlock(&mfd->dma->ov_mutex);
+}
diff --git a/drivers/staging/msm/mdp4_util.c b/drivers/staging/msm/mdp4_util.c
new file mode 100644
index 0000000..fd97f52
--- /dev/null
+++ b/drivers/staging/msm/mdp4_util.c
@@ -0,0 +1,1686 @@
+
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
+#include <linux/clk.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+void mdp4_sw_reset(ulong bits)
+{
+ bits &= 0x1f; /* 5 bits */
+ outpdw(MDP_BASE + 0x001c, bits); /* MDP_SW_RESET */
+
+ while (inpdw(MDP_BASE + 0x001c) & bits) /* self clear when complete */
+ ;
+ MSM_FB_INFO("mdp4_sw_reset: 0x%x\n", (int)bits);
+}
+
+void mdp4_overlay_cfg(int overlayer, int blt_mode, int refresh, int direct_out)
+{
+ ulong bits = 0;
+
+ if (blt_mode)
+ bits |= (1 << 3);
+ refresh &= 0x03; /* 2 bites */
+ bits |= (refresh << 1);
+ direct_out &= 0x01;
+ bits |= direct_out;
+
+ if (overlayer == MDP4_MIXER0)
+ outpdw(MDP_BASE + 0x10004, bits); /* MDP_OVERLAY0_CFG */
+ else
+ outpdw(MDP_BASE + 0x18004, bits); /* MDP_OVERLAY1_CFG */
+
+ MSM_FB_INFO("mdp4_overlay_cfg: 0x%x\n", (int)inpdw(MDP_BASE + 0x10004));
+}
+
+void mdp4_display_intf_sel(int output, ulong intf)
+{
+ ulong bits, mask;
+
+ bits = inpdw(MDP_BASE + 0x0038); /* MDP_DISP_INTF_SEL */
+
+ mask = 0x03; /* 2 bits */
+ intf &= 0x03; /* 2 bits */
+
+ switch (output) {
+ case EXTERNAL_INTF_SEL:
+ intf <<= 4;
+ mask <<= 4;
+ break;
+ case SECONDARY_INTF_SEL:
+ intf &= 0x02; /* only MDDI and EBI2 support */
+ intf <<= 2;
+ mask <<= 2;
+ break;
+ default:
+ break;
+ }
+
+
+ bits &= ~mask;
+ bits |= intf;
+
+ outpdw(MDP_BASE + 0x0038, bits); /* MDP_DISP_INTF_SEL */
+
+ MSM_FB_INFO("mdp4_display_intf_sel: 0x%x\n", (int)inpdw(MDP_BASE + 0x0038));
+}
+
+unsigned long mdp4_display_status(void)
+{
+ return inpdw(MDP_BASE + 0x0018) & 0x3ff; /* MDP_DISPLAY_STATUS */
+}
+
+void mdp4_ebi2_lcd_setup(int lcd, ulong base, int ystride)
+{
+ /* always use memory map */
+ ystride &= 0x01fff; /* 13 bits */
+ if (lcd == EBI2_LCD0) {
+ outpdw(MDP_BASE + 0x0060, base);/* MDP_EBI2_LCD0 */
+ outpdw(MDP_BASE + 0x0068, ystride);/* MDP_EBI2_LCD0_YSTRIDE */
+ } else {
+ outpdw(MDP_BASE + 0x0064, base);/* MDP_EBI2_LCD1 */
+ outpdw(MDP_BASE + 0x006c, ystride);/* MDP_EBI2_LCD1_YSTRIDE */
+ }
+}
+
+void mdp4_mddi_setup(int mddi, unsigned long id)
+{
+ ulong bits;
+
+ if (mddi == MDDI_EXTERNAL_SET)
+ bits = 0x02;
+ else if (mddi == MDDI_SECONDARY_SET)
+ bits = 0x01;
+ else
+ bits = 0; /* PRIMARY_SET */
+
+ id <<= 16;
+
+ bits |= id;
+
+ outpdw(MDP_BASE + 0x0090, bits); /* MDP_MDDI_PARAM_WR_SEL */
+}
+
+int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req,
+ struct file **pp_src_file, struct file **pp_dst_file)
+{
+
+ /* not implemented yet */
+ return -1;
+}
+
+void mdp4_hw_init(void)
+{
+ ulong bits;
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+#ifdef MDP4_ERROR
+ /*
+ * Issue software reset on DMA_P will casue DMA_P dma engine stall
+ * on LCDC mode. However DMA_P does not stall at MDDI mode.
+ * This need further investigation.
+ */
+ mdp4_sw_reset(0x17);
+#endif
+
+ mdp4_clear_lcdc();
+
+ mdp4_mixer_blend_init(0);
+ mdp4_mixer_blend_init(1);
+ mdp4_vg_qseed_init(0);
+ mdp4_vg_qseed_init(1);
+ mdp4_vg_csc_mv_setup(0);
+ mdp4_vg_csc_mv_setup(1);
+ mdp4_vg_csc_pre_bv_setup(0);
+ mdp4_vg_csc_pre_bv_setup(1);
+ mdp4_vg_csc_post_bv_setup(0);
+ mdp4_vg_csc_post_bv_setup(1);
+ mdp4_vg_csc_pre_lv_setup(0);
+ mdp4_vg_csc_pre_lv_setup(1);
+ mdp4_vg_csc_post_lv_setup(0);
+ mdp4_vg_csc_post_lv_setup(1);
+
+ mdp4_mixer_gc_lut_setup(0);
+ mdp4_mixer_gc_lut_setup(1);
+
+ mdp4_vg_igc_lut_setup(0);
+ mdp4_vg_igc_lut_setup(1);
+
+ mdp4_rgb_igc_lut_setup(0);
+ mdp4_rgb_igc_lut_setup(1);
+
+ outp32(MDP_EBI2_PORTMAP_MODE, 0x3);
+
+ /* system interrupts */
+
+ bits = mdp_intr_mask;
+ outpdw(MDP_BASE + 0x0050, bits);/* enable specififed interrupts */
+
+ /* histogram */
+ MDP_OUTP(MDP_BASE + 0x95010, 1); /* auto clear HIST */
+
+ /* enable histogram interrupts */
+ outpdw(MDP_BASE + 0x9501c, INTR_HIST_DONE);
+
+ /* For the max read pending cmd config below, if the MDP clock */
+ /* is less than the AXI clock, then we must use 3 pending */
+ /* pending requests. Otherwise, we should use 8 pending requests. */
+ /* In the future we should do this detection automatically. */
+
+ /* max read pending cmd config */
+ outpdw(MDP_BASE + 0x004c, 0x02222); /* 3 pending requests */
+
+ /* dma_p fetch config */
+ outpdw(MDP_BASE + 0x91004, 0x27); /* burst size of 8 */
+
+#ifndef CONFIG_FB_MSM_OVERLAY
+ /* both REFRESH_MODE and DIRECT_OUT are ignored at BLT mode */
+ mdp4_overlay_cfg(MDP4_MIXER0, OVERLAY_MODE_BLT, 0, 0);
+ mdp4_overlay_cfg(MDP4_MIXER1, OVERLAY_MODE_BLT, 0, 0);
+#endif
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+
+void mdp4_clear_lcdc(void)
+{
+ uint32 bits;
+
+ bits = inpdw(MDP_BASE + 0xc0000);
+ if (bits & 0x01) /* enabled already */
+ return;
+
+ outpdw(MDP_BASE + 0xc0004, 0); /* vsync ctrl out */
+ outpdw(MDP_BASE + 0xc0008, 0); /* vsync period */
+ outpdw(MDP_BASE + 0xc000c, 0); /* vsync pusle width */
+ outpdw(MDP_BASE + 0xc0010, 0); /* lcdc display HCTL */
+ outpdw(MDP_BASE + 0xc0014, 0); /* lcdc display v start */
+ outpdw(MDP_BASE + 0xc0018, 0); /* lcdc display v end */
+ outpdw(MDP_BASE + 0xc001c, 0); /* lcdc active hctl */
+ outpdw(MDP_BASE + 0xc0020, 0); /* lcdc active v start */
+ outpdw(MDP_BASE + 0xc0024, 0); /* lcdc active v end */
+ outpdw(MDP_BASE + 0xc0028, 0); /* lcdc board color */
+ outpdw(MDP_BASE + 0xc002c, 0); /* lcdc underflow ctrl */
+ outpdw(MDP_BASE + 0xc0030, 0); /* lcdc hsync skew */
+ outpdw(MDP_BASE + 0xc0034, 0); /* lcdc test ctl */
+ outpdw(MDP_BASE + 0xc0038, 0); /* lcdc ctl polarity */
+}
+
+static struct mdp_dma_data overlay1_data;
+static int intr_dma_p;
+static int intr_dma_s;
+static int intr_dma_e;
+static int intr_overlay0;
+static int intr_overlay1;
+
+irqreturn_t mdp4_isr(int irq, void *ptr)
+{
+ uint32 isr, mask, lcdc;
+ struct mdp_dma_data *dma;
+
+ mdp_is_in_isr = TRUE;
+
+ while (1) {
+ isr = inpdw(MDP_INTR_STATUS);
+ if (isr == 0)
+ break;
+
+ mask = inpdw(MDP_INTR_ENABLE);
+ outpdw(MDP_INTR_CLEAR, isr);
+
+ isr &= mask;
+
+ if (unlikely(isr == 0))
+ break;
+
+ if (isr & INTR_DMA_P_DONE) {
+ intr_dma_p++;
+ lcdc = inpdw(MDP_BASE + 0xc0000);
+ dma = &dma2_data;
+ if (lcdc & 0x01) { /* LCDC enable */
+ /* disable LCDC interrupt */
+ mdp_intr_mask &= ~INTR_DMA_P_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ dma->waiting = FALSE;
+ } else {
+ dma->busy = FALSE;
+ mdp_pipe_ctrl(MDP_DMA2_BLOCK,
+ MDP_BLOCK_POWER_OFF, TRUE);
+ }
+ complete(&dma->comp);
+ }
+ if (isr & INTR_DMA_S_DONE) {
+ intr_dma_s++;
+ dma = &dma_s_data;
+ dma->busy = FALSE;
+ mdp_pipe_ctrl(MDP_DMA_S_BLOCK,
+ MDP_BLOCK_POWER_OFF, TRUE);
+ complete(&dma->comp);
+ }
+ if (isr & INTR_DMA_E_DONE) {
+ intr_dma_e++;
+ dma = &dma_e_data;
+ mdp_intr_mask &= ~INTR_DMA_E_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ dma->busy = FALSE;
+
+ if (dma->waiting) {
+ dma->waiting = FALSE;
+ complete(&dma->comp);
+ }
+ }
+ if (isr & INTR_OVERLAY0_DONE) {
+ intr_overlay0++;
+ lcdc = inpdw(MDP_BASE + 0xc0000);
+ dma = &dma2_data;
+ if (lcdc & 0x01) { /* LCDC enable */
+ /* disable LCDC interrupt */
+ mdp_intr_mask &= ~INTR_OVERLAY0_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ dma->waiting = FALSE;
+ mdp4_overlay0_done_lcdc();
+ } else { /* MDDI */
+ dma->busy = FALSE;
+#ifdef MDP4_NONBLOCKING
+ mdp_disable_irq_nolock(MDP_OVERLAY0_TERM);
+#endif
+ mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK,
+ MDP_BLOCK_POWER_OFF, TRUE);
+ mdp4_overlay0_done_mddi();
+ }
+ }
+ if (isr & INTR_OVERLAY1_DONE) {
+ intr_overlay1++;
+ dma = &overlay1_data;
+ dma->busy = FALSE;
+ mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK,
+ MDP_BLOCK_POWER_OFF, TRUE);
+ complete(&dma->comp);
+ }
+ if (isr & INTR_DMA_P_HISTOGRAM) {
+ isr = inpdw(MDP_DMA_P_HIST_INTR_STATUS);
+ mask = inpdw(MDP_DMA_P_HIST_INTR_ENABLE);
+ outpdw(MDP_DMA_P_HIST_INTR_CLEAR, isr);
+ isr &= mask;
+ if (isr & INTR_HIST_DONE) {
+ if (mdp_hist.r)
+ memcpy(mdp_hist.r, MDP_BASE + 0x95100,
+ mdp_hist.bin_cnt*4);
+ if (mdp_hist.g)
+ memcpy(mdp_hist.g, MDP_BASE + 0x95200,
+ mdp_hist.bin_cnt*4);
+ if (mdp_hist.b)
+ memcpy(mdp_hist.b, MDP_BASE + 0x95300,
+ mdp_hist.bin_cnt*4);
+ complete(&mdp_hist_comp);
+ }
+ }
+ }
+
+ mdp_is_in_isr = FALSE;
+
+ return IRQ_HANDLED;
+}
+
+
+/*
+ * QSEED tables
+ */
+
+static uint32 vg_qseed_table0[] = {
+ 0x5556aaff, 0x00000000, 0x00000000, 0x00000000
+};
+
+static uint32 vg_qseed_table1[] = {
+ 0x76543210, 0xfedcba98
+};
+
+static uint32 vg_qseed_table2[] = {
+ 0x02000000, 0x00000000, 0x02060ff2, 0x00000008,
+ 0x02090fe4, 0x00000013, 0x020a0fd9, 0x0ffc0021,
+ 0x02080fce, 0x0ffa0030, 0x02030fc5, 0x0ff60042,
+ 0x01fd0fbe, 0x0ff10054, 0x01f50fb6, 0x0fed0068,
+ 0x01e90fb1, 0x0fe60080, 0x01dc0fae, 0x0fe10095,
+ 0x01ca0fae, 0x0fda00ae, 0x01b70fad, 0x0fd600c6,
+ 0x01a40fad, 0x0fcf00e0, 0x018f0faf, 0x0fc800fa,
+ 0x01780fb1, 0x0fc30114, 0x015f0fb5, 0x0fbf012d,
+ 0x01490fb7, 0x0fb70149, 0x012d0fbf, 0x0fb5015f,
+ 0x01140fc3, 0x0fb10178, 0x00fa0fc8, 0x0faf018f,
+ 0x00e00fcf, 0x0fad01a4, 0x00c60fd6, 0x0fad01b7,
+ 0x00ae0fda, 0x0fae01ca, 0x00950fe1, 0x0fae01dc,
+ 0x00800fe6, 0x0fb101e9, 0x00680fed, 0x0fb601f5,
+ 0x00540ff1, 0x0fbe01fd, 0x00420ff6, 0x0fc50203,
+ 0x00300ffa, 0x0fce0208, 0x00210ffc, 0x0fd9020a,
+ 0x00130000, 0x0fe40209, 0x00080000, 0x0ff20206,
+ 0x02000000, 0x00000000, 0x02040ff2, 0x0000000a,
+ 0x02040fe4, 0x00000018, 0x02010fda, 0x0ffc0029,
+ 0x01fc0fcf, 0x0ffa003b, 0x01f30fc7, 0x0ff60050,
+ 0x01e90fc0, 0x0ff20065, 0x01dc0fba, 0x0fee007c,
+ 0x01cc0fb6, 0x0fe80096, 0x01ba0fb4, 0x0fe400ae,
+ 0x01a70fb4, 0x0fdd00c8, 0x018f0fb5, 0x0fda00e2,
+ 0x017a0fb5, 0x0fd400fd, 0x01630fb8, 0x0fce0117,
+ 0x014c0fba, 0x0fca0130, 0x01320fbf, 0x0fc70148,
+ 0x011b0fc1, 0x0fc10163, 0x01010fc8, 0x0fc00177,
+ 0x00e90fcd, 0x0fbd018d, 0x00d10fd1, 0x0fbc01a2,
+ 0x00ba0fd7, 0x0fbb01b4, 0x00a30fdd, 0x0fbc01c4,
+ 0x008e0fe1, 0x0fbd01d4, 0x00790fe7, 0x0fbe01e2,
+ 0x00670feb, 0x0fc001ee, 0x00540ff1, 0x0fc501f6,
+ 0x00430ff4, 0x0fcb01fe, 0x00340ff8, 0x0fd10203,
+ 0x00260ffb, 0x0fd80207, 0x001a0ffd, 0x0fe10208,
+ 0x000f0000, 0x0fea0207, 0x00060000, 0x0ff50205,
+ 0x02000000, 0x00000000, 0x02020ff2, 0x0000000c,
+ 0x02000fe4, 0x0000001c, 0x01fa0fda, 0x0ffc0030,
+ 0x01f10fd0, 0x0ffa0045, 0x01e50fc8, 0x0ff6005d,
+ 0x01d60fc3, 0x0ff30074, 0x01c60fbd, 0x0fef008e,
+ 0x01b30fba, 0x0fe900aa, 0x019e0fb9, 0x0fe500c4,
+ 0x01870fba, 0x0fe000df, 0x016f0fbb, 0x0fdd00f9,
+ 0x01580fbc, 0x0fd80114, 0x01400fbf, 0x0fd3012e,
+ 0x01280fc2, 0x0fd00146, 0x010f0fc6, 0x0fce015d,
+ 0x00f90fc9, 0x0fc90175, 0x00e00fcf, 0x0fc90188,
+ 0x00ca0fd4, 0x0fc6019c, 0x00b40fd8, 0x0fc601ae,
+ 0x009f0fdd, 0x0fc501bf, 0x008b0fe3, 0x0fc601cc,
+ 0x00780fe6, 0x0fc701db, 0x00660feb, 0x0fc801e7,
+ 0x00560fef, 0x0fcb01f0, 0x00460ff3, 0x0fcf01f8,
+ 0x00380ff6, 0x0fd401fe, 0x002c0ff9, 0x0fd90202,
+ 0x00200ffc, 0x0fdf0205, 0x00160ffe, 0x0fe60206,
+ 0x000c0000, 0x0fed0207, 0x00050000, 0x0ff70204,
+ 0x02000000, 0x00000000, 0x01fe0ff3, 0x0000000f,
+ 0x01f60fe5, 0x00000025, 0x01ea0fdb, 0x0ffd003e,
+ 0x01db0fd2, 0x0ffb0058, 0x01c80fcc, 0x0ff70075,
+ 0x01b50fc7, 0x0ff40090, 0x01a00fc3, 0x0ff000ad,
+ 0x01880fc1, 0x0feb00cc, 0x01700fc1, 0x0fe800e7,
+ 0x01550fc3, 0x0fe40104, 0x013b0fc5, 0x0fe2011e,
+ 0x01240fc6, 0x0fde0138, 0x010c0fca, 0x0fda0150,
+ 0x00f40fcd, 0x0fd90166, 0x00dd0fd1, 0x0fd7017b,
+ 0x00c80fd4, 0x0fd40190, 0x00b20fd9, 0x0fd401a1,
+ 0x009f0fdd, 0x0fd301b1, 0x008c0fe1, 0x0fd301c0,
+ 0x007b0fe5, 0x0fd301cd, 0x006a0fea, 0x0fd401d8,
+ 0x005c0fec, 0x0fd501e3, 0x004d0ff0, 0x0fd601ed,
+ 0x00410ff3, 0x0fd801f4, 0x00340ff7, 0x0fdb01fa,
+ 0x002a0ff9, 0x0fdf01fe, 0x00200ffb, 0x0fe30202,
+ 0x00180ffd, 0x0fe70204, 0x00100ffe, 0x0fed0205,
+ 0x00090000, 0x0ff20205, 0x00040000, 0x0ff90203,
+ 0x02000000, 0x00000000, 0x02050ff5, 0x00000006,
+ 0x02070fea, 0x0000000f, 0x02080fe1, 0x0ffd001a,
+ 0x02070fd8, 0x0ffb0026, 0x02030fd1, 0x0ff80034,
+ 0x01fe0fcb, 0x0ff40043, 0x01f60fc5, 0x0ff10054,
+ 0x01ee0fc0, 0x0feb0067, 0x01e20fbe, 0x0fe70079,
+ 0x01d40fbd, 0x0fe1008e, 0x01c40fbc, 0x0fdd00a3,
+ 0x01b40fbb, 0x0fd700ba, 0x01a20fbc, 0x0fd100d1,
+ 0x018d0fbd, 0x0fcd00e9, 0x01770fc0, 0x0fc80101,
+ 0x01630fc1, 0x0fc1011b, 0x01480fc7, 0x0fbf0132,
+ 0x01300fca, 0x0fba014c, 0x01170fce, 0x0fb80163,
+ 0x00fd0fd4, 0x0fb5017a, 0x00e20fda, 0x0fb5018f,
+ 0x00c80fdd, 0x0fb401a7, 0x00ae0fe4, 0x0fb401ba,
+ 0x00960fe8, 0x0fb601cc, 0x007c0fee, 0x0fba01dc,
+ 0x00650ff2, 0x0fc001e9, 0x00500ff6, 0x0fc701f3,
+ 0x003b0ffa, 0x0fcf01fc, 0x00290ffc, 0x0fda0201,
+ 0x00180000, 0x0fe40204, 0x000a0000, 0x0ff20204,
+ 0x02000000, 0x00000000, 0x02030ff5, 0x00000008,
+ 0x02030fea, 0x00000013, 0x02020fe1, 0x0ffd0020,
+ 0x01fc0fd9, 0x0ffc002f, 0x01f60fd2, 0x0ff80040,
+ 0x01ed0fcd, 0x0ff50051, 0x01e30fc7, 0x0ff10065,
+ 0x01d70fc3, 0x0fec007a, 0x01c60fc2, 0x0fe9008f,
+ 0x01b60fc1, 0x0fe300a6, 0x01a20fc1, 0x0fe000bd,
+ 0x018f0fc1, 0x0fdb00d5, 0x017b0fc2, 0x0fd500ee,
+ 0x01640fc4, 0x0fd20106, 0x014d0fc8, 0x0fce011d,
+ 0x01370fc9, 0x0fc90137, 0x011d0fce, 0x0fc8014d,
+ 0x01060fd2, 0x0fc40164, 0x00ee0fd5, 0x0fc2017b,
+ 0x00d50fdb, 0x0fc1018f, 0x00bd0fe0, 0x0fc101a2,
+ 0x00a60fe3, 0x0fc101b6, 0x008f0fe9, 0x0fc201c6,
+ 0x007a0fec, 0x0fc301d7, 0x00650ff1, 0x0fc701e3,
+ 0x00510ff5, 0x0fcd01ed, 0x00400ff8, 0x0fd201f6,
+ 0x002f0ffc, 0x0fd901fc, 0x00200ffd, 0x0fe10202,
+ 0x00130000, 0x0fea0203, 0x00080000, 0x0ff50203,
+ 0x02000000, 0x00000000, 0x02020ff5, 0x00000009,
+ 0x01ff0fea, 0x00000017, 0x01fb0fe2, 0x0ffd0026,
+ 0x01f30fda, 0x0ffc0037, 0x01ea0fd3, 0x0ff8004b,
+ 0x01df0fce, 0x0ff5005e, 0x01d10fc9, 0x0ff20074,
+ 0x01c10fc6, 0x0fed008c, 0x01ae0fc5, 0x0fea00a3,
+ 0x019b0fc5, 0x0fe500bb, 0x01850fc6, 0x0fe200d3,
+ 0x01700fc6, 0x0fde00ec, 0x015a0fc8, 0x0fd90105,
+ 0x01430fca, 0x0fd6011d, 0x012b0fcd, 0x0fd30135,
+ 0x01150fcf, 0x0fcf014d, 0x00fc0fd4, 0x0fce0162,
+ 0x00e50fd8, 0x0fcc0177, 0x00cf0fdb, 0x0fca018c,
+ 0x00b80fe0, 0x0fc9019f, 0x00a20fe5, 0x0fca01af,
+ 0x008e0fe8, 0x0fcb01bf, 0x00790fec, 0x0fcb01d0,
+ 0x00670fef, 0x0fcd01dd, 0x00550ff4, 0x0fd001e7,
+ 0x00440ff7, 0x0fd501f0, 0x00350ffa, 0x0fda01f7,
+ 0x00270ffc, 0x0fdf01fe, 0x001b0ffe, 0x0fe70200,
+ 0x00100000, 0x0fee0202, 0x00060000, 0x0ff70203,
+ 0x02000000, 0x00000000, 0x01ff0ff5, 0x0000000c,
+ 0x01f80fea, 0x0000001e, 0x01ef0fe2, 0x0ffd0032,
+ 0x01e20fdb, 0x0ffc0047, 0x01d30fd5, 0x0ff9005f,
+ 0x01c20fd1, 0x0ff60077, 0x01b00fcd, 0x0ff30090,
+ 0x019b0fcb, 0x0fef00ab, 0x01850fcb, 0x0fec00c4,
+ 0x016e0fcc, 0x0fe800de, 0x01550fcd, 0x0fe600f8,
+ 0x013f0fce, 0x0fe20111, 0x01280fd0, 0x0fdf0129,
+ 0x01110fd2, 0x0fdd0140, 0x00f90fd6, 0x0fdb0156,
+ 0x00e40fd8, 0x0fd8016c, 0x00cd0fdd, 0x0fd8017e,
+ 0x00b80fe0, 0x0fd60192, 0x00a40fe3, 0x0fd601a3,
+ 0x00910fe7, 0x0fd501b3, 0x007f0feb, 0x0fd601c0,
+ 0x006e0fed, 0x0fd701ce, 0x005d0ff1, 0x0fd701db,
+ 0x004f0ff3, 0x0fd901e5, 0x00400ff7, 0x0fdc01ed,
+ 0x00330ff9, 0x0fe001f4, 0x00280ffb, 0x0fe301fa,
+ 0x001d0ffd, 0x0fe801fe, 0x00140ffe, 0x0fed0201,
+ 0x000c0000, 0x0ff20202, 0x00050000, 0x0ff90202,
+ 0x02000000, 0x00000000, 0x02040ff7, 0x00000005,
+ 0x02070fed, 0x0000000c, 0x02060fe6, 0x0ffe0016,
+ 0x02050fdf, 0x0ffc0020, 0x02020fd9, 0x0ff9002c,
+ 0x01fe0fd4, 0x0ff60038, 0x01f80fcf, 0x0ff30046,
+ 0x01f00fcb, 0x0fef0056, 0x01e70fc8, 0x0feb0066,
+ 0x01db0fc7, 0x0fe60078, 0x01cc0fc6, 0x0fe3008b,
+ 0x01bf0fc5, 0x0fdd009f, 0x01ae0fc6, 0x0fd800b4,
+ 0x019c0fc6, 0x0fd400ca, 0x01880fc9, 0x0fcf00e0,
+ 0x01750fc9, 0x0fc900f9, 0x015d0fce, 0x0fc6010f,
+ 0x01460fd0, 0x0fc20128, 0x012e0fd3, 0x0fbf0140,
+ 0x01140fd8, 0x0fbc0158, 0x00f90fdd, 0x0fbb016f,
+ 0x00df0fe0, 0x0fba0187, 0x00c40fe5, 0x0fb9019e,
+ 0x00aa0fe9, 0x0fba01b3, 0x008e0fef, 0x0fbd01c6,
+ 0x00740ff3, 0x0fc301d6, 0x005d0ff6, 0x0fc801e5,
+ 0x00450ffa, 0x0fd001f1, 0x00300ffc, 0x0fda01fa,
+ 0x001c0000, 0x0fe40200, 0x000c0000, 0x0ff20202,
+ 0x02000000, 0x00000000, 0x02030ff7, 0x00000006,
+ 0x02020fee, 0x00000010, 0x02000fe7, 0x0ffe001b,
+ 0x01fe0fdf, 0x0ffc0027, 0x01f70fda, 0x0ffa0035,
+ 0x01f00fd5, 0x0ff70044, 0x01e70fd0, 0x0ff40055,
+ 0x01dd0fcd, 0x0fef0067, 0x01d00fcb, 0x0fec0079,
+ 0x01bf0fcb, 0x0fe8008e, 0x01af0fca, 0x0fe500a2,
+ 0x019f0fc9, 0x0fe000b8, 0x018c0fca, 0x0fdb00cf,
+ 0x01770fcc, 0x0fd800e5, 0x01620fce, 0x0fd400fc,
+ 0x014d0fcf, 0x0fcf0115, 0x01350fd3, 0x0fcd012b,
+ 0x011d0fd6, 0x0fca0143, 0x01050fd9, 0x0fc8015a,
+ 0x00ec0fde, 0x0fc60170, 0x00d30fe2, 0x0fc60185,
+ 0x00bb0fe5, 0x0fc5019b, 0x00a30fea, 0x0fc501ae,
+ 0x008c0fed, 0x0fc601c1, 0x00740ff2, 0x0fc901d1,
+ 0x005e0ff5, 0x0fce01df, 0x004b0ff8, 0x0fd301ea,
+ 0x00370ffc, 0x0fda01f3, 0x00260ffd, 0x0fe201fb,
+ 0x00170000, 0x0fea01ff, 0x00090000, 0x0ff50202,
+ 0x02000000, 0x00000000, 0x02010ff7, 0x00000008,
+ 0x01ff0fee, 0x00000013, 0x01fb0fe7, 0x0ffe0020,
+ 0x01f60fe0, 0x0ffc002e, 0x01ed0fda, 0x0ffa003f,
+ 0x01e40fd6, 0x0ff7004f, 0x01d80fd2, 0x0ff40062,
+ 0x01ca0fcf, 0x0ff00077, 0x01bb0fcd, 0x0fed008b,
+ 0x01a90fcd, 0x0fe900a1, 0x01960fcd, 0x0fe600b7,
+ 0x01830fcd, 0x0fe200ce, 0x016d0fcf, 0x0fde00e6,
+ 0x01580fd0, 0x0fdb00fd, 0x01410fd3, 0x0fd80114,
+ 0x012c0fd4, 0x0fd4012c, 0x01140fd8, 0x0fd30141,
+ 0x00fd0fdb, 0x0fd00158, 0x00e60fde, 0x0fcf016d,
+ 0x00ce0fe2, 0x0fcd0183, 0x00b70fe6, 0x0fcd0196,
+ 0x00a10fe9, 0x0fcd01a9, 0x008b0fed, 0x0fcd01bb,
+ 0x00770ff0, 0x0fcf01ca, 0x00620ff4, 0x0fd201d8,
+ 0x004f0ff7, 0x0fd601e4, 0x003f0ffa, 0x0fda01ed,
+ 0x002e0ffc, 0x0fe001f6, 0x00200ffe, 0x0fe701fb,
+ 0x00130000, 0x0fee01ff, 0x00080000, 0x0ff70201,
+ 0x02000000, 0x00000000, 0x01ff0ff7, 0x0000000a,
+ 0x01f90fee, 0x00000019, 0x01f10fe7, 0x0ffe002a,
+ 0x01e60fe1, 0x0ffd003c, 0x01d90fdc, 0x0ffa0051,
+ 0x01cc0fd8, 0x0ff70065, 0x01bb0fd5, 0x0ff5007b,
+ 0x01a80fd3, 0x0ff10094, 0x01950fd2, 0x0fef00aa,
+ 0x01800fd2, 0x0feb00c3, 0x016a0fd3, 0x0fe900da,
+ 0x01540fd3, 0x0fe600f3, 0x013f0fd5, 0x0fe2010a,
+ 0x01280fd7, 0x0fe00121, 0x01100fda, 0x0fde0138,
+ 0x00fb0fdb, 0x0fdb014f, 0x00e40fdf, 0x0fdb0162,
+ 0x00ce0fe2, 0x0fd90177, 0x00b90fe4, 0x0fd8018b,
+ 0x00a50fe8, 0x0fd8019b, 0x00910fec, 0x0fd801ab,
+ 0x007e0fee, 0x0fd801bc, 0x006c0ff2, 0x0fd901c9,
+ 0x005c0ff4, 0x0fda01d6, 0x004b0ff7, 0x0fdd01e1,
+ 0x003c0ff9, 0x0fe001eb, 0x002f0ffb, 0x0fe401f2,
+ 0x00230ffd, 0x0fe801f8, 0x00180ffe, 0x0fed01fd,
+ 0x000e0000, 0x0ff20200, 0x00060000, 0x0ff90201,
+ 0x02000000, 0x00000000, 0x02030ff9, 0x00000004,
+ 0x02050ff2, 0x00000009, 0x02050fed, 0x0ffe0010,
+ 0x02040fe7, 0x0ffd0018, 0x02020fe3, 0x0ffb0020,
+ 0x01fe0fdf, 0x0ff9002a, 0x01fa0fdb, 0x0ff70034,
+ 0x01f40fd8, 0x0ff30041, 0x01ed0fd6, 0x0ff0004d,
+ 0x01e30fd5, 0x0fec005c, 0x01d80fd4, 0x0fea006a,
+ 0x01cd0fd3, 0x0fe5007b, 0x01c00fd3, 0x0fe1008c,
+ 0x01b10fd3, 0x0fdd009f, 0x01a10fd4, 0x0fd900b2,
+ 0x01900fd4, 0x0fd400c8, 0x017b0fd7, 0x0fd100dd,
+ 0x01660fd9, 0x0fcd00f4, 0x01500fda, 0x0fca010c,
+ 0x01380fde, 0x0fc60124, 0x011e0fe2, 0x0fc5013b,
+ 0x01040fe4, 0x0fc30155, 0x00e70fe8, 0x0fc10170,
+ 0x00cc0feb, 0x0fc10188, 0x00ad0ff0, 0x0fc301a0,
+ 0x00900ff4, 0x0fc701b5, 0x00750ff7, 0x0fcc01c8,
+ 0x00580ffb, 0x0fd201db, 0x003e0ffd, 0x0fdb01ea,
+ 0x00250000, 0x0fe501f6, 0x000f0000, 0x0ff301fe,
+ 0x02000000, 0x00000000, 0x02020ff9, 0x00000005,
+ 0x02020ff2, 0x0000000c, 0x02010fed, 0x0ffe0014,
+ 0x01fe0fe8, 0x0ffd001d, 0x01fa0fe3, 0x0ffb0028,
+ 0x01f40fe0, 0x0ff90033, 0x01ed0fdc, 0x0ff70040,
+ 0x01e50fd9, 0x0ff3004f, 0x01db0fd7, 0x0ff1005d,
+ 0x01ce0fd7, 0x0fed006e, 0x01c00fd6, 0x0feb007f,
+ 0x01b30fd5, 0x0fe70091, 0x01a30fd6, 0x0fe300a4,
+ 0x01920fd6, 0x0fe000b8, 0x017e0fd8, 0x0fdd00cd,
+ 0x016c0fd8, 0x0fd800e4, 0x01560fdb, 0x0fd600f9,
+ 0x01400fdd, 0x0fd20111, 0x01290fdf, 0x0fd00128,
+ 0x01110fe2, 0x0fce013f, 0x00f80fe6, 0x0fcd0155,
+ 0x00de0fe8, 0x0fcc016e, 0x00c40fec, 0x0fcb0185,
+ 0x00ab0fef, 0x0fcb019b, 0x00900ff3, 0x0fcd01b0,
+ 0x00770ff6, 0x0fd101c2, 0x005f0ff9, 0x0fd501d3,
+ 0x00470ffc, 0x0fdb01e2, 0x00320ffd, 0x0fe201ef,
+ 0x001e0000, 0x0fea01f8, 0x000c0000, 0x0ff501ff,
+ 0x02000000, 0x00000000, 0x02010ff9, 0x00000006,
+ 0x02000ff2, 0x0000000e, 0x01fd0fed, 0x0ffe0018,
+ 0x01f80fe8, 0x0ffd0023, 0x01f20fe4, 0x0ffb002f,
+ 0x01eb0fe0, 0x0ff9003c, 0x01e10fdd, 0x0ff7004b,
+ 0x01d60fda, 0x0ff4005c, 0x01c90fd9, 0x0ff2006c,
+ 0x01bc0fd8, 0x0fee007e, 0x01ab0fd8, 0x0fec0091,
+ 0x019b0fd8, 0x0fe800a5, 0x018b0fd8, 0x0fe400b9,
+ 0x01770fd9, 0x0fe200ce, 0x01620fdb, 0x0fdf00e4,
+ 0x014f0fdb, 0x0fdb00fb, 0x01380fde, 0x0fda0110,
+ 0x01210fe0, 0x0fd70128, 0x010a0fe2, 0x0fd5013f,
+ 0x00f30fe6, 0x0fd30154, 0x00da0fe9, 0x0fd3016a,
+ 0x00c30feb, 0x0fd20180, 0x00aa0fef, 0x0fd20195,
+ 0x00940ff1, 0x0fd301a8, 0x007b0ff5, 0x0fd501bb,
+ 0x00650ff7, 0x0fd801cc, 0x00510ffa, 0x0fdc01d9,
+ 0x003c0ffd, 0x0fe101e6, 0x002a0ffe, 0x0fe701f1,
+ 0x00190000, 0x0fee01f9, 0x000a0000, 0x0ff701ff,
+ 0x02000000, 0x00000000, 0x01ff0ff9, 0x00000008,
+ 0x01fb0ff2, 0x00000013, 0x01f50fed, 0x0ffe0020,
+ 0x01ed0fe8, 0x0ffd002e, 0x01e30fe4, 0x0ffb003e,
+ 0x01d80fe1, 0x0ff9004e, 0x01cb0fde, 0x0ff70060,
+ 0x01bc0fdc, 0x0ff40074, 0x01ac0fdb, 0x0ff20087,
+ 0x019a0fdb, 0x0fef009c, 0x01870fdb, 0x0fed00b1,
+ 0x01740fdb, 0x0fea00c7, 0x01600fdc, 0x0fe700dd,
+ 0x014b0fdd, 0x0fe500f3, 0x01350fdf, 0x0fe30109,
+ 0x01200fe0, 0x0fe00120, 0x01090fe3, 0x0fdf0135,
+ 0x00f30fe5, 0x0fdd014b, 0x00dd0fe7, 0x0fdc0160,
+ 0x00c70fea, 0x0fdb0174, 0x00b10fed, 0x0fdb0187,
+ 0x009c0fef, 0x0fdb019a, 0x00870ff2, 0x0fdb01ac,
+ 0x00740ff4, 0x0fdc01bc, 0x00600ff7, 0x0fde01cb,
+ 0x004e0ff9, 0x0fe101d8, 0x003e0ffb, 0x0fe401e3,
+ 0x002e0ffd, 0x0fe801ed, 0x00200ffe, 0x0fed01f5,
+ 0x00130000, 0x0ff201fb, 0x00080000, 0x0ff901ff,
+ 0x02000000, 0x00000000, 0x02060ff2, 0x00000008,
+ 0x02090fe4, 0x00000013, 0x020a0fd9, 0x0ffc0021,
+ 0x02080fce, 0x0ffa0030, 0x02030fc5, 0x0ff60042,
+ 0x01fd0fbe, 0x0ff10054, 0x01f50fb6, 0x0fed0068,
+ 0x01e90fb1, 0x0fe60080, 0x01dc0fae, 0x0fe10095,
+ 0x01ca0fae, 0x0fda00ae, 0x01b70fad, 0x0fd600c6,
+ 0x01a40fad, 0x0fcf00e0, 0x018f0faf, 0x0fc800fa,
+ 0x01780fb1, 0x0fc30114, 0x015f0fb5, 0x0fbf012d,
+ 0x01490fb7, 0x0fb70149, 0x012d0fbf, 0x0fb5015f,
+ 0x01140fc3, 0x0fb10178, 0x00fa0fc8, 0x0faf018f,
+ 0x00e00fcf, 0x0fad01a4, 0x00c60fd6, 0x0fad01b7,
+ 0x00ae0fda, 0x0fae01ca, 0x00950fe1, 0x0fae01dc,
+ 0x00800fe6, 0x0fb101e9, 0x00680fed, 0x0fb601f5,
+ 0x00540ff1, 0x0fbe01fd, 0x00420ff6, 0x0fc50203,
+ 0x00300ffa, 0x0fce0208, 0x00210ffc, 0x0fd9020a,
+ 0x00130000, 0x0fe40209, 0x00080000, 0x0ff20206,
+ 0x02000000, 0x00000000, 0x02040ff2, 0x0000000a,
+ 0x02040fe4, 0x00000018, 0x02010fda, 0x0ffc0029,
+ 0x01fc0fcf, 0x0ffa003b, 0x01f30fc7, 0x0ff60050,
+ 0x01e90fc0, 0x0ff20065, 0x01dc0fba, 0x0fee007c,
+ 0x01cc0fb6, 0x0fe80096, 0x01ba0fb4, 0x0fe400ae,
+ 0x01a70fb4, 0x0fdd00c8, 0x018f0fb5, 0x0fda00e2,
+ 0x017a0fb5, 0x0fd400fd, 0x01630fb8, 0x0fce0117,
+ 0x014c0fba, 0x0fca0130, 0x01320fbf, 0x0fc70148,
+ 0x011b0fc1, 0x0fc10163, 0x01010fc8, 0x0fc00177,
+ 0x00e90fcd, 0x0fbd018d, 0x00d10fd1, 0x0fbc01a2,
+ 0x00ba0fd7, 0x0fbb01b4, 0x00a30fdd, 0x0fbc01c4,
+ 0x008e0fe1, 0x0fbd01d4, 0x00790fe7, 0x0fbe01e2,
+ 0x00670feb, 0x0fc001ee, 0x00540ff1, 0x0fc501f6,
+ 0x00430ff4, 0x0fcb01fe, 0x00340ff8, 0x0fd10203,
+ 0x00260ffb, 0x0fd80207, 0x001a0ffd, 0x0fe10208,
+ 0x000f0000, 0x0fea0207, 0x00060000, 0x0ff50205,
+ 0x02000000, 0x00000000, 0x02020ff2, 0x0000000c,
+ 0x02000fe4, 0x0000001c, 0x01fa0fda, 0x0ffc0030,
+ 0x01f10fd0, 0x0ffa0045, 0x01e50fc8, 0x0ff6005d,
+ 0x01d60fc3, 0x0ff30074, 0x01c60fbd, 0x0fef008e,
+ 0x01b30fba, 0x0fe900aa, 0x019e0fb9, 0x0fe500c4,
+ 0x01870fba, 0x0fe000df, 0x016f0fbb, 0x0fdd00f9,
+ 0x01580fbc, 0x0fd80114, 0x01400fbf, 0x0fd3012e,
+ 0x01280fc2, 0x0fd00146, 0x010f0fc6, 0x0fce015d,
+ 0x00f90fc9, 0x0fc90175, 0x00e00fcf, 0x0fc90188,
+ 0x00ca0fd4, 0x0fc6019c, 0x00b40fd8, 0x0fc601ae,
+ 0x009f0fdd, 0x0fc501bf, 0x008b0fe3, 0x0fc601cc,
+ 0x00780fe6, 0x0fc701db, 0x00660feb, 0x0fc801e7,
+ 0x00560fef, 0x0fcb01f0, 0x00460ff3, 0x0fcf01f8,
+ 0x00380ff6, 0x0fd401fe, 0x002c0ff9, 0x0fd90202,
+ 0x00200ffc, 0x0fdf0205, 0x00160ffe, 0x0fe60206,
+ 0x000c0000, 0x0fed0207, 0x00050000, 0x0ff70204,
+ 0x02000000, 0x00000000, 0x01fe0ff3, 0x0000000f,
+ 0x01f60fe5, 0x00000025, 0x01ea0fdb, 0x0ffd003e,
+ 0x01db0fd2, 0x0ffb0058, 0x01c80fcc, 0x0ff70075,
+ 0x01b50fc7, 0x0ff40090, 0x01a00fc3, 0x0ff000ad,
+ 0x01880fc1, 0x0feb00cc, 0x01700fc1, 0x0fe800e7,
+ 0x01550fc3, 0x0fe40104, 0x013b0fc5, 0x0fe2011e,
+ 0x01240fc6, 0x0fde0138, 0x010c0fca, 0x0fda0150,
+ 0x00f40fcd, 0x0fd90166, 0x00dd0fd1, 0x0fd7017b,
+ 0x00c80fd4, 0x0fd40190, 0x00b20fd9, 0x0fd401a1,
+ 0x009f0fdd, 0x0fd301b1, 0x008c0fe1, 0x0fd301c0,
+ 0x007b0fe5, 0x0fd301cd, 0x006a0fea, 0x0fd401d8,
+ 0x005c0fec, 0x0fd501e3, 0x004d0ff0, 0x0fd601ed,
+ 0x00410ff3, 0x0fd801f4, 0x00340ff7, 0x0fdb01fa,
+ 0x002a0ff9, 0x0fdf01fe, 0x00200ffb, 0x0fe30202,
+ 0x00180ffd, 0x0fe70204, 0x00100ffe, 0x0fed0205,
+ 0x00090000, 0x0ff20205, 0x00040000, 0x0ff90203,
+ 0x02000000, 0x00000000, 0x02050ff5, 0x00000006,
+ 0x02070fea, 0x0000000f, 0x02080fe1, 0x0ffd001a,
+ 0x02070fd8, 0x0ffb0026, 0x02030fd1, 0x0ff80034,
+ 0x01fe0fcb, 0x0ff40043, 0x01f60fc5, 0x0ff10054,
+ 0x01ee0fc0, 0x0feb0067, 0x01e20fbe, 0x0fe70079,
+ 0x01d40fbd, 0x0fe1008e, 0x01c40fbc, 0x0fdd00a3,
+ 0x01b40fbb, 0x0fd700ba, 0x01a20fbc, 0x0fd100d1,
+ 0x018d0fbd, 0x0fcd00e9, 0x01770fc0, 0x0fc80101,
+ 0x01630fc1, 0x0fc1011b, 0x01480fc7, 0x0fbf0132,
+ 0x01300fca, 0x0fba014c, 0x01170fce, 0x0fb80163,
+ 0x00fd0fd4, 0x0fb5017a, 0x00e20fda, 0x0fb5018f,
+ 0x00c80fdd, 0x0fb401a7, 0x00ae0fe4, 0x0fb401ba,
+ 0x00960fe8, 0x0fb601cc, 0x007c0fee, 0x0fba01dc,
+ 0x00650ff2, 0x0fc001e9, 0x00500ff6, 0x0fc701f3,
+ 0x003b0ffa, 0x0fcf01fc, 0x00290ffc, 0x0fda0201,
+ 0x00180000, 0x0fe40204, 0x000a0000, 0x0ff20204,
+ 0x02000000, 0x00000000, 0x02030ff5, 0x00000008,
+ 0x02030fea, 0x00000013, 0x02020fe1, 0x0ffd0020,
+ 0x01fc0fd9, 0x0ffc002f, 0x01f60fd2, 0x0ff80040,
+ 0x01ed0fcd, 0x0ff50051, 0x01e30fc7, 0x0ff10065,
+ 0x01d70fc3, 0x0fec007a, 0x01c60fc2, 0x0fe9008f,
+ 0x01b60fc1, 0x0fe300a6, 0x01a20fc1, 0x0fe000bd,
+ 0x018f0fc1, 0x0fdb00d5, 0x017b0fc2, 0x0fd500ee,
+ 0x01640fc4, 0x0fd20106, 0x014d0fc8, 0x0fce011d,
+ 0x01370fc9, 0x0fc90137, 0x011d0fce, 0x0fc8014d,
+ 0x01060fd2, 0x0fc40164, 0x00ee0fd5, 0x0fc2017b,
+ 0x00d50fdb, 0x0fc1018f, 0x00bd0fe0, 0x0fc101a2,
+ 0x00a60fe3, 0x0fc101b6, 0x008f0fe9, 0x0fc201c6,
+ 0x007a0fec, 0x0fc301d7, 0x00650ff1, 0x0fc701e3,
+ 0x00510ff5, 0x0fcd01ed, 0x00400ff8, 0x0fd201f6,
+ 0x002f0ffc, 0x0fd901fc, 0x00200ffd, 0x0fe10202,
+ 0x00130000, 0x0fea0203, 0x00080000, 0x0ff50203,
+ 0x02000000, 0x00000000, 0x02020ff5, 0x00000009,
+ 0x01ff0fea, 0x00000017, 0x01fb0fe2, 0x0ffd0026,
+ 0x01f30fda, 0x0ffc0037, 0x01ea0fd3, 0x0ff8004b,
+ 0x01df0fce, 0x0ff5005e, 0x01d10fc9, 0x0ff20074,
+ 0x01c10fc6, 0x0fed008c, 0x01ae0fc5, 0x0fea00a3,
+ 0x019b0fc5, 0x0fe500bb, 0x01850fc6, 0x0fe200d3,
+ 0x01700fc6, 0x0fde00ec, 0x015a0fc8, 0x0fd90105,
+ 0x01430fca, 0x0fd6011d, 0x012b0fcd, 0x0fd30135,
+ 0x01150fcf, 0x0fcf014d, 0x00fc0fd4, 0x0fce0162,
+ 0x00e50fd8, 0x0fcc0177, 0x00cf0fdb, 0x0fca018c,
+ 0x00b80fe0, 0x0fc9019f, 0x00a20fe5, 0x0fca01af,
+ 0x008e0fe8, 0x0fcb01bf, 0x00790fec, 0x0fcb01d0,
+ 0x00670fef, 0x0fcd01dd, 0x00550ff4, 0x0fd001e7,
+ 0x00440ff7, 0x0fd501f0, 0x00350ffa, 0x0fda01f7,
+ 0x00270ffc, 0x0fdf01fe, 0x001b0ffe, 0x0fe70200,
+ 0x00100000, 0x0fee0202, 0x00060000, 0x0ff70203,
+ 0x02000000, 0x00000000, 0x01ff0ff5, 0x0000000c,
+ 0x01f80fea, 0x0000001e, 0x01ef0fe2, 0x0ffd0032,
+ 0x01e20fdb, 0x0ffc0047, 0x01d30fd5, 0x0ff9005f,
+ 0x01c20fd1, 0x0ff60077, 0x01b00fcd, 0x0ff30090,
+ 0x019b0fcb, 0x0fef00ab, 0x01850fcb, 0x0fec00c4,
+ 0x016e0fcc, 0x0fe800de, 0x01550fcd, 0x0fe600f8,
+ 0x013f0fce, 0x0fe20111, 0x01280fd0, 0x0fdf0129,
+ 0x01110fd2, 0x0fdd0140, 0x00f90fd6, 0x0fdb0156,
+ 0x00e40fd8, 0x0fd8016c, 0x00cd0fdd, 0x0fd8017e,
+ 0x00b80fe0, 0x0fd60192, 0x00a40fe3, 0x0fd601a3,
+ 0x00910fe7, 0x0fd501b3, 0x007f0feb, 0x0fd601c0,
+ 0x006e0fed, 0x0fd701ce, 0x005d0ff1, 0x0fd701db,
+ 0x004f0ff3, 0x0fd901e5, 0x00400ff7, 0x0fdc01ed,
+ 0x00330ff9, 0x0fe001f4, 0x00280ffb, 0x0fe301fa,
+ 0x001d0ffd, 0x0fe801fe, 0x00140ffe, 0x0fed0201,
+ 0x000c0000, 0x0ff20202, 0x00050000, 0x0ff90202,
+ 0x02000000, 0x00000000, 0x02040ff7, 0x00000005,
+ 0x02070fed, 0x0000000c, 0x02060fe6, 0x0ffe0016,
+ 0x02050fdf, 0x0ffc0020, 0x02020fd9, 0x0ff9002c,
+ 0x01fe0fd4, 0x0ff60038, 0x01f80fcf, 0x0ff30046,
+ 0x01f00fcb, 0x0fef0056, 0x01e70fc8, 0x0feb0066,
+ 0x01db0fc7, 0x0fe60078, 0x01cc0fc6, 0x0fe3008b,
+ 0x01bf0fc5, 0x0fdd009f, 0x01ae0fc6, 0x0fd800b4,
+ 0x019c0fc6, 0x0fd400ca, 0x01880fc9, 0x0fcf00e0,
+ 0x01750fc9, 0x0fc900f9, 0x015d0fce, 0x0fc6010f,
+ 0x01460fd0, 0x0fc20128, 0x012e0fd3, 0x0fbf0140,
+ 0x01140fd8, 0x0fbc0158, 0x00f90fdd, 0x0fbb016f,
+ 0x00df0fe0, 0x0fba0187, 0x00c40fe5, 0x0fb9019e,
+ 0x00aa0fe9, 0x0fba01b3, 0x008e0fef, 0x0fbd01c6,
+ 0x00740ff3, 0x0fc301d6, 0x005d0ff6, 0x0fc801e5,
+ 0x00450ffa, 0x0fd001f1, 0x00300ffc, 0x0fda01fa,
+ 0x001c0000, 0x0fe40200, 0x000c0000, 0x0ff20202,
+ 0x02000000, 0x00000000, 0x02030ff7, 0x00000006,
+ 0x02020fee, 0x00000010, 0x02000fe7, 0x0ffe001b,
+ 0x01fe0fdf, 0x0ffc0027, 0x01f70fda, 0x0ffa0035,
+ 0x01f00fd5, 0x0ff70044, 0x01e70fd0, 0x0ff40055,
+ 0x01dd0fcd, 0x0fef0067, 0x01d00fcb, 0x0fec0079,
+ 0x01bf0fcb, 0x0fe8008e, 0x01af0fca, 0x0fe500a2,
+ 0x019f0fc9, 0x0fe000b8, 0x018c0fca, 0x0fdb00cf,
+ 0x01770fcc, 0x0fd800e5, 0x01620fce, 0x0fd400fc,
+ 0x014d0fcf, 0x0fcf0115, 0x01350fd3, 0x0fcd012b,
+ 0x011d0fd6, 0x0fca0143, 0x01050fd9, 0x0fc8015a,
+ 0x00ec0fde, 0x0fc60170, 0x00d30fe2, 0x0fc60185,
+ 0x00bb0fe5, 0x0fc5019b, 0x00a30fea, 0x0fc501ae,
+ 0x008c0fed, 0x0fc601c1, 0x00740ff2, 0x0fc901d1,
+ 0x005e0ff5, 0x0fce01df, 0x004b0ff8, 0x0fd301ea,
+ 0x00370ffc, 0x0fda01f3, 0x00260ffd, 0x0fe201fb,
+ 0x00170000, 0x0fea01ff, 0x00090000, 0x0ff50202,
+ 0x02000000, 0x00000000, 0x02010ff7, 0x00000008,
+ 0x01ff0fee, 0x00000013, 0x01fb0fe7, 0x0ffe0020,
+ 0x01f60fe0, 0x0ffc002e, 0x01ed0fda, 0x0ffa003f,
+ 0x01e40fd6, 0x0ff7004f, 0x01d80fd2, 0x0ff40062,
+ 0x01ca0fcf, 0x0ff00077, 0x01bb0fcd, 0x0fed008b,
+ 0x01a90fcd, 0x0fe900a1, 0x01960fcd, 0x0fe600b7,
+ 0x01830fcd, 0x0fe200ce, 0x016d0fcf, 0x0fde00e6,
+ 0x01580fd0, 0x0fdb00fd, 0x01410fd3, 0x0fd80114,
+ 0x012c0fd4, 0x0fd4012c, 0x01140fd8, 0x0fd30141,
+ 0x00fd0fdb, 0x0fd00158, 0x00e60fde, 0x0fcf016d,
+ 0x00ce0fe2, 0x0fcd0183, 0x00b70fe6, 0x0fcd0196,
+ 0x00a10fe9, 0x0fcd01a9, 0x008b0fed, 0x0fcd01bb,
+ 0x00770ff0, 0x0fcf01ca, 0x00620ff4, 0x0fd201d8,
+ 0x004f0ff7, 0x0fd601e4, 0x003f0ffa, 0x0fda01ed,
+ 0x002e0ffc, 0x0fe001f6, 0x00200ffe, 0x0fe701fb,
+ 0x00130000, 0x0fee01ff, 0x00080000, 0x0ff70201,
+ 0x02000000, 0x00000000, 0x01ff0ff7, 0x0000000a,
+ 0x01f90fee, 0x00000019, 0x01f10fe7, 0x0ffe002a,
+ 0x01e60fe1, 0x0ffd003c, 0x01d90fdc, 0x0ffa0051,
+ 0x01cc0fd8, 0x0ff70065, 0x01bb0fd5, 0x0ff5007b,
+ 0x01a80fd3, 0x0ff10094, 0x01950fd2, 0x0fef00aa,
+ 0x01800fd2, 0x0feb00c3, 0x016a0fd3, 0x0fe900da,
+ 0x01540fd3, 0x0fe600f3, 0x013f0fd5, 0x0fe2010a,
+ 0x01280fd7, 0x0fe00121, 0x01100fda, 0x0fde0138,
+ 0x00fb0fdb, 0x0fdb014f, 0x00e40fdf, 0x0fdb0162,
+ 0x00ce0fe2, 0x0fd90177, 0x00b90fe4, 0x0fd8018b,
+ 0x00a50fe8, 0x0fd8019b, 0x00910fec, 0x0fd801ab,
+ 0x007e0fee, 0x0fd801bc, 0x006c0ff2, 0x0fd901c9,
+ 0x005c0ff4, 0x0fda01d6, 0x004b0ff7, 0x0fdd01e1,
+ 0x003c0ff9, 0x0fe001eb, 0x002f0ffb, 0x0fe401f2,
+ 0x00230ffd, 0x0fe801f8, 0x00180ffe, 0x0fed01fd,
+ 0x000e0000, 0x0ff20200, 0x00060000, 0x0ff90201,
+ 0x02000000, 0x00000000, 0x02030ff9, 0x00000004,
+ 0x02050ff2, 0x00000009, 0x02050fed, 0x0ffe0010,
+ 0x02040fe7, 0x0ffd0018, 0x02020fe3, 0x0ffb0020,
+ 0x01fe0fdf, 0x0ff9002a, 0x01fa0fdb, 0x0ff70034,
+ 0x01f40fd8, 0x0ff30041, 0x01ed0fd6, 0x0ff0004d,
+ 0x01e30fd5, 0x0fec005c, 0x01d80fd4, 0x0fea006a,
+ 0x01cd0fd3, 0x0fe5007b, 0x01c00fd3, 0x0fe1008c,
+ 0x01b10fd3, 0x0fdd009f, 0x01a10fd4, 0x0fd900b2,
+ 0x01900fd4, 0x0fd400c8, 0x017b0fd7, 0x0fd100dd,
+ 0x01660fd9, 0x0fcd00f4, 0x01500fda, 0x0fca010c,
+ 0x01380fde, 0x0fc60124, 0x011e0fe2, 0x0fc5013b,
+ 0x01040fe4, 0x0fc30155, 0x00e70fe8, 0x0fc10170,
+ 0x00cc0feb, 0x0fc10188, 0x00ad0ff0, 0x0fc301a0,
+ 0x00900ff4, 0x0fc701b5, 0x00750ff7, 0x0fcc01c8,
+ 0x00580ffb, 0x0fd201db, 0x003e0ffd, 0x0fdb01ea,
+ 0x00250000, 0x0fe501f6, 0x000f0000, 0x0ff301fe,
+ 0x02000000, 0x00000000, 0x02020ff9, 0x00000005,
+ 0x02020ff2, 0x0000000c, 0x02010fed, 0x0ffe0014,
+ 0x01fe0fe8, 0x0ffd001d, 0x01fa0fe3, 0x0ffb0028,
+ 0x01f40fe0, 0x0ff90033, 0x01ed0fdc, 0x0ff70040,
+ 0x01e50fd9, 0x0ff3004f, 0x01db0fd7, 0x0ff1005d,
+ 0x01ce0fd7, 0x0fed006e, 0x01c00fd6, 0x0feb007f,
+ 0x01b30fd5, 0x0fe70091, 0x01a30fd6, 0x0fe300a4,
+ 0x01920fd6, 0x0fe000b8, 0x017e0fd8, 0x0fdd00cd,
+ 0x016c0fd8, 0x0fd800e4, 0x01560fdb, 0x0fd600f9,
+ 0x01400fdd, 0x0fd20111, 0x01290fdf, 0x0fd00128,
+ 0x01110fe2, 0x0fce013f, 0x00f80fe6, 0x0fcd0155,
+ 0x00de0fe8, 0x0fcc016e, 0x00c40fec, 0x0fcb0185,
+ 0x00ab0fef, 0x0fcb019b, 0x00900ff3, 0x0fcd01b0,
+ 0x00770ff6, 0x0fd101c2, 0x005f0ff9, 0x0fd501d3,
+ 0x00470ffc, 0x0fdb01e2, 0x00320ffd, 0x0fe201ef,
+ 0x001e0000, 0x0fea01f8, 0x000c0000, 0x0ff501ff,
+ 0x02000000, 0x00000000, 0x02010ff9, 0x00000006,
+ 0x02000ff2, 0x0000000e, 0x01fd0fed, 0x0ffe0018,
+ 0x01f80fe8, 0x0ffd0023, 0x01f20fe4, 0x0ffb002f,
+ 0x01eb0fe0, 0x0ff9003c, 0x01e10fdd, 0x0ff7004b,
+ 0x01d60fda, 0x0ff4005c, 0x01c90fd9, 0x0ff2006c,
+ 0x01bc0fd8, 0x0fee007e, 0x01ab0fd8, 0x0fec0091,
+ 0x019b0fd8, 0x0fe800a5, 0x018b0fd8, 0x0fe400b9,
+ 0x01770fd9, 0x0fe200ce, 0x01620fdb, 0x0fdf00e4,
+ 0x014f0fdb, 0x0fdb00fb, 0x01380fde, 0x0fda0110,
+ 0x01210fe0, 0x0fd70128, 0x010a0fe2, 0x0fd5013f,
+ 0x00f30fe6, 0x0fd30154, 0x00da0fe9, 0x0fd3016a,
+ 0x00c30feb, 0x0fd20180, 0x00aa0fef, 0x0fd20195,
+ 0x00940ff1, 0x0fd301a8, 0x007b0ff5, 0x0fd501bb,
+ 0x00650ff7, 0x0fd801cc, 0x00510ffa, 0x0fdc01d9,
+ 0x003c0ffd, 0x0fe101e6, 0x002a0ffe, 0x0fe701f1,
+ 0x00190000, 0x0fee01f9, 0x000a0000, 0x0ff701ff,
+ 0x02000000, 0x00000000, 0x01ff0ff9, 0x00000008,
+ 0x01fb0ff2, 0x00000013, 0x01f50fed, 0x0ffe0020,
+ 0x01ed0fe8, 0x0ffd002e, 0x01e30fe4, 0x0ffb003e,
+ 0x01d80fe1, 0x0ff9004e, 0x01cb0fde, 0x0ff70060,
+ 0x01bc0fdc, 0x0ff40074, 0x01ac0fdb, 0x0ff20087,
+ 0x019a0fdb, 0x0fef009c, 0x01870fdb, 0x0fed00b1,
+ 0x01740fdb, 0x0fea00c7, 0x01600fdc, 0x0fe700dd,
+ 0x014b0fdd, 0x0fe500f3, 0x01350fdf, 0x0fe30109,
+ 0x01200fe0, 0x0fe00120, 0x01090fe3, 0x0fdf0135,
+ 0x00f30fe5, 0x0fdd014b, 0x00dd0fe7, 0x0fdc0160,
+ 0x00c70fea, 0x0fdb0174, 0x00b10fed, 0x0fdb0187,
+ 0x009c0fef, 0x0fdb019a, 0x00870ff2, 0x0fdb01ac,
+ 0x00740ff4, 0x0fdc01bc, 0x00600ff7, 0x0fde01cb,
+ 0x004e0ff9, 0x0fe101d8, 0x003e0ffb, 0x0fe401e3,
+ 0x002e0ffd, 0x0fe801ed, 0x00200ffe, 0x0fed01f5,
+ 0x00130000, 0x0ff201fb, 0x00080000, 0x0ff901ff
+};
+
+
+#define MDP4_QSEED_TABLE0_OFF 0x8100
+#define MDP4_QSEED_TABLE1_OFF 0x8200
+#define MDP4_QSEED_TABLE2_OFF 0x9000
+
+void mdp4_vg_qseed_init(int vp_num)
+{
+ uint32 *off;
+ int i, voff;
+
+ voff = MDP4_VIDEO_OFF * vp_num;
+ off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+ MDP4_QSEED_TABLE0_OFF);
+ for (i = 0; i < (sizeof(vg_qseed_table0) / sizeof(uint32)); i++) {
+ outpdw(off, vg_qseed_table0[i]);
+ off++;
+ }
+
+ off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+ MDP4_QSEED_TABLE1_OFF);
+ for (i = 0; i < (sizeof(vg_qseed_table1) / sizeof(uint32)); i++) {
+ outpdw(off, vg_qseed_table1[i]);
+ off++;
+ }
+
+ off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+ MDP4_QSEED_TABLE2_OFF);
+ for (i = 0; i < (sizeof(vg_qseed_table2) / sizeof(uint32)); i++) {
+ outpdw(off, vg_qseed_table2[i]);
+ off++;
+ }
+
+}
+
+void mdp4_mixer_blend_init(mixer_num)
+{
+ unsigned char *overlay_base;
+ int off;
+
+ if (mixer_num) /* mixer number, /dev/fb0, /dev/fb1 */
+ overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
+ else
+ overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+
+ /* stage 0 to stage 2 */
+ off = 0;
+ outpdw(overlay_base + off + 0x104, 0x010);
+ outpdw(overlay_base + off + 0x108, 0xff);/* FG */
+ outpdw(overlay_base + off + 0x10c, 0x00);/* BG */
+
+ off += 0x20;
+ outpdw(overlay_base + off + 0x104, 0x010);
+ outpdw(overlay_base + off + 0x108, 0xff);/* FG */
+ outpdw(overlay_base + off + 0x10c, 0x00);/* BG */
+
+ off += 0x20;
+ outpdw(overlay_base + off + 0x104, 0x010);
+ outpdw(overlay_base + off + 0x108, 0xff);/* FG */
+ outpdw(overlay_base + off + 0x10c, 0x00);/* BG */
+}
+
+
+static uint32 csc_matrix_tab[9] = {
+ 0x0254, 0x0000, 0x0331,
+ 0x0254, 0xff37, 0xfe60,
+ 0x0254, 0x0409, 0x0000
+};
+
+static uint32 csc_pre_bv_tab[3] = {0xfff0, 0xff80, 0xff80 };
+static uint32 csc_post_bv_tab[3] = {0, 0, 0 };
+
+static uint32 csc_pre_lv_tab[6] = {0, 0xff, 0, 0xff, 0, 0xff };
+static uint32 csc_post_lv_tab[6] = {0, 0xff, 0, 0xff, 0, 0xff };
+
+#define MDP4_CSC_MV_OFF 0x4400
+#define MDP4_CSC_PRE_BV_OFF 0x4500
+#define MDP4_CSC_POST_BV_OFF 0x4580
+#define MDP4_CSC_PRE_LV_OFF 0x4600
+#define MDP4_CSC_POST_LV_OFF 0x4680
+
+void mdp4_vg_csc_mv_setup(int vp_num)
+{
+ uint32 *off;
+ int i, voff;
+
+ voff = MDP4_VIDEO_OFF * vp_num;
+ off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+ MDP4_CSC_MV_OFF);
+ for (i = 0; i < 9; i++) {
+ outpdw(off, csc_matrix_tab[i]);
+ off++;
+ }
+}
+
+void mdp4_vg_csc_pre_bv_setup(int vp_num)
+{
+ uint32 *off;
+ int i, voff;
+
+ voff = MDP4_VIDEO_OFF * vp_num;
+ off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+ MDP4_CSC_PRE_BV_OFF);
+ for (i = 0; i < 3; i++) {
+ outpdw(off, csc_pre_bv_tab[i]);
+ off++;
+ }
+}
+
+void mdp4_vg_csc_post_bv_setup(int vp_num)
+{
+ uint32 *off;
+ int i, voff;
+
+ voff = MDP4_VIDEO_OFF * vp_num;
+ off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+ MDP4_CSC_POST_BV_OFF);
+ for (i = 0; i < 3; i++) {
+ outpdw(off, csc_post_bv_tab[i]);
+ off++;
+ }
+}
+
+void mdp4_vg_csc_pre_lv_setup(int vp_num)
+{
+ uint32 *off;
+ int i, voff;
+
+ voff = MDP4_VIDEO_OFF * vp_num;
+ off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+ MDP4_CSC_PRE_LV_OFF);
+
+ for (i = 0; i < 6; i++) {
+ outpdw(off, csc_pre_lv_tab[i]);
+ off++;
+ }
+}
+
+void mdp4_vg_csc_post_lv_setup(int vp_num)
+{
+ uint32 *off;
+ int i, voff;
+
+ voff = MDP4_VIDEO_OFF * vp_num;
+ off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+ MDP4_CSC_POST_LV_OFF);
+
+ for (i = 0; i < 6; i++) {
+ outpdw(off, csc_post_lv_tab[i]);
+ off++;
+ }
+}
+
+char gc_lut[] = {
+ 0x0, 0x1, 0x2, 0x2, 0x3, 0x4, 0x5, 0x6,
+ 0x6, 0x7, 0x8, 0x9, 0xA, 0xA, 0xB, 0xC,
+ 0xD, 0xD, 0xE, 0xF, 0xF, 0x10, 0x10, 0x11,
+ 0x12, 0x12, 0x13, 0x13, 0x14, 0x14, 0x15, 0x15,
+ 0x16, 0x16, 0x17, 0x17, 0x17, 0x18, 0x18, 0x19,
+ 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1C,
+ 0x1C, 0x1D, 0x1D, 0x1D, 0x1E, 0x1E, 0x1E, 0x1F,
+ 0x1F, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21,
+ 0x22, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24,
+ 0x24, 0x24, 0x25, 0x25, 0x25, 0x25, 0x26, 0x26,
+ 0x26, 0x26, 0x27, 0x27, 0x27, 0x28, 0x28, 0x28,
+ 0x28, 0x29, 0x29, 0x29, 0x29, 0x2A, 0x2A, 0x2A,
+ 0x2A, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2C, 0x2C,
+ 0x2C, 0x2C, 0x2D, 0x2D, 0x2D, 0x2D, 0x2E, 0x2E,
+ 0x2E, 0x2E, 0x2E, 0x2F, 0x2F, 0x2F, 0x2F, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31,
+ 0x31, 0x32, 0x32, 0x32, 0x32, 0x32, 0x33, 0x33,
+ 0x33, 0x33, 0x33, 0x34, 0x34, 0x34, 0x34, 0x34,
+ 0x35, 0x35, 0x35, 0x35, 0x35, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37,
+ 0x38, 0x38, 0x38, 0x38, 0x38, 0x39, 0x39, 0x39,
+ 0x39, 0x39, 0x39, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A,
+ 0x3A, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3C,
+ 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3D, 0x3D, 0x3D,
+ 0x3D, 0x3D, 0x3D, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E,
+ 0x3E, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41,
+ 0x41, 0x41, 0x41, 0x41, 0x42, 0x42, 0x42, 0x42,
+ 0x42, 0x42, 0x42, 0x43, 0x43, 0x43, 0x43, 0x43,
+ 0x43, 0x43, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
+ 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47,
+ 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x48, 0x48,
+ 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49,
+ 0x49, 0x49, 0x49, 0x49, 0x49, 0x4A, 0x4A, 0x4A,
+ 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4B, 0x4B, 0x4B,
+ 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4C, 0x4C, 0x4C,
+ 0x4C, 0x4C, 0x4C, 0x4C, 0x4D, 0x4D, 0x4D, 0x4D,
+ 0x4D, 0x4D, 0x4D, 0x4D, 0x4E, 0x4E, 0x4E, 0x4E,
+ 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4F, 0x4F, 0x4F,
+ 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x50, 0x50, 0x50,
+ 0x50, 0x50, 0x50, 0x50, 0x50, 0x51, 0x51, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x52, 0x52,
+ 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x53, 0x53,
+ 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x54,
+ 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56,
+ 0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+ 0x57, 0x57, 0x57, 0x58, 0x58, 0x58, 0x58, 0x58,
+ 0x58, 0x58, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59,
+ 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B,
+ 0x5B, 0x5B, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
+ 0x5C, 0x5C, 0x5C, 0x5C, 0x5D, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5E, 0x5E,
+ 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E,
+ 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F,
+ 0x5F, 0x5F, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61,
+ 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x62,
+ 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62,
+ 0x62, 0x62, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x64, 0x64, 0x64,
+ 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
+ 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
+ 0x65, 0x65, 0x65, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x67, 0x67,
+ 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67,
+ 0x67, 0x67, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68,
+ 0x68, 0x68, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69,
+ 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+ 0x69, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
+ 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6B, 0x6B, 0x6B,
+ 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B,
+ 0x6B, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C,
+ 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6D, 0x6D, 0x6D,
+ 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D,
+ 0x6D, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E,
+ 0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x6F, 0x6F, 0x6F,
+ 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F,
+ 0x6F, 0x6F, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
+ 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x71, 0x71,
+ 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71,
+ 0x71, 0x71, 0x71, 0x72, 0x72, 0x72, 0x72, 0x72,
+ 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
+ 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+ 0x73, 0x73, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74,
+ 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74,
+ 0x74, 0x74, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75,
+ 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75,
+ 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
+ 0x76, 0x76, 0x76, 0x76, 0x76, 0x77, 0x77, 0x77,
+ 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
+ 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0x78, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79,
+ 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x7A, 0x7A,
+ 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A,
+ 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7B, 0x7B, 0x7B,
+ 0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B,
+ 0x7B, 0x7B, 0x7B, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C,
+ 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C,
+ 0x7C, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D,
+ 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D,
+ 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E,
+ 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82, 0x82,
+ 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
+ 0x82, 0x82, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
+ 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
+ 0x83, 0x83, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
+ 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
+ 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
+ 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
+ 0x85, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
+ 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
+ 0x86, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
+ 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
+ 0x87, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+ 0x88, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
+ 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
+ 0x89, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A,
+ 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A,
+ 0x8A, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B,
+ 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B,
+ 0x8B, 0x8B, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C,
+ 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C,
+ 0x8C, 0x8C, 0x8C, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D,
+ 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D,
+ 0x8D, 0x8D, 0x8D, 0x8D, 0x8E, 0x8E, 0x8E, 0x8E,
+ 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E,
+ 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8F, 0x8F, 0x8F,
+ 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F,
+ 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x90, 0x90,
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+ 0x91, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
+ 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
+ 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
+ 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
+ 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94,
+ 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+ 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x95, 0x95,
+ 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
+ 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
+ 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96,
+ 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96,
+ 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x97, 0x97,
+ 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97,
+ 0x97, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
+ 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
+ 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
+ 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
+ 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
+ 0x99, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+ 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+ 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9B, 0x9B, 0x9B,
+ 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B,
+ 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B,
+ 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C,
+ 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C,
+ 0x9C, 0x9C, 0x9C, 0x9C, 0x9D, 0x9D, 0x9D, 0x9D,
+ 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D,
+ 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9E,
+ 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E,
+ 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E,
+ 0x9E, 0x9E, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F,
+ 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F,
+ 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0xA0, 0xA0,
+ 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
+ 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
+ 0xA0, 0xA0, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1,
+ 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1,
+ 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA2, 0xA2,
+ 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2,
+ 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2,
+ 0xA2, 0xA2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3,
+ 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3,
+ 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA4, 0xA4,
+ 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4,
+ 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4,
+ 0xA4, 0xA4, 0xA4, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5,
+ 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5,
+ 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5,
+ 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6,
+ 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6,
+ 0xA6, 0xA6, 0xA6, 0xA6, 0xA7, 0xA7, 0xA7, 0xA7,
+ 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7,
+ 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7,
+ 0xA7, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8,
+ 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8,
+ 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA9,
+ 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9,
+ 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9,
+ 0xA9, 0xA9, 0xA9, 0xA9, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB,
+ 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB,
+ 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAC,
+ 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
+ 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
+ 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAD, 0xAD, 0xAD,
+ 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD,
+ 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD,
+ 0xAD, 0xAD, 0xAD, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE,
+ 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE,
+ 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE,
+ 0xAE, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF,
+ 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF,
+ 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xB0,
+ 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0,
+ 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0,
+ 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB1, 0xB1,
+ 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1,
+ 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1,
+ 0xB1, 0xB1, 0xB1, 0xB1, 0xB2, 0xB2, 0xB2, 0xB2,
+ 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2,
+ 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2,
+ 0xB2, 0xB2, 0xB2, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3,
+ 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3,
+ 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3,
+ 0xB3, 0xB3, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4,
+ 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4,
+ 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4,
+ 0xB4, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5,
+ 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5,
+ 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5,
+ 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
+ 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
+ 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
+ 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7,
+ 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7,
+ 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB8,
+ 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8,
+ 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8,
+ 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB9,
+ 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9,
+ 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9,
+ 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xBA,
+ 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA,
+ 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA,
+ 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBB,
+ 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
+ 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
+ 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
+ 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC,
+ 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC,
+ 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC,
+ 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD,
+ 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD,
+ 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD,
+ 0xBD, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE,
+ 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE,
+ 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE,
+ 0xBE, 0xBE, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF,
+ 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF,
+ 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF,
+ 0xBF, 0xBF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
+ 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
+ 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
+ 0xC0, 0xC0, 0xC0, 0xC0, 0xC1, 0xC1, 0xC1, 0xC1,
+ 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1,
+ 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1,
+ 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC2, 0xC2, 0xC2,
+ 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2,
+ 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2,
+ 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC3, 0xC3,
+ 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
+ 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
+ 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
+ 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4,
+ 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4,
+ 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4,
+ 0xC4, 0xC4, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5,
+ 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5,
+ 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5,
+ 0xC5, 0xC5, 0xC5, 0xC5, 0xC6, 0xC6, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
+ 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC7, 0xC7,
+ 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7,
+ 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7,
+ 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7,
+ 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
+ 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
+ 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
+ 0xC8, 0xC8, 0xC8, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9,
+ 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9,
+ 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9,
+ 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xCA, 0xCA,
+ 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA,
+ 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA,
+ 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA,
+ 0xCA, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB,
+ 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB,
+ 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB,
+ 0xCB, 0xCB, 0xCB, 0xCB, 0xCC, 0xCC, 0xCC, 0xCC,
+ 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
+ 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
+ 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCD,
+ 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD,
+ 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD,
+ 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD,
+ 0xCD, 0xCD, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE,
+ 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE,
+ 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE,
+ 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCF, 0xCF,
+ 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF,
+ 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF,
+ 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF,
+ 0xCF, 0xCF, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0,
+ 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0,
+ 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0,
+ 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD1, 0xD1, 0xD1,
+ 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1,
+ 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1,
+ 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1,
+ 0xD1, 0xD1, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+ 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+ 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+ 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD3, 0xD3,
+ 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3,
+ 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3,
+ 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3,
+ 0xD3, 0xD3, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4,
+ 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4,
+ 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4,
+ 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD5,
+ 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5,
+ 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5,
+ 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5,
+ 0xD5, 0xD5, 0xD5, 0xD5, 0xD6, 0xD6, 0xD6, 0xD6,
+ 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6,
+ 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6,
+ 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6,
+ 0xD6, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7,
+ 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7,
+ 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7,
+ 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD8, 0xD8,
+ 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8,
+ 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8,
+ 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8,
+ 0xD8, 0xD8, 0xD8, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9,
+ 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9,
+ 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9,
+ 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9,
+ 0xD9, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA,
+ 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA,
+ 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA,
+ 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDB, 0xDB,
+ 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB,
+ 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB,
+ 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB,
+ 0xDB, 0xDB, 0xDB, 0xDB, 0xDC, 0xDC, 0xDC, 0xDC,
+ 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC,
+ 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC,
+ 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC,
+ 0xDC, 0xDC, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
+ 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
+ 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
+ 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
+ 0xDD, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE,
+ 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE,
+ 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE,
+ 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDF,
+ 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF,
+ 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF,
+ 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF,
+ 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xE0, 0xE0,
+ 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
+ 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
+ 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
+ 0xE0, 0xE0, 0xE0, 0xE0, 0xE1, 0xE1, 0xE1, 0xE1,
+ 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1,
+ 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1,
+ 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1,
+ 0xE1, 0xE1, 0xE1, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2,
+ 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2,
+ 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2,
+ 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2,
+ 0xE2, 0xE2, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
+ 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
+ 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
+ 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
+ 0xE3, 0xE3, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4,
+ 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4,
+ 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4,
+ 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4,
+ 0xE4, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+ 0xE5, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
+ 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
+ 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
+ 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
+ 0xE6, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
+ 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
+ 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
+ 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
+ 0xE7, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
+ 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
+ 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
+ 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
+ 0xE8, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9,
+ 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9,
+ 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9,
+ 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9,
+ 0xE9, 0xE9, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA,
+ 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA,
+ 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA,
+ 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA,
+ 0xEA, 0xEA, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB,
+ 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB,
+ 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB,
+ 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB,
+ 0xEB, 0xEB, 0xEB, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC,
+ 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC,
+ 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC,
+ 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC,
+ 0xEC, 0xEC, 0xEC, 0xEC, 0xED, 0xED, 0xED, 0xED,
+ 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
+ 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
+ 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
+ 0xED, 0xED, 0xED, 0xED, 0xED, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
+ 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEF, 0xEF,
+ 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
+ 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
+ 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
+ 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
+ 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
+ 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
+ 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
+ 0xF1, 0xF1, 0xF1, 0xF1, 0xF2, 0xF2, 0xF2, 0xF2,
+ 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
+ 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
+ 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
+ 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF3, 0xF3,
+ 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3,
+ 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3,
+ 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3,
+ 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3,
+ 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4,
+ 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4,
+ 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4,
+ 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4,
+ 0xF4, 0xF4, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5,
+ 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5,
+ 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5,
+ 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5,
+ 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF6, 0xF6, 0xF6,
+ 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6,
+ 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6,
+ 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6,
+ 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6,
+ 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
+ 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
+ 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
+ 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
+ 0xF7, 0xF7, 0xF7, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
+ 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
+ 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
+ 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
+ 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF9, 0xF9,
+ 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9,
+ 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9,
+ 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9,
+ 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9,
+ 0xF9, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+ 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+ 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+ 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+ 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFB, 0xFB, 0xFB,
+ 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB,
+ 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB,
+ 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB,
+ 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB,
+ 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+ 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFD, 0xFD, 0xFD,
+ 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD,
+ 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD,
+ 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD,
+ 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD,
+ 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
+ 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
+ 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
+ 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
+ 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+void mdp4_mixer_gc_lut_setup(int mixer_num)
+{
+ unsigned char *base;
+ uint32 data;
+ char val;
+ int i, off;
+
+ if (mixer_num) /* mixer number, /dev/fb0, /dev/fb1 */
+ base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
+ else
+ base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+
+ base += 0x4000; /* GC_LUT offset */
+
+ off = 0;
+ for (i = 0; i < 4096; i++) {
+ val = gc_lut[i];
+ data = (val << 16 | val << 8 | val); /* R, B, and G are same */
+ outpdw(base + off, data);
+ off += 4;
+ }
+}
+
+uint32 igc_video_lut[] = { /* non linear */
+ 0x0, 0x1, 0x2, 0x4, 0x5, 0x6, 0x7, 0x9,
+ 0xA, 0xB, 0xC, 0xE, 0xF, 0x10, 0x12, 0x14,
+ 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F, 0x21, 0x23,
+ 0x25, 0x28, 0x2A, 0x2D, 0x30, 0x32, 0x35, 0x38,
+ 0x3B, 0x3E, 0x42, 0x45, 0x48, 0x4C, 0x4F, 0x53,
+ 0x57, 0x5B, 0x5F, 0x63, 0x67, 0x6B, 0x70, 0x74,
+ 0x79, 0x7E, 0x83, 0x88, 0x8D, 0x92, 0x97, 0x9C,
+ 0xA2, 0xA8, 0xAD, 0xB3, 0xB9, 0xBF, 0xC5, 0xCC,
+ 0xD2, 0xD8, 0xDF, 0xE6, 0xED, 0xF4, 0xFB, 0x102,
+ 0x109, 0x111, 0x118, 0x120, 0x128, 0x130, 0x138, 0x140,
+ 0x149, 0x151, 0x15A, 0x162, 0x16B, 0x174, 0x17D, 0x186,
+ 0x190, 0x199, 0x1A3, 0x1AC, 0x1B6, 0x1C0, 0x1CA, 0x1D5,
+ 0x1DF, 0x1EA, 0x1F4, 0x1FF, 0x20A, 0x215, 0x220, 0x22B,
+ 0x237, 0x242, 0x24E, 0x25A, 0x266, 0x272, 0x27F, 0x28B,
+ 0x298, 0x2A4, 0x2B1, 0x2BE, 0x2CB, 0x2D8, 0x2E6, 0x2F3,
+ 0x301, 0x30F, 0x31D, 0x32B, 0x339, 0x348, 0x356, 0x365,
+ 0x374, 0x383, 0x392, 0x3A1, 0x3B1, 0x3C0, 0x3D0, 0x3E0,
+ 0x3F0, 0x400, 0x411, 0x421, 0x432, 0x443, 0x454, 0x465,
+ 0x476, 0x487, 0x499, 0x4AB, 0x4BD, 0x4CF, 0x4E1, 0x4F3,
+ 0x506, 0x518, 0x52B, 0x53E, 0x551, 0x565, 0x578, 0x58C,
+ 0x5A0, 0x5B3, 0x5C8, 0x5DC, 0x5F0, 0x605, 0x61A, 0x62E,
+ 0x643, 0x659, 0x66E, 0x684, 0x699, 0x6AF, 0x6C5, 0x6DB,
+ 0x6F2, 0x708, 0x71F, 0x736, 0x74D, 0x764, 0x77C, 0x793,
+ 0x7AB, 0x7C3, 0x7DB, 0x7F3, 0x80B, 0x824, 0x83D, 0x855,
+ 0x86F, 0x888, 0x8A1, 0x8BB, 0x8D4, 0x8EE, 0x908, 0x923,
+ 0x93D, 0x958, 0x973, 0x98E, 0x9A9, 0x9C4, 0x9DF, 0x9FB,
+ 0xA17, 0xA33, 0xA4F, 0xA6C, 0xA88, 0xAA5, 0xAC2, 0xADF,
+ 0xAFC, 0xB19, 0xB37, 0xB55, 0xB73, 0xB91, 0xBAF, 0xBCE,
+ 0xBEC, 0xC0B, 0xC2A, 0xC4A, 0xC69, 0xC89, 0xCA8, 0xCC8,
+ 0xCE8, 0xD09, 0xD29, 0xD4A, 0xD6B, 0xD8C, 0xDAD, 0xDCF,
+ 0xDF0, 0xE12, 0xE34, 0xE56, 0xE79, 0xE9B, 0xEBE, 0xEE1,
+ 0xF04, 0xF27, 0xF4B, 0xF6E, 0xF92, 0xFB6, 0xFDB, 0xFFF,
+};
+
+void mdp4_vg_igc_lut_setup(int vp_num)
+{
+ unsigned char *base;
+ int i, voff, off;
+ uint32 data, val;
+
+ voff = MDP4_VIDEO_OFF * vp_num;
+ base = MDP_BASE + MDP4_VIDEO_BASE + voff + 0x5000;
+
+ off = 0;
+ for (i = 0; i < 256; i++) {
+ val = igc_video_lut[i];
+ data = (val << 16 | val); /* color 0 and 1 */
+ outpdw(base + off, data);
+ outpdw(base + off + 0x800, val); /* color 2 */
+ off += 4;
+ }
+}
+
+uint32 igc_rgb_lut[] = { /* linear */
+ 0x0, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
+ 0x80, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
+ 0x101, 0x111, 0x121, 0x131, 0x141, 0x151, 0x161, 0x171,
+ 0x181, 0x191, 0x1A2, 0x1B2, 0x1C2, 0x1D2, 0x1E2, 0x1F2,
+ 0x202, 0x212, 0x222, 0x232, 0x242, 0x252, 0x262, 0x272,
+ 0x282, 0x292, 0x2A2, 0x2B3, 0x2C3, 0x2D3, 0x2E3, 0x2F3,
+ 0x303, 0x313, 0x323, 0x333, 0x343, 0x353, 0x363, 0x373,
+ 0x383, 0x393, 0x3A3, 0x3B3, 0x3C4, 0x3D4, 0x3E4, 0x3F4,
+ 0x404, 0x414, 0x424, 0x434, 0x444, 0x454, 0x464, 0x474,
+ 0x484, 0x494, 0x4A4, 0x4B4, 0x4C4, 0x4D5, 0x4E5, 0x4F5,
+ 0x505, 0x515, 0x525, 0x535, 0x545, 0x555, 0x565, 0x575,
+ 0x585, 0x595, 0x5A5, 0x5B5, 0x5C5, 0x5D5, 0x5E6, 0x5F6,
+ 0x606, 0x616, 0x626, 0x636, 0x646, 0x656, 0x666, 0x676,
+ 0x686, 0x696, 0x6A6, 0x6B6, 0x6C6, 0x6D6, 0x6E6, 0x6F7,
+ 0x707, 0x717, 0x727, 0x737, 0x747, 0x757, 0x767, 0x777,
+ 0x787, 0x797, 0x7A7, 0x7B7, 0x7C7, 0x7D7, 0x7E7, 0x7F7,
+ 0x808, 0x818, 0x828, 0x838, 0x848, 0x858, 0x868, 0x878,
+ 0x888, 0x898, 0x8A8, 0x8B8, 0x8C8, 0x8D8, 0x8E8, 0x8F8,
+ 0x908, 0x919, 0x929, 0x939, 0x949, 0x959, 0x969, 0x979,
+ 0x989, 0x999, 0x9A9, 0x9B9, 0x9C9, 0x9D9, 0x9E9, 0x9F9,
+ 0xA09, 0xA19, 0xA2A, 0xA3A, 0xA4A, 0xA5A, 0xA6A, 0xA7A,
+ 0xA8A, 0xA9A, 0xAAA, 0xABA, 0xACA, 0xADA, 0xAEA, 0xAFA,
+ 0xB0A, 0xB1A, 0xB2A, 0xB3B, 0xB4B, 0xB5B, 0xB6B, 0xB7B,
+ 0xB8B, 0xB9B, 0xBAB, 0xBBB, 0xBCB, 0xBDB, 0xBEB, 0xBFB,
+ 0xC0B, 0xC1B, 0xC2B, 0xC3B, 0xC4C, 0xC5C, 0xC6C, 0xC7C,
+ 0xC8C, 0xC9C, 0xCAC, 0xCBC, 0xCCC, 0xCDC, 0xCEC, 0xCFC,
+ 0xD0C, 0xD1C, 0xD2C, 0xD3C, 0xD4C, 0xD5D, 0xD6D, 0xD7D,
+ 0xD8D, 0xD9D, 0xDAD, 0xDBD, 0xDCD, 0xDDD, 0xDED, 0xDFD,
+ 0xE0D, 0xE1D, 0xE2D, 0xE3D, 0xE4D, 0xE5D, 0xE6E, 0xE7E,
+ 0xE8E, 0xE9E, 0xEAE, 0xEBE, 0xECE, 0xEDE, 0xEEE, 0xEFE,
+ 0xF0E, 0xF1E, 0xF2E, 0xF3E, 0xF4E, 0xF5E, 0xF6E, 0xF7F,
+ 0xF8F, 0xF9F, 0xFAF, 0xFBF, 0xFCF, 0xFDF, 0xFEF, 0xFFF,
+};
+
+void mdp4_rgb_igc_lut_setup(int num)
+{
+ unsigned char *base;
+ int i, voff, off;
+ uint32 data, val;
+
+ voff = MDP4_RGB_OFF * num;
+ base = MDP_BASE + MDP4_RGB_BASE + voff + 0x5000;
+
+ off = 0;
+ for (i = 0; i < 256; i++) {
+ val = igc_rgb_lut[i];
+ data = (val << 16 | val); /* color 0 and 1 */
+ outpdw(base + off, data);
+ outpdw(base + off + 0x800, val); /* color 2 */
+ off += 4;
+ }
+}
diff --git a/drivers/staging/msm/mdp_cursor.c b/drivers/staging/msm/mdp_cursor.c
new file mode 100644
index 0000000..7d28f30
--- /dev/null
+++ b/drivers/staging/msm/mdp_cursor.c
@@ -0,0 +1,104 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+
+#include <mach/hardware.h>
+#include <asm/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+
+static int cursor_enabled;
+
+int mdp_hw_cursor_update(struct fb_info *info, struct fb_cursor *cursor)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ struct fb_image *img = &cursor->image;
+ int calpha_en, transp_en;
+ int alpha;
+ int ret = 0;
+
+ if ((img->width > MDP_CURSOR_WIDTH) ||
+ (img->height > MDP_CURSOR_HEIGHT) ||
+ (img->depth != 32))
+ return -EINVAL;
+
+ if (cursor->set & FB_CUR_SETPOS)
+ MDP_OUTP(MDP_BASE + 0x9004c, (img->dy << 16) | img->dx);
+
+ if (cursor->set & FB_CUR_SETIMAGE) {
+ ret = copy_from_user(mfd->cursor_buf, img->data,
+ img->width*img->height*4);
+ if (ret)
+ return ret;
+
+ if (img->bg_color == 0xffffffff)
+ transp_en = 0;
+ else
+ transp_en = 1;
+
+ alpha = (img->fg_color & 0xff000000) >> 24;
+
+ if (alpha)
+ calpha_en = 0x2; /* xrgb */
+ else
+ calpha_en = 0x1; /* argb */
+
+ MDP_OUTP(MDP_BASE + 0x90044, (img->height << 16) | img->width);
+ MDP_OUTP(MDP_BASE + 0x90048, mfd->cursor_buf_phys);
+ /* order the writes the cursor_buf before updating the
+ * hardware */
+// dma_coherent_pre_ops();
+ MDP_OUTP(MDP_BASE + 0x90060,
+ (transp_en << 3) | (calpha_en << 1) |
+ (inp32(MDP_BASE + 0x90060) & 0x1));
+#ifdef CONFIG_FB_MSM_MDP40
+ MDP_OUTP(MDP_BASE + 0x90064, (alpha << 24));
+ MDP_OUTP(MDP_BASE + 0x90068, (0xffffff & img->bg_color));
+ MDP_OUTP(MDP_BASE + 0x9006C, (0xffffff & img->bg_color));
+#else
+ MDP_OUTP(MDP_BASE + 0x90064,
+ (alpha << 24) | (0xffffff & img->bg_color));
+ MDP_OUTP(MDP_BASE + 0x90068, 0);
+#endif
+ }
+
+ if ((cursor->enable) && (!cursor_enabled)) {
+ cursor_enabled = 1;
+ MDP_OUTP(MDP_BASE + 0x90060, inp32(MDP_BASE + 0x90060) | 0x1);
+ } else if ((!cursor->enable) && (cursor_enabled)) {
+ cursor_enabled = 0;
+ MDP_OUTP(MDP_BASE + 0x90060,
+ inp32(MDP_BASE + 0x90060) & (~0x1));
+ }
+
+ return 0;
+}
diff --git a/drivers/staging/msm/mdp_dma.c b/drivers/staging/msm/mdp_dma.c
new file mode 100644
index 0000000..639918b
--- /dev/null
+++ b/drivers/staging/msm/mdp_dma.c
@@ -0,0 +1,561 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mddihost.h"
+
+static uint32 mdp_last_dma2_update_width;
+static uint32 mdp_last_dma2_update_height;
+static uint32 mdp_curr_dma2_update_width;
+static uint32 mdp_curr_dma2_update_height;
+
+ktime_t mdp_dma2_last_update_time = { 0 };
+
+int mdp_lcd_rd_cnt_offset_slow = 20;
+int mdp_lcd_rd_cnt_offset_fast = 20;
+int mdp_vsync_usec_wait_line_too_short = 5;
+uint32 mdp_dma2_update_time_in_usec;
+uint32 mdp_total_vdopkts;
+
+extern u32 msm_fb_debug_enabled;
+extern struct workqueue_struct *mdp_dma_wq;
+
+int vsync_start_y_adjust = 4;
+
+static void mdp_dma2_update_lcd(struct msm_fb_data_type *mfd)
+{
+ MDPIBUF *iBuf = &mfd->ibuf;
+ int mddi_dest = FALSE;
+ uint32 outBpp = iBuf->bpp;
+ uint32 dma2_cfg_reg;
+ uint8 *src;
+ uint32 mddi_ld_param;
+ uint16 mddi_vdo_packet_reg;
+ struct msm_fb_panel_data *pdata =
+ (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+ uint32 ystride = mfd->fbi->fix.line_length;
+
+ dma2_cfg_reg = DMA_PACK_TIGHT | DMA_PACK_ALIGN_LSB |
+ DMA_OUT_SEL_AHB | DMA_IBUF_NONCONTIGUOUS;
+
+#ifdef CONFIG_FB_MSM_MDP30
+ /*
+ * Software workaround: On 7x25/7x27, the MDP will not
+ * respond if dma_w is 1 pixel. Set the update width to
+ * 2 pixels and adjust the x offset if needed.
+ */
+ if (iBuf->dma_w == 1) {
+ iBuf->dma_w = 2;
+ if (iBuf->dma_x == (iBuf->ibuf_width - 2))
+ iBuf->dma_x--;
+ }
+#endif
+
+ if (mfd->fb_imgType == MDP_BGR_565)
+ dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
+ else
+ dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;
+
+ if (outBpp == 4)
+ dma2_cfg_reg |= DMA_IBUF_C3ALPHA_EN;
+
+ if (outBpp == 2)
+ dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB565;
+
+ mddi_ld_param = 0;
+ mddi_vdo_packet_reg = mfd->panel_info.mddi.vdopkt;
+
+ if ((mfd->panel_info.type == MDDI_PANEL) ||
+ (mfd->panel_info.type == EXT_MDDI_PANEL)) {
+ dma2_cfg_reg |= DMA_OUT_SEL_MDDI;
+ mddi_dest = TRUE;
+
+ if (mfd->panel_info.type == MDDI_PANEL) {
+ mdp_total_vdopkts++;
+ if (mfd->panel_info.pdest == DISPLAY_1) {
+ dma2_cfg_reg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY;
+ mddi_ld_param = 0;
+#ifdef MDDI_HOST_WINDOW_WORKAROUND
+ mddi_window_adjust(mfd, iBuf->dma_x,
+ iBuf->dma_w - 1, iBuf->dma_y,
+ iBuf->dma_h - 1);
+#endif
+ } else {
+ dma2_cfg_reg |=
+ DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY;
+ mddi_ld_param = 1;
+#ifdef MDDI_HOST_WINDOW_WORKAROUND
+ mddi_window_adjust(mfd, iBuf->dma_x,
+ iBuf->dma_w - 1, iBuf->dma_y,
+ iBuf->dma_h - 1);
+#endif
+ }
+ } else {
+ dma2_cfg_reg |= DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL;
+ mddi_ld_param = 2;
+ }
+ } else {
+ if (mfd->panel_info.pdest == DISPLAY_1) {
+ dma2_cfg_reg |= DMA_AHBM_LCD_SEL_PRIMARY;
+ outp32(MDP_EBI2_LCD0, mfd->data_port_phys);
+ } else {
+ dma2_cfg_reg |= DMA_AHBM_LCD_SEL_SECONDARY;
+ outp32(MDP_EBI2_LCD1, mfd->data_port_phys);
+ }
+ }
+
+ dma2_cfg_reg |= DMA_DITHER_EN;
+
+ src = (uint8 *) iBuf->buf;
+ /* starting input address */
+ src += iBuf->dma_x * outBpp + iBuf->dma_y * ystride;
+
+ mdp_curr_dma2_update_width = iBuf->dma_w;
+ mdp_curr_dma2_update_height = iBuf->dma_h;
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+#ifdef CONFIG_FB_MSM_MDP22
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0184,
+ (iBuf->dma_h << 16 | iBuf->dma_w));
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0188, src);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x018C, ystride);
+#else
+ MDP_OUTP(MDP_BASE + 0x90004, (iBuf->dma_h << 16 | iBuf->dma_w));
+ MDP_OUTP(MDP_BASE + 0x90008, src);
+ MDP_OUTP(MDP_BASE + 0x9000c, ystride);
+#endif
+
+ if (mfd->panel_info.bpp == 18) {
+ dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 666 18BPP */
+ DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
+ } else {
+ dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */
+ DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
+ }
+
+ if (mddi_dest) {
+#ifdef CONFIG_FB_MSM_MDP22
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0194,
+ (iBuf->dma_y << 16) | iBuf->dma_x);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01a0, mddi_ld_param);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01a4,
+ (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg);
+#else
+ MDP_OUTP(MDP_BASE + 0x90010, (iBuf->dma_y << 16) | iBuf->dma_x);
+ MDP_OUTP(MDP_BASE + 0x00090, mddi_ld_param);
+ MDP_OUTP(MDP_BASE + 0x00094,
+ (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg);
+#endif
+ } else {
+ /* setting EBI2 LCDC write window */
+ pdata->set_rect(iBuf->dma_x, iBuf->dma_y, iBuf->dma_w,
+ iBuf->dma_h);
+ }
+
+ /* dma2 config register */
+#ifdef MDP_HW_VSYNC
+ MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);
+
+ if ((mfd->use_mdp_vsync) &&
+ (mfd->ibuf.vsync_enable) && (mfd->panel_info.lcd.vsync_enable)) {
+ uint32 start_y;
+
+ if (vsync_start_y_adjust <= iBuf->dma_y)
+ start_y = iBuf->dma_y - vsync_start_y_adjust;
+ else
+ start_y =
+ (mfd->total_lcd_lines - 1) - (vsync_start_y_adjust -
+ iBuf->dma_y);
+
+ /*
+ * MDP VSYNC clock must be On by now so, we don't have to
+ * re-enable it
+ */
+ MDP_OUTP(MDP_BASE + 0x210, start_y);
+ MDP_OUTP(MDP_BASE + 0x20c, 1); /* enable prim vsync */
+ } else {
+ MDP_OUTP(MDP_BASE + 0x20c, 0); /* disable prim vsync */
+ }
+#else
+#ifdef CONFIG_FB_MSM_MDP22
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0180, dma2_cfg_reg);
+#else
+ MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);
+#endif
+#endif /* MDP_HW_VSYNC */
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+static ktime_t vt = { 0 };
+int mdp_usec_diff_threshold = 100;
+int mdp_expected_usec_wait;
+
+enum hrtimer_restart mdp_dma2_vsync_hrtimer_handler(struct hrtimer *ht)
+{
+ struct msm_fb_data_type *mfd = NULL;
+
+ mfd = container_of(ht, struct msm_fb_data_type, dma_hrtimer);
+
+ mdp_pipe_kickoff(MDP_DMA2_TERM, mfd);
+
+ if (msm_fb_debug_enabled) {
+ ktime_t t;
+ int usec_diff;
+ int actual_wait;
+
+ t = ktime_get_real();
+
+ actual_wait =
+ (t.tv.sec - vt.tv.sec) * 1000000 + (t.tv.nsec -
+ vt.tv.nsec) / 1000;
+ usec_diff = actual_wait - mdp_expected_usec_wait;
+
+ if ((mdp_usec_diff_threshold < usec_diff) || (usec_diff < 0))
+ MSM_FB_DEBUG
+ ("HRT Diff = %d usec Exp=%d usec Act=%d usec\n",
+ usec_diff, mdp_expected_usec_wait, actual_wait);
+ }
+
+ return HRTIMER_NORESTART;
+}
+
+static void mdp_dma_schedule(struct msm_fb_data_type *mfd, uint32 term)
+{
+ /*
+ * dma2 configure VSYNC block
+ * vsync supported on Primary LCD only for now
+ */
+ int32 mdp_lcd_rd_cnt;
+ uint32 usec_wait_time;
+ uint32 start_y;
+
+ /*
+ * ToDo: if we can move HRT timer callback to workqueue, we can
+ * move DMA2 power on under mdp_pipe_kickoff().
+ * This will save a power for hrt time wait.
+ * However if the latency for context switch (hrt irq -> workqueue)
+ * is too big, we will miss the vsync timing.
+ */
+ if (term == MDP_DMA2_TERM)
+ mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ mdp_dma2_update_time_in_usec =
+ MDP_KTIME2USEC(mdp_dma2_last_update_time);
+
+ if ((!mfd->ibuf.vsync_enable) || (!mfd->panel_info.lcd.vsync_enable)
+ || (mfd->use_mdp_vsync)) {
+ mdp_pipe_kickoff(term, mfd);
+ return;
+ }
+ /* SW vsync logic starts here */
+
+ /* get current rd counter */
+ mdp_lcd_rd_cnt = mdp_get_lcd_line_counter(mfd);
+ if (mdp_dma2_update_time_in_usec != 0) {
+ uint32 num, den;
+
+ /*
+ * roi width boundary calculation to know the size of pixel
+ * width that MDP can send faster or slower than LCD read
+ * pointer
+ */
+
+ num = mdp_last_dma2_update_width * mdp_last_dma2_update_height;
+ den =
+ (((mfd->panel_info.lcd.refx100 * mfd->total_lcd_lines) /
+ 1000) * (mdp_dma2_update_time_in_usec / 100)) / 1000;
+
+ if (den == 0)
+ mfd->vsync_width_boundary[mdp_last_dma2_update_width] =
+ mfd->panel_info.xres + 1;
+ else
+ mfd->vsync_width_boundary[mdp_last_dma2_update_width] =
+ (int)(num / den);
+ }
+
+ if (mfd->vsync_width_boundary[mdp_last_dma2_update_width] >
+ mdp_curr_dma2_update_width) {
+ /* MDP wrp is faster than LCD rdp */
+ mdp_lcd_rd_cnt += mdp_lcd_rd_cnt_offset_fast;
+ } else {
+ /* MDP wrp is slower than LCD rdp */
+ mdp_lcd_rd_cnt -= mdp_lcd_rd_cnt_offset_slow;
+ }
+
+ if (mdp_lcd_rd_cnt < 0)
+ mdp_lcd_rd_cnt = mfd->total_lcd_lines + mdp_lcd_rd_cnt;
+ else if (mdp_lcd_rd_cnt > mfd->total_lcd_lines)
+ mdp_lcd_rd_cnt = mdp_lcd_rd_cnt - mfd->total_lcd_lines - 1;
+
+ /* get wrt pointer position */
+ start_y = mfd->ibuf.dma_y;
+
+ /* measure line difference between start_y and rd counter */
+ if (start_y > mdp_lcd_rd_cnt) {
+ /*
+ * *100 for lcd_ref_hzx100 was already multiplied by 100
+ * *1000000 is for usec conversion
+ */
+
+ if ((start_y - mdp_lcd_rd_cnt) <=
+ mdp_vsync_usec_wait_line_too_short)
+ usec_wait_time = 0;
+ else
+ usec_wait_time =
+ ((start_y -
+ mdp_lcd_rd_cnt) * 1000000) /
+ ((mfd->total_lcd_lines *
+ mfd->panel_info.lcd.refx100) / 100);
+ } else {
+ if ((start_y + (mfd->total_lcd_lines - mdp_lcd_rd_cnt)) <=
+ mdp_vsync_usec_wait_line_too_short)
+ usec_wait_time = 0;
+ else
+ usec_wait_time =
+ ((start_y +
+ (mfd->total_lcd_lines -
+ mdp_lcd_rd_cnt)) * 1000000) /
+ ((mfd->total_lcd_lines *
+ mfd->panel_info.lcd.refx100) / 100);
+ }
+
+ mdp_last_dma2_update_width = mdp_curr_dma2_update_width;
+ mdp_last_dma2_update_height = mdp_curr_dma2_update_height;
+
+ if (usec_wait_time == 0) {
+ mdp_pipe_kickoff(term, mfd);
+ } else {
+ ktime_t wait_time;
+
+ wait_time.tv.sec = 0;
+ wait_time.tv.nsec = usec_wait_time * 1000;
+
+ if (msm_fb_debug_enabled) {
+ vt = ktime_get_real();
+ mdp_expected_usec_wait = usec_wait_time;
+ }
+ hrtimer_start(&mfd->dma_hrtimer, wait_time, HRTIMER_MODE_REL);
+ }
+}
+
+#ifdef MDDI_HOST_WINDOW_WORKAROUND
+void mdp_dma2_update(struct msm_fb_data_type *mfd)
+{
+ MDPIBUF *iBuf;
+ uint32 upper_height;
+
+ if (mfd->panel.type == EXT_MDDI_PANEL) {
+ mdp_dma2_update_sub(mfd);
+ return;
+ }
+
+ iBuf = &mfd->ibuf;
+
+ upper_height =
+ (uint32) mddi_assign_pkt_height((uint16) iBuf->dma_w,
+ (uint16) iBuf->dma_h, 18);
+
+ if (upper_height >= iBuf->dma_h) {
+ mdp_dma2_update_sub(mfd);
+ } else {
+ MDPIBUF lower_height;
+
+ /* sending the upper region first */
+ lower_height = iBuf->dma_h - upper_height;
+ iBuf->dma_h = upper_height;
+ mdp_dma2_update_sub(mfd);
+
+ /* sending the lower region second */
+ iBuf->dma_h = lower_height;
+ iBuf->dma_y += lower_height;
+ iBuf->vsync_enable = FALSE;
+ mdp_dma2_update_sub(mfd);
+ }
+}
+
+void mdp_dma2_update_sub(struct msm_fb_data_type *mfd)
+#else
+void mdp_dma2_update(struct msm_fb_data_type *mfd)
+#endif
+{
+ down(&mfd->dma->mutex);
+ if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
+ down(&mfd->sem);
+ mfd->ibuf_flushed = TRUE;
+ mdp_dma2_update_lcd(mfd);
+
+ mdp_enable_irq(MDP_DMA2_TERM);
+ mfd->dma->busy = TRUE;
+ INIT_COMPLETION(mfd->dma->comp);
+
+ /* schedule DMA to start */
+ mdp_dma_schedule(mfd, MDP_DMA2_TERM);
+ up(&mfd->sem);
+
+ /* wait until DMA finishes the current job */
+ wait_for_completion_killable(&mfd->dma->comp);
+ mdp_disable_irq(MDP_DMA2_TERM);
+
+ /* signal if pan function is waiting for the update completion */
+ if (mfd->pan_waiting) {
+ mfd->pan_waiting = FALSE;
+ complete(&mfd->pan_comp);
+ }
+ }
+ up(&mfd->dma->mutex);
+}
+
+void mdp_lcd_update_workqueue_handler(struct work_struct *work)
+{
+ struct msm_fb_data_type *mfd = NULL;
+
+ mfd = container_of(work, struct msm_fb_data_type, dma_update_worker);
+ if (mfd)
+ mfd->dma_fnc(mfd);
+}
+
+void mdp_set_dma_pan_info(struct fb_info *info, struct mdp_dirty_region *dirty,
+ boolean sync)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ MDPIBUF *iBuf;
+ int bpp = info->var.bits_per_pixel / 8;
+
+ down(&mfd->sem);
+ iBuf = &mfd->ibuf;
+ iBuf->buf = (uint8 *) info->fix.smem_start;
+ iBuf->buf += info->var.xoffset * bpp +
+ info->var.yoffset * info->fix.line_length;
+
+ iBuf->ibuf_width = info->var.xres_virtual;
+ iBuf->bpp = bpp;
+
+ iBuf->vsync_enable = sync;
+
+ if (dirty) {
+ /*
+ * ToDo: dirty region check inside var.xoffset+xres
+ * <-> var.yoffset+yres
+ */
+ iBuf->dma_x = dirty->xoffset % info->var.xres;
+ iBuf->dma_y = dirty->yoffset % info->var.yres;
+ iBuf->dma_w = dirty->width;
+ iBuf->dma_h = dirty->height;
+ } else {
+ iBuf->dma_x = 0;
+ iBuf->dma_y = 0;
+ iBuf->dma_w = info->var.xres;
+ iBuf->dma_h = info->var.yres;
+ }
+ mfd->ibuf_flushed = FALSE;
+ up(&mfd->sem);
+}
+
+void mdp_set_offset_info(struct fb_info *info, uint32 addr, uint32 sync)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ MDPIBUF *iBuf;
+
+ int bpp = info->var.bits_per_pixel / 8;
+
+ down(&mfd->sem);
+ iBuf = &mfd->ibuf;
+ iBuf->ibuf_width = info->var.xres_virtual;
+ iBuf->bpp = bpp;
+ iBuf->vsync_enable = sync;
+ iBuf->dma_x = 0;
+ iBuf->dma_y = 0;
+ iBuf->dma_w = info->var.xres;
+ iBuf->dma_h = info->var.yres;
+ iBuf->buf = (uint8 *) addr;
+
+ mfd->ibuf_flushed = FALSE;
+ up(&mfd->sem);
+}
+
+void mdp_dma_pan_update(struct fb_info *info)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ MDPIBUF *iBuf;
+
+ iBuf = &mfd->ibuf;
+
+ if (mfd->sw_currently_refreshing) {
+ /* we need to wait for the pending update */
+ mfd->pan_waiting = TRUE;
+ if (!mfd->ibuf_flushed) {
+ wait_for_completion_killable(&mfd->pan_comp);
+ }
+ /* waiting for this update to complete */
+ mfd->pan_waiting = TRUE;
+ wait_for_completion_killable(&mfd->pan_comp);
+ } else
+ mfd->dma_fnc(mfd);
+}
+
+void mdp_refresh_screen(unsigned long data)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data;
+
+ if ((mfd->sw_currently_refreshing) && (mfd->sw_refreshing_enable)) {
+ init_timer(&mfd->refresh_timer);
+ mfd->refresh_timer.function = mdp_refresh_screen;
+ mfd->refresh_timer.data = data;
+
+ if (mfd->dma->busy)
+ /* come back in 1 msec */
+ mfd->refresh_timer.expires = jiffies + (HZ / 1000);
+ else
+ mfd->refresh_timer.expires =
+ jiffies + mfd->refresh_timer_duration;
+
+ add_timer(&mfd->refresh_timer);
+
+ if (!mfd->dma->busy) {
+ if (!queue_work(mdp_dma_wq, &mfd->dma_update_worker)) {
+ MSM_FB_DEBUG("mdp_dma: can't queue_work! -> \
+ MDP/MDDI/LCD clock speed needs to be increased\n");
+ }
+ }
+ } else {
+ if (!mfd->hw_refresh)
+ complete(&mfd->refresher_comp);
+ }
+}
diff --git a/drivers/staging/msm/mdp_dma_lcdc.c b/drivers/staging/msm/mdp_dma_lcdc.c
new file mode 100644
index 0000000..b57fa1a
--- /dev/null
+++ b/drivers/staging/msm/mdp_dma_lcdc.c
@@ -0,0 +1,379 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+#ifdef CONFIG_FB_MSM_MDP40
+#define LCDC_BASE 0xC0000
+#define DTV_BASE 0xD0000
+#define DMA_E_BASE 0xB0000
+#else
+#define LCDC_BASE 0xE0000
+#endif
+
+#define DMA_P_BASE 0x90000
+
+extern spinlock_t mdp_spin_lock;
+#ifndef CONFIG_FB_MSM_MDP40
+extern uint32 mdp_intr_mask;
+#endif
+
+int first_pixel_start_x;
+int first_pixel_start_y;
+
+int mdp_lcdc_on(struct platform_device *pdev)
+{
+ int lcdc_width;
+ int lcdc_height;
+ int lcdc_bpp;
+ int lcdc_border_clr;
+ int lcdc_underflow_clr;
+ int lcdc_hsync_skew;
+
+ int hsync_period;
+ int hsync_ctrl;
+ int vsync_period;
+ int display_hctl;
+ int display_v_start;
+ int display_v_end;
+ int active_hctl;
+ int active_h_start;
+ int active_h_end;
+ int active_v_start;
+ int active_v_end;
+ int ctrl_polarity;
+ int h_back_porch;
+ int h_front_porch;
+ int v_back_porch;
+ int v_front_porch;
+ int hsync_pulse_width;
+ int vsync_pulse_width;
+ int hsync_polarity;
+ int vsync_polarity;
+ int data_en_polarity;
+ int hsync_start_x;
+ int hsync_end_x;
+ uint8 *buf;
+ int bpp;
+ uint32 dma2_cfg_reg;
+ struct fb_info *fbi;
+ struct fb_var_screeninfo *var;
+ struct msm_fb_data_type *mfd;
+ uint32 dma_base;
+ uint32 timer_base = LCDC_BASE;
+ uint32 block = MDP_DMA2_BLOCK;
+ int ret;
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ fbi = mfd->fbi;
+ var = &fbi->var;
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf += fbi->var.xoffset * bpp + fbi->var.yoffset * fbi->fix.line_length;
+
+ dma2_cfg_reg = DMA_PACK_ALIGN_LSB | DMA_DITHER_EN | DMA_OUT_SEL_LCDC;
+
+ if (mfd->fb_imgType == MDP_BGR_565)
+ dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
+ else
+ dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;
+
+ if (bpp == 2)
+ dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB565;
+ else if (bpp == 3)
+ dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB888;
+ else
+ dma2_cfg_reg |= DMA_IBUF_FORMAT_xRGB8888_OR_ARGB8888;
+
+ switch (mfd->panel_info.bpp) {
+ case 24:
+ dma2_cfg_reg |= DMA_DSTC0G_8BITS |
+ DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
+ break;
+
+ case 18:
+ dma2_cfg_reg |= DMA_DSTC0G_6BITS |
+ DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
+ break;
+
+ case 16:
+ dma2_cfg_reg |= DMA_DSTC0G_6BITS |
+ DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
+ break;
+
+ default:
+ printk(KERN_ERR "mdp lcdc can't support format %d bpp!\n",
+ mfd->panel_info.bpp);
+ return -ENODEV;
+ }
+
+ /* DMA register config */
+
+ dma_base = DMA_P_BASE;
+
+#ifdef CONFIG_FB_MSM_MDP40
+ if (mfd->panel.type == HDMI_PANEL)
+ dma_base = DMA_E_BASE;
+#endif
+
+ /* starting address */
+ MDP_OUTP(MDP_BASE + dma_base + 0x8, (uint32) buf);
+ /* active window width and height */
+ MDP_OUTP(MDP_BASE + dma_base + 0x4, ((fbi->var.yres) << 16) |
+ (fbi->var.xres));
+ /* buffer ystride */
+ MDP_OUTP(MDP_BASE + dma_base + 0xc, fbi->fix.line_length);
+ /* x/y coordinate = always 0 for lcdc */
+ MDP_OUTP(MDP_BASE + dma_base + 0x10, 0);
+ /* dma config */
+ MDP_OUTP(MDP_BASE + dma_base, dma2_cfg_reg);
+
+ /*
+ * LCDC timing setting
+ */
+ h_back_porch = var->left_margin;
+ h_front_porch = var->right_margin;
+ v_back_porch = var->upper_margin;
+ v_front_porch = var->lower_margin;
+ hsync_pulse_width = var->hsync_len;
+ vsync_pulse_width = var->vsync_len;
+ lcdc_border_clr = mfd->panel_info.lcdc.border_clr;
+ lcdc_underflow_clr = mfd->panel_info.lcdc.underflow_clr;
+ lcdc_hsync_skew = mfd->panel_info.lcdc.hsync_skew;
+
+ lcdc_width = mfd->panel_info.xres;
+ lcdc_height = mfd->panel_info.yres;
+ lcdc_bpp = mfd->panel_info.bpp;
+
+ hsync_period =
+ hsync_pulse_width + h_back_porch + lcdc_width + h_front_porch;
+ hsync_ctrl = (hsync_period << 16) | hsync_pulse_width;
+ hsync_start_x = hsync_pulse_width + h_back_porch;
+ hsync_end_x = hsync_period - h_front_porch - 1;
+ display_hctl = (hsync_end_x << 16) | hsync_start_x;
+
+ vsync_period =
+ (vsync_pulse_width + v_back_porch + lcdc_height +
+ v_front_porch) * hsync_period;
+ display_v_start =
+ (vsync_pulse_width + v_back_porch) * hsync_period + lcdc_hsync_skew;
+ display_v_end =
+ vsync_period - (v_front_porch * hsync_period) + lcdc_hsync_skew - 1;
+
+ if (lcdc_width != var->xres) {
+ active_h_start = hsync_start_x + first_pixel_start_x;
+ active_h_end = active_h_start + var->xres - 1;
+ active_hctl =
+ ACTIVE_START_X_EN | (active_h_end << 16) | active_h_start;
+ } else {
+ active_hctl = 0;
+ }
+
+ if (lcdc_height != var->yres) {
+ active_v_start =
+ display_v_start + first_pixel_start_y * hsync_period;
+ active_v_end = active_v_start + (var->yres) * hsync_period - 1;
+ active_v_start |= ACTIVE_START_Y_EN;
+ } else {
+ active_v_start = 0;
+ active_v_end = 0;
+ }
+
+
+#ifdef CONFIG_FB_MSM_MDP40
+ if (mfd->panel.type == HDMI_PANEL) {
+ block = MDP_DMA_E_BLOCK;
+ timer_base = DTV_BASE;
+ hsync_polarity = 0;
+ vsync_polarity = 0;
+ } else {
+ hsync_polarity = 1;
+ vsync_polarity = 1;
+ }
+
+ lcdc_underflow_clr |= 0x80000000; /* enable recovery */
+#else
+ hsync_polarity = 0;
+ vsync_polarity = 0;
+#endif
+ data_en_polarity = 0;
+
+ ctrl_polarity =
+ (data_en_polarity << 2) | (vsync_polarity << 1) | (hsync_polarity);
+
+ MDP_OUTP(MDP_BASE + timer_base + 0x4, hsync_ctrl);
+ MDP_OUTP(MDP_BASE + timer_base + 0x8, vsync_period);
+ MDP_OUTP(MDP_BASE + timer_base + 0xc, vsync_pulse_width * hsync_period);
+ if (timer_base == LCDC_BASE) {
+ MDP_OUTP(MDP_BASE + timer_base + 0x10, display_hctl);
+ MDP_OUTP(MDP_BASE + timer_base + 0x14, display_v_start);
+ MDP_OUTP(MDP_BASE + timer_base + 0x18, display_v_end);
+ MDP_OUTP(MDP_BASE + timer_base + 0x28, lcdc_border_clr);
+ MDP_OUTP(MDP_BASE + timer_base + 0x2c, lcdc_underflow_clr);
+ MDP_OUTP(MDP_BASE + timer_base + 0x30, lcdc_hsync_skew);
+ MDP_OUTP(MDP_BASE + timer_base + 0x38, ctrl_polarity);
+ MDP_OUTP(MDP_BASE + timer_base + 0x1c, active_hctl);
+ MDP_OUTP(MDP_BASE + timer_base + 0x20, active_v_start);
+ MDP_OUTP(MDP_BASE + timer_base + 0x24, active_v_end);
+ } else {
+ MDP_OUTP(MDP_BASE + timer_base + 0x18, display_hctl);
+ MDP_OUTP(MDP_BASE + timer_base + 0x1c, display_v_start);
+ MDP_OUTP(MDP_BASE + timer_base + 0x20, display_v_end);
+ MDP_OUTP(MDP_BASE + timer_base + 0x40, lcdc_border_clr);
+ MDP_OUTP(MDP_BASE + timer_base + 0x44, lcdc_underflow_clr);
+ MDP_OUTP(MDP_BASE + timer_base + 0x48, lcdc_hsync_skew);
+ MDP_OUTP(MDP_BASE + timer_base + 0x50, ctrl_polarity);
+ MDP_OUTP(MDP_BASE + timer_base + 0x2c, active_hctl);
+ MDP_OUTP(MDP_BASE + timer_base + 0x30, active_v_start);
+ MDP_OUTP(MDP_BASE + timer_base + 0x38, active_v_end);
+ }
+
+ ret = panel_next_on(pdev);
+ if (ret == 0) {
+ /* enable LCDC block */
+ MDP_OUTP(MDP_BASE + timer_base, 1);
+ mdp_pipe_ctrl(block, MDP_BLOCK_POWER_ON, FALSE);
+ }
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ return ret;
+}
+
+int mdp_lcdc_off(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct msm_fb_data_type *mfd;
+ uint32 timer_base = LCDC_BASE;
+ uint32 block = MDP_DMA2_BLOCK;
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+#ifdef CONFIG_FB_MSM_MDP40
+ if (mfd->panel.type == HDMI_PANEL) {
+ block = MDP_DMA_E_BLOCK;
+ timer_base = DTV_BASE;
+ }
+#endif
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ MDP_OUTP(MDP_BASE + timer_base, 0);
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ mdp_pipe_ctrl(block, MDP_BLOCK_POWER_OFF, FALSE);
+
+ ret = panel_next_off(pdev);
+
+ /* delay to make sure the last frame finishes */
+ mdelay(100);
+
+ return ret;
+}
+
+void mdp_lcdc_update(struct msm_fb_data_type *mfd)
+{
+ struct fb_info *fbi = mfd->fbi;
+ uint8 *buf;
+ int bpp;
+ unsigned long flag;
+ uint32 dma_base;
+ int irq_block = MDP_DMA2_TERM;
+#ifdef CONFIG_FB_MSM_MDP40
+ int intr = INTR_DMA_P_DONE;
+#endif
+
+ if (!mfd->panel_power_on)
+ return;
+
+ /* no need to power on cmd block since it's lcdc mode */
+
+ if (!mfd->ibuf.visible_swapped) {
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf += fbi->var.xoffset * bpp +
+ fbi->var.yoffset * fbi->fix.line_length;
+ } else {
+ /* we've done something to update the pointer. */
+ bpp = mfd->ibuf.bpp;
+ buf = mfd->ibuf.buf;
+ }
+
+ dma_base = DMA_P_BASE;
+
+#ifdef CONFIG_FB_MSM_MDP40
+ if (mfd->panel.type == HDMI_PANEL) {
+ intr = INTR_DMA_E_DONE;
+ irq_block = MDP_DMA_E_TERM;
+ dma_base = DMA_E_BASE;
+ }
+#endif
+
+ /* starting address */
+ MDP_OUTP(MDP_BASE + dma_base + 0x8, (uint32) buf);
+
+ /* enable LCDC irq */
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ mdp_enable_irq(irq_block);
+ INIT_COMPLETION(mfd->dma->comp);
+ mfd->dma->waiting = TRUE;
+#ifdef CONFIG_FB_MSM_MDP40
+ outp32(MDP_INTR_CLEAR, intr);
+ mdp_intr_mask |= intr;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+#else
+ outp32(MDP_INTR_CLEAR, LCDC_FRAME_START);
+ mdp_intr_mask |= LCDC_FRAME_START;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+#endif
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+ if (mfd->ibuf.vsync_enable)
+ wait_for_completion_killable(&mfd->dma->comp);
+ mdp_disable_irq(irq_block);
+}
diff --git a/drivers/staging/msm/mdp_dma_s.c b/drivers/staging/msm/mdp_dma_s.c
new file mode 100644
index 0000000..0c34a10
--- /dev/null
+++ b/drivers/staging/msm/mdp_dma_s.c
@@ -0,0 +1,139 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+
+static void mdp_dma_s_update_lcd(struct msm_fb_data_type *mfd)
+{
+ MDPIBUF *iBuf = &mfd->ibuf;
+ int mddi_dest = FALSE;
+ uint32 outBpp = iBuf->bpp;
+ uint32 dma_s_cfg_reg;
+ uint8 *src;
+ struct msm_fb_panel_data *pdata =
+ (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+
+ dma_s_cfg_reg = DMA_PACK_TIGHT | DMA_PACK_ALIGN_LSB |
+ DMA_OUT_SEL_AHB | DMA_IBUF_NONCONTIGUOUS;
+
+ if (mfd->fb_imgType == MDP_BGR_565)
+ dma_s_cfg_reg |= DMA_PACK_PATTERN_BGR;
+ else
+ dma_s_cfg_reg |= DMA_PACK_PATTERN_RGB;
+
+ if (outBpp == 4)
+ dma_s_cfg_reg |= DMA_IBUF_C3ALPHA_EN;
+
+ if (outBpp == 2)
+ dma_s_cfg_reg |= DMA_IBUF_FORMAT_RGB565;
+
+ if (mfd->panel_info.pdest != DISPLAY_2) {
+ printk(KERN_ERR "error: non-secondary type through dma_s!\n");
+ return;
+ }
+
+ if (mfd->panel_info.type == MDDI_PANEL) {
+ dma_s_cfg_reg |= DMA_OUT_SEL_MDDI;
+ mddi_dest = TRUE;
+ } else {
+ dma_s_cfg_reg |= DMA_AHBM_LCD_SEL_SECONDARY;
+ outp32(MDP_EBI2_LCD1, mfd->data_port_phys);
+ }
+
+ dma_s_cfg_reg |= DMA_DITHER_EN;
+
+ src = (uint8 *) iBuf->buf;
+ /* starting input address */
+ src += (iBuf->dma_x + iBuf->dma_y * iBuf->ibuf_width) * outBpp;
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ /* PIXELSIZE */
+ MDP_OUTP(MDP_BASE + 0xa0004, (iBuf->dma_h << 16 | iBuf->dma_w));
+ MDP_OUTP(MDP_BASE + 0xa0008, src); /* ibuf address */
+ MDP_OUTP(MDP_BASE + 0xa000c, iBuf->ibuf_width * outBpp);/* ystride */
+
+ if (mfd->panel_info.bpp == 18) {
+ dma_s_cfg_reg |= DMA_DSTC0G_6BITS | /* 666 18BPP */
+ DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
+ } else {
+ dma_s_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */
+ DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
+ }
+
+ if (mddi_dest) {
+ MDP_OUTP(MDP_BASE + 0xa0010, (iBuf->dma_y << 16) | iBuf->dma_x);
+ MDP_OUTP(MDP_BASE + 0x00090, 1);
+ MDP_OUTP(MDP_BASE + 0x00094,
+ (MDDI_VDO_PACKET_DESC << 16) |
+ mfd->panel_info.mddi.vdopkt);
+ } else {
+ /* setting LCDC write window */
+ pdata->set_rect(iBuf->dma_x, iBuf->dma_y, iBuf->dma_w,
+ iBuf->dma_h);
+ }
+
+ MDP_OUTP(MDP_BASE + 0xa0000, dma_s_cfg_reg);
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ mdp_pipe_kickoff(MDP_DMA_S_TERM, mfd);
+}
+
+void mdp_dma_s_update(struct msm_fb_data_type *mfd)
+{
+ down(&mfd->dma->mutex);
+ if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
+ down(&mfd->sem);
+ mdp_enable_irq(MDP_DMA_S_TERM);
+ mfd->dma->busy = TRUE;
+ INIT_COMPLETION(mfd->dma->comp);
+ mfd->ibuf_flushed = TRUE;
+ mdp_dma_s_update_lcd(mfd);
+ up(&mfd->sem);
+
+ /* wait until DMA finishes the current job */
+ wait_for_completion_killable(&mfd->dma->comp);
+ mdp_disable_irq(MDP_DMA_S_TERM);
+
+ /* signal if pan function is waiting for the update completion */
+ if (mfd->pan_waiting) {
+ mfd->pan_waiting = FALSE;
+ complete(&mfd->pan_comp);
+ }
+ }
+ up(&mfd->dma->mutex);
+}
diff --git a/drivers/staging/msm/mdp_dma_tv.c b/drivers/staging/msm/mdp_dma_tv.c
new file mode 100644
index 0000000..70989fb
--- /dev/null
+++ b/drivers/staging/msm/mdp_dma_tv.c
@@ -0,0 +1,142 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+
+extern spinlock_t mdp_spin_lock;
+extern uint32 mdp_intr_mask;
+
+int mdp_dma3_on(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ struct fb_info *fbi;
+ uint8 *buf;
+ int bpp;
+ int ret = 0;
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ fbi = mfd->fbi;
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf += fbi->var.xoffset * bpp +
+ fbi->var.yoffset * fbi->fix.line_length;
+
+ /* starting address[31..8] of Video frame buffer is CS0 */
+ MDP_OUTP(MDP_BASE + 0xC0008, (uint32) buf >> 3);
+
+ mdp_pipe_ctrl(MDP_DMA3_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ MDP_OUTP(MDP_BASE + 0xC0004, 0x4c60674); /* flicker filter enabled */
+ MDP_OUTP(MDP_BASE + 0xC0010, 0x20); /* sobel treshold */
+
+ MDP_OUTP(MDP_BASE + 0xC0018, 0xeb0010); /* Y Max, Y min */
+ MDP_OUTP(MDP_BASE + 0xC001C, 0xf00010); /* Cb Max, Cb min */
+ MDP_OUTP(MDP_BASE + 0xC0020, 0xf00010); /* Cb Max, Cb min */
+
+ MDP_OUTP(MDP_BASE + 0xC000C, 0x67686970); /* add a few chars for CC */
+ MDP_OUTP(MDP_BASE + 0xC0000, 0x1); /* MDP tv out enable */
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ ret = panel_next_on(pdev);
+
+ return ret;
+}
+
+int mdp_dma3_off(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ ret = panel_next_off(pdev);
+ if (ret)
+ return ret;
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ MDP_OUTP(MDP_BASE + 0xC0000, 0x0);
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ mdp_pipe_ctrl(MDP_DMA3_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ /* delay to make sure the last frame finishes */
+ mdelay(100);
+
+ return ret;
+}
+
+void mdp_dma3_update(struct msm_fb_data_type *mfd)
+{
+ struct fb_info *fbi = mfd->fbi;
+ uint8 *buf;
+ int bpp;
+ unsigned long flag;
+
+ if (!mfd->panel_power_on)
+ return;
+
+ /* no need to power on cmd block since dma3 is running */
+ bpp = fbi->var.bits_per_pixel / 8;
+ buf = (uint8 *) fbi->fix.smem_start;
+ buf += fbi->var.xoffset * bpp +
+ fbi->var.yoffset * fbi->fix.line_length;
+ MDP_OUTP(MDP_BASE + 0xC0008, (uint32) buf >> 3);
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ mdp_enable_irq(MDP_DMA3_TERM);
+ INIT_COMPLETION(mfd->dma->comp);
+ mfd->dma->waiting = TRUE;
+
+ outp32(MDP_INTR_CLEAR, TV_OUT_DMA3_START);
+ mdp_intr_mask |= TV_OUT_DMA3_START;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+ wait_for_completion_killable(&mfd->dma->comp);
+ mdp_disable_irq(MDP_DMA3_TERM);
+}
diff --git a/drivers/staging/msm/mdp_hw_init.c b/drivers/staging/msm/mdp_hw_init.c
new file mode 100644
index 0000000..807362a
--- /dev/null
+++ b/drivers/staging/msm/mdp_hw_init.c
@@ -0,0 +1,720 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "mdp.h"
+
+/* mdp primary csc limit vector */
+uint32 mdp_plv[] = { 0x10, 0xeb, 0x10, 0xf0 };
+
+/* Color Coefficient matrix for YUV -> RGB */
+struct mdp_ccs mdp_ccs_yuv2rgb = {
+ MDP_CCS_YUV2RGB,
+ {
+ 0x254,
+ 0x000,
+ 0x331,
+ 0x254,
+ 0xff38,
+ 0xfe61,
+ 0x254,
+ 0x409,
+ 0x000,
+ },
+ {
+#ifdef CONFIG_FB_MSM_MDP31
+ 0x1f0,
+ 0x180,
+ 0x180
+#else
+ 0x10,
+ 0x80,
+ 0x80
+#endif
+ }
+};
+
+/* Color Coefficient matrix for RGB -> YUV */
+struct mdp_ccs mdp_ccs_rgb2yuv = {
+ MDP_CCS_RGB2YUV,
+ {
+ 0x83,
+ 0x102,
+ 0x32,
+ 0xffb5,
+ 0xff6c,
+ 0xe1,
+ 0xe1,
+ 0xff45,
+ 0xffdc,
+ },
+#ifdef CONFIG_FB_MSM_MDP31
+ {
+ 0x10,
+ 0x80,
+ 0x80
+ }
+#endif
+};
+
+static void mdp_load_lut_param(void)
+{
+ outpdw(MDP_BASE + 0x40800, 0x0);
+ outpdw(MDP_BASE + 0x40804, 0x151515);
+ outpdw(MDP_BASE + 0x40808, 0x1d1d1d);
+ outpdw(MDP_BASE + 0x4080c, 0x232323);
+ outpdw(MDP_BASE + 0x40810, 0x272727);
+ outpdw(MDP_BASE + 0x40814, 0x2b2b2b);
+ outpdw(MDP_BASE + 0x40818, 0x2f2f2f);
+ outpdw(MDP_BASE + 0x4081c, 0x333333);
+ outpdw(MDP_BASE + 0x40820, 0x363636);
+ outpdw(MDP_BASE + 0x40824, 0x393939);
+ outpdw(MDP_BASE + 0x40828, 0x3b3b3b);
+ outpdw(MDP_BASE + 0x4082c, 0x3e3e3e);
+ outpdw(MDP_BASE + 0x40830, 0x404040);
+ outpdw(MDP_BASE + 0x40834, 0x434343);
+ outpdw(MDP_BASE + 0x40838, 0x454545);
+ outpdw(MDP_BASE + 0x4083c, 0x474747);
+ outpdw(MDP_BASE + 0x40840, 0x494949);
+ outpdw(MDP_BASE + 0x40844, 0x4b4b4b);
+ outpdw(MDP_BASE + 0x40848, 0x4d4d4d);
+ outpdw(MDP_BASE + 0x4084c, 0x4f4f4f);
+ outpdw(MDP_BASE + 0x40850, 0x515151);
+ outpdw(MDP_BASE + 0x40854, 0x535353);
+ outpdw(MDP_BASE + 0x40858, 0x555555);
+ outpdw(MDP_BASE + 0x4085c, 0x565656);
+ outpdw(MDP_BASE + 0x40860, 0x585858);
+ outpdw(MDP_BASE + 0x40864, 0x5a5a5a);
+ outpdw(MDP_BASE + 0x40868, 0x5b5b5b);
+ outpdw(MDP_BASE + 0x4086c, 0x5d5d5d);
+ outpdw(MDP_BASE + 0x40870, 0x5e5e5e);
+ outpdw(MDP_BASE + 0x40874, 0x606060);
+ outpdw(MDP_BASE + 0x40878, 0x616161);
+ outpdw(MDP_BASE + 0x4087c, 0x636363);
+ outpdw(MDP_BASE + 0x40880, 0x646464);
+ outpdw(MDP_BASE + 0x40884, 0x666666);
+ outpdw(MDP_BASE + 0x40888, 0x676767);
+ outpdw(MDP_BASE + 0x4088c, 0x686868);
+ outpdw(MDP_BASE + 0x40890, 0x6a6a6a);
+ outpdw(MDP_BASE + 0x40894, 0x6b6b6b);
+ outpdw(MDP_BASE + 0x40898, 0x6c6c6c);
+ outpdw(MDP_BASE + 0x4089c, 0x6e6e6e);
+ outpdw(MDP_BASE + 0x408a0, 0x6f6f6f);
+ outpdw(MDP_BASE + 0x408a4, 0x707070);
+ outpdw(MDP_BASE + 0x408a8, 0x717171);
+ outpdw(MDP_BASE + 0x408ac, 0x727272);
+ outpdw(MDP_BASE + 0x408b0, 0x747474);
+ outpdw(MDP_BASE + 0x408b4, 0x757575);
+ outpdw(MDP_BASE + 0x408b8, 0x767676);
+ outpdw(MDP_BASE + 0x408bc, 0x777777);
+ outpdw(MDP_BASE + 0x408c0, 0x787878);
+ outpdw(MDP_BASE + 0x408c4, 0x797979);
+ outpdw(MDP_BASE + 0x408c8, 0x7a7a7a);
+ outpdw(MDP_BASE + 0x408cc, 0x7c7c7c);
+ outpdw(MDP_BASE + 0x408d0, 0x7d7d7d);
+ outpdw(MDP_BASE + 0x408d4, 0x7e7e7e);
+ outpdw(MDP_BASE + 0x408d8, 0x7f7f7f);
+ outpdw(MDP_BASE + 0x408dc, 0x808080);
+ outpdw(MDP_BASE + 0x408e0, 0x818181);
+ outpdw(MDP_BASE + 0x408e4, 0x828282);
+ outpdw(MDP_BASE + 0x408e8, 0x838383);
+ outpdw(MDP_BASE + 0x408ec, 0x848484);
+ outpdw(MDP_BASE + 0x408f0, 0x858585);
+ outpdw(MDP_BASE + 0x408f4, 0x868686);
+ outpdw(MDP_BASE + 0x408f8, 0x878787);
+ outpdw(MDP_BASE + 0x408fc, 0x888888);
+ outpdw(MDP_BASE + 0x40900, 0x898989);
+ outpdw(MDP_BASE + 0x40904, 0x8a8a8a);
+ outpdw(MDP_BASE + 0x40908, 0x8b8b8b);
+ outpdw(MDP_BASE + 0x4090c, 0x8c8c8c);
+ outpdw(MDP_BASE + 0x40910, 0x8d8d8d);
+ outpdw(MDP_BASE + 0x40914, 0x8e8e8e);
+ outpdw(MDP_BASE + 0x40918, 0x8f8f8f);
+ outpdw(MDP_BASE + 0x4091c, 0x8f8f8f);
+ outpdw(MDP_BASE + 0x40920, 0x909090);
+ outpdw(MDP_BASE + 0x40924, 0x919191);
+ outpdw(MDP_BASE + 0x40928, 0x929292);
+ outpdw(MDP_BASE + 0x4092c, 0x939393);
+ outpdw(MDP_BASE + 0x40930, 0x949494);
+ outpdw(MDP_BASE + 0x40934, 0x959595);
+ outpdw(MDP_BASE + 0x40938, 0x969696);
+ outpdw(MDP_BASE + 0x4093c, 0x969696);
+ outpdw(MDP_BASE + 0x40940, 0x979797);
+ outpdw(MDP_BASE + 0x40944, 0x989898);
+ outpdw(MDP_BASE + 0x40948, 0x999999);
+ outpdw(MDP_BASE + 0x4094c, 0x9a9a9a);
+ outpdw(MDP_BASE + 0x40950, 0x9b9b9b);
+ outpdw(MDP_BASE + 0x40954, 0x9c9c9c);
+ outpdw(MDP_BASE + 0x40958, 0x9c9c9c);
+ outpdw(MDP_BASE + 0x4095c, 0x9d9d9d);
+ outpdw(MDP_BASE + 0x40960, 0x9e9e9e);
+ outpdw(MDP_BASE + 0x40964, 0x9f9f9f);
+ outpdw(MDP_BASE + 0x40968, 0xa0a0a0);
+ outpdw(MDP_BASE + 0x4096c, 0xa0a0a0);
+ outpdw(MDP_BASE + 0x40970, 0xa1a1a1);
+ outpdw(MDP_BASE + 0x40974, 0xa2a2a2);
+ outpdw(MDP_BASE + 0x40978, 0xa3a3a3);
+ outpdw(MDP_BASE + 0x4097c, 0xa4a4a4);
+ outpdw(MDP_BASE + 0x40980, 0xa4a4a4);
+ outpdw(MDP_BASE + 0x40984, 0xa5a5a5);
+ outpdw(MDP_BASE + 0x40988, 0xa6a6a6);
+ outpdw(MDP_BASE + 0x4098c, 0xa7a7a7);
+ outpdw(MDP_BASE + 0x40990, 0xa7a7a7);
+ outpdw(MDP_BASE + 0x40994, 0xa8a8a8);
+ outpdw(MDP_BASE + 0x40998, 0xa9a9a9);
+ outpdw(MDP_BASE + 0x4099c, 0xaaaaaa);
+ outpdw(MDP_BASE + 0x409a0, 0xaaaaaa);
+ outpdw(MDP_BASE + 0x409a4, 0xababab);
+ outpdw(MDP_BASE + 0x409a8, 0xacacac);
+ outpdw(MDP_BASE + 0x409ac, 0xadadad);
+ outpdw(MDP_BASE + 0x409b0, 0xadadad);
+ outpdw(MDP_BASE + 0x409b4, 0xaeaeae);
+ outpdw(MDP_BASE + 0x409b8, 0xafafaf);
+ outpdw(MDP_BASE + 0x409bc, 0xafafaf);
+ outpdw(MDP_BASE + 0x409c0, 0xb0b0b0);
+ outpdw(MDP_BASE + 0x409c4, 0xb1b1b1);
+ outpdw(MDP_BASE + 0x409c8, 0xb2b2b2);
+ outpdw(MDP_BASE + 0x409cc, 0xb2b2b2);
+ outpdw(MDP_BASE + 0x409d0, 0xb3b3b3);
+ outpdw(MDP_BASE + 0x409d4, 0xb4b4b4);
+ outpdw(MDP_BASE + 0x409d8, 0xb4b4b4);
+ outpdw(MDP_BASE + 0x409dc, 0xb5b5b5);
+ outpdw(MDP_BASE + 0x409e0, 0xb6b6b6);
+ outpdw(MDP_BASE + 0x409e4, 0xb6b6b6);
+ outpdw(MDP_BASE + 0x409e8, 0xb7b7b7);
+ outpdw(MDP_BASE + 0x409ec, 0xb8b8b8);
+ outpdw(MDP_BASE + 0x409f0, 0xb8b8b8);
+ outpdw(MDP_BASE + 0x409f4, 0xb9b9b9);
+ outpdw(MDP_BASE + 0x409f8, 0xbababa);
+ outpdw(MDP_BASE + 0x409fc, 0xbababa);
+ outpdw(MDP_BASE + 0x40a00, 0xbbbbbb);
+ outpdw(MDP_BASE + 0x40a04, 0xbcbcbc);
+ outpdw(MDP_BASE + 0x40a08, 0xbcbcbc);
+ outpdw(MDP_BASE + 0x40a0c, 0xbdbdbd);
+ outpdw(MDP_BASE + 0x40a10, 0xbebebe);
+ outpdw(MDP_BASE + 0x40a14, 0xbebebe);
+ outpdw(MDP_BASE + 0x40a18, 0xbfbfbf);
+ outpdw(MDP_BASE + 0x40a1c, 0xc0c0c0);
+ outpdw(MDP_BASE + 0x40a20, 0xc0c0c0);
+ outpdw(MDP_BASE + 0x40a24, 0xc1c1c1);
+ outpdw(MDP_BASE + 0x40a28, 0xc1c1c1);
+ outpdw(MDP_BASE + 0x40a2c, 0xc2c2c2);
+ outpdw(MDP_BASE + 0x40a30, 0xc3c3c3);
+ outpdw(MDP_BASE + 0x40a34, 0xc3c3c3);
+ outpdw(MDP_BASE + 0x40a38, 0xc4c4c4);
+ outpdw(MDP_BASE + 0x40a3c, 0xc5c5c5);
+ outpdw(MDP_BASE + 0x40a40, 0xc5c5c5);
+ outpdw(MDP_BASE + 0x40a44, 0xc6c6c6);
+ outpdw(MDP_BASE + 0x40a48, 0xc6c6c6);
+ outpdw(MDP_BASE + 0x40a4c, 0xc7c7c7);
+ outpdw(MDP_BASE + 0x40a50, 0xc8c8c8);
+ outpdw(MDP_BASE + 0x40a54, 0xc8c8c8);
+ outpdw(MDP_BASE + 0x40a58, 0xc9c9c9);
+ outpdw(MDP_BASE + 0x40a5c, 0xc9c9c9);
+ outpdw(MDP_BASE + 0x40a60, 0xcacaca);
+ outpdw(MDP_BASE + 0x40a64, 0xcbcbcb);
+ outpdw(MDP_BASE + 0x40a68, 0xcbcbcb);
+ outpdw(MDP_BASE + 0x40a6c, 0xcccccc);
+ outpdw(MDP_BASE + 0x40a70, 0xcccccc);
+ outpdw(MDP_BASE + 0x40a74, 0xcdcdcd);
+ outpdw(MDP_BASE + 0x40a78, 0xcecece);
+ outpdw(MDP_BASE + 0x40a7c, 0xcecece);
+ outpdw(MDP_BASE + 0x40a80, 0xcfcfcf);
+ outpdw(MDP_BASE + 0x40a84, 0xcfcfcf);
+ outpdw(MDP_BASE + 0x40a88, 0xd0d0d0);
+ outpdw(MDP_BASE + 0x40a8c, 0xd0d0d0);
+ outpdw(MDP_BASE + 0x40a90, 0xd1d1d1);
+ outpdw(MDP_BASE + 0x40a94, 0xd2d2d2);
+ outpdw(MDP_BASE + 0x40a98, 0xd2d2d2);
+ outpdw(MDP_BASE + 0x40a9c, 0xd3d3d3);
+ outpdw(MDP_BASE + 0x40aa0, 0xd3d3d3);
+ outpdw(MDP_BASE + 0x40aa4, 0xd4d4d4);
+ outpdw(MDP_BASE + 0x40aa8, 0xd4d4d4);
+ outpdw(MDP_BASE + 0x40aac, 0xd5d5d5);
+ outpdw(MDP_BASE + 0x40ab0, 0xd6d6d6);
+ outpdw(MDP_BASE + 0x40ab4, 0xd6d6d6);
+ outpdw(MDP_BASE + 0x40ab8, 0xd7d7d7);
+ outpdw(MDP_BASE + 0x40abc, 0xd7d7d7);
+ outpdw(MDP_BASE + 0x40ac0, 0xd8d8d8);
+ outpdw(MDP_BASE + 0x40ac4, 0xd8d8d8);
+ outpdw(MDP_BASE + 0x40ac8, 0xd9d9d9);
+ outpdw(MDP_BASE + 0x40acc, 0xd9d9d9);
+ outpdw(MDP_BASE + 0x40ad0, 0xdadada);
+ outpdw(MDP_BASE + 0x40ad4, 0xdbdbdb);
+ outpdw(MDP_BASE + 0x40ad8, 0xdbdbdb);
+ outpdw(MDP_BASE + 0x40adc, 0xdcdcdc);
+ outpdw(MDP_BASE + 0x40ae0, 0xdcdcdc);
+ outpdw(MDP_BASE + 0x40ae4, 0xdddddd);
+ outpdw(MDP_BASE + 0x40ae8, 0xdddddd);
+ outpdw(MDP_BASE + 0x40aec, 0xdedede);
+ outpdw(MDP_BASE + 0x40af0, 0xdedede);
+ outpdw(MDP_BASE + 0x40af4, 0xdfdfdf);
+ outpdw(MDP_BASE + 0x40af8, 0xdfdfdf);
+ outpdw(MDP_BASE + 0x40afc, 0xe0e0e0);
+ outpdw(MDP_BASE + 0x40b00, 0xe0e0e0);
+ outpdw(MDP_BASE + 0x40b04, 0xe1e1e1);
+ outpdw(MDP_BASE + 0x40b08, 0xe1e1e1);
+ outpdw(MDP_BASE + 0x40b0c, 0xe2e2e2);
+ outpdw(MDP_BASE + 0x40b10, 0xe3e3e3);
+ outpdw(MDP_BASE + 0x40b14, 0xe3e3e3);
+ outpdw(MDP_BASE + 0x40b18, 0xe4e4e4);
+ outpdw(MDP_BASE + 0x40b1c, 0xe4e4e4);
+ outpdw(MDP_BASE + 0x40b20, 0xe5e5e5);
+ outpdw(MDP_BASE + 0x40b24, 0xe5e5e5);
+ outpdw(MDP_BASE + 0x40b28, 0xe6e6e6);
+ outpdw(MDP_BASE + 0x40b2c, 0xe6e6e6);
+ outpdw(MDP_BASE + 0x40b30, 0xe7e7e7);
+ outpdw(MDP_BASE + 0x40b34, 0xe7e7e7);
+ outpdw(MDP_BASE + 0x40b38, 0xe8e8e8);
+ outpdw(MDP_BASE + 0x40b3c, 0xe8e8e8);
+ outpdw(MDP_BASE + 0x40b40, 0xe9e9e9);
+ outpdw(MDP_BASE + 0x40b44, 0xe9e9e9);
+ outpdw(MDP_BASE + 0x40b48, 0xeaeaea);
+ outpdw(MDP_BASE + 0x40b4c, 0xeaeaea);
+ outpdw(MDP_BASE + 0x40b50, 0xebebeb);
+ outpdw(MDP_BASE + 0x40b54, 0xebebeb);
+ outpdw(MDP_BASE + 0x40b58, 0xececec);
+ outpdw(MDP_BASE + 0x40b5c, 0xececec);
+ outpdw(MDP_BASE + 0x40b60, 0xededed);
+ outpdw(MDP_BASE + 0x40b64, 0xededed);
+ outpdw(MDP_BASE + 0x40b68, 0xeeeeee);
+ outpdw(MDP_BASE + 0x40b6c, 0xeeeeee);
+ outpdw(MDP_BASE + 0x40b70, 0xefefef);
+ outpdw(MDP_BASE + 0x40b74, 0xefefef);
+ outpdw(MDP_BASE + 0x40b78, 0xf0f0f0);
+ outpdw(MDP_BASE + 0x40b7c, 0xf0f0f0);
+ outpdw(MDP_BASE + 0x40b80, 0xf1f1f1);
+ outpdw(MDP_BASE + 0x40b84, 0xf1f1f1);
+ outpdw(MDP_BASE + 0x40b88, 0xf2f2f2);
+ outpdw(MDP_BASE + 0x40b8c, 0xf2f2f2);
+ outpdw(MDP_BASE + 0x40b90, 0xf2f2f2);
+ outpdw(MDP_BASE + 0x40b94, 0xf3f3f3);
+ outpdw(MDP_BASE + 0x40b98, 0xf3f3f3);
+ outpdw(MDP_BASE + 0x40b9c, 0xf4f4f4);
+ outpdw(MDP_BASE + 0x40ba0, 0xf4f4f4);
+ outpdw(MDP_BASE + 0x40ba4, 0xf5f5f5);
+ outpdw(MDP_BASE + 0x40ba8, 0xf5f5f5);
+ outpdw(MDP_BASE + 0x40bac, 0xf6f6f6);
+ outpdw(MDP_BASE + 0x40bb0, 0xf6f6f6);
+ outpdw(MDP_BASE + 0x40bb4, 0xf7f7f7);
+ outpdw(MDP_BASE + 0x40bb8, 0xf7f7f7);
+ outpdw(MDP_BASE + 0x40bbc, 0xf8f8f8);
+ outpdw(MDP_BASE + 0x40bc0, 0xf8f8f8);
+ outpdw(MDP_BASE + 0x40bc4, 0xf9f9f9);
+ outpdw(MDP_BASE + 0x40bc8, 0xf9f9f9);
+ outpdw(MDP_BASE + 0x40bcc, 0xfafafa);
+ outpdw(MDP_BASE + 0x40bd0, 0xfafafa);
+ outpdw(MDP_BASE + 0x40bd4, 0xfafafa);
+ outpdw(MDP_BASE + 0x40bd8, 0xfbfbfb);
+ outpdw(MDP_BASE + 0x40bdc, 0xfbfbfb);
+ outpdw(MDP_BASE + 0x40be0, 0xfcfcfc);
+ outpdw(MDP_BASE + 0x40be4, 0xfcfcfc);
+ outpdw(MDP_BASE + 0x40be8, 0xfdfdfd);
+ outpdw(MDP_BASE + 0x40bec, 0xfdfdfd);
+ outpdw(MDP_BASE + 0x40bf0, 0xfefefe);
+ outpdw(MDP_BASE + 0x40bf4, 0xfefefe);
+ outpdw(MDP_BASE + 0x40bf8, 0xffffff);
+ outpdw(MDP_BASE + 0x40bfc, 0xffffff);
+ outpdw(MDP_BASE + 0x40c00, 0x0);
+ outpdw(MDP_BASE + 0x40c04, 0x0);
+ outpdw(MDP_BASE + 0x40c08, 0x0);
+ outpdw(MDP_BASE + 0x40c0c, 0x0);
+ outpdw(MDP_BASE + 0x40c10, 0x0);
+ outpdw(MDP_BASE + 0x40c14, 0x0);
+ outpdw(MDP_BASE + 0x40c18, 0x0);
+ outpdw(MDP_BASE + 0x40c1c, 0x0);
+ outpdw(MDP_BASE + 0x40c20, 0x0);
+ outpdw(MDP_BASE + 0x40c24, 0x0);
+ outpdw(MDP_BASE + 0x40c28, 0x0);
+ outpdw(MDP_BASE + 0x40c2c, 0x0);
+ outpdw(MDP_BASE + 0x40c30, 0x0);
+ outpdw(MDP_BASE + 0x40c34, 0x0);
+ outpdw(MDP_BASE + 0x40c38, 0x0);
+ outpdw(MDP_BASE + 0x40c3c, 0x0);
+ outpdw(MDP_BASE + 0x40c40, 0x10101);
+ outpdw(MDP_BASE + 0x40c44, 0x10101);
+ outpdw(MDP_BASE + 0x40c48, 0x10101);
+ outpdw(MDP_BASE + 0x40c4c, 0x10101);
+ outpdw(MDP_BASE + 0x40c50, 0x10101);
+ outpdw(MDP_BASE + 0x40c54, 0x10101);
+ outpdw(MDP_BASE + 0x40c58, 0x10101);
+ outpdw(MDP_BASE + 0x40c5c, 0x10101);
+ outpdw(MDP_BASE + 0x40c60, 0x10101);
+ outpdw(MDP_BASE + 0x40c64, 0x10101);
+ outpdw(MDP_BASE + 0x40c68, 0x20202);
+ outpdw(MDP_BASE + 0x40c6c, 0x20202);
+ outpdw(MDP_BASE + 0x40c70, 0x20202);
+ outpdw(MDP_BASE + 0x40c74, 0x20202);
+ outpdw(MDP_BASE + 0x40c78, 0x20202);
+ outpdw(MDP_BASE + 0x40c7c, 0x20202);
+ outpdw(MDP_BASE + 0x40c80, 0x30303);
+ outpdw(MDP_BASE + 0x40c84, 0x30303);
+ outpdw(MDP_BASE + 0x40c88, 0x30303);
+ outpdw(MDP_BASE + 0x40c8c, 0x30303);
+ outpdw(MDP_BASE + 0x40c90, 0x30303);
+ outpdw(MDP_BASE + 0x40c94, 0x40404);
+ outpdw(MDP_BASE + 0x40c98, 0x40404);
+ outpdw(MDP_BASE + 0x40c9c, 0x40404);
+ outpdw(MDP_BASE + 0x40ca0, 0x40404);
+ outpdw(MDP_BASE + 0x40ca4, 0x40404);
+ outpdw(MDP_BASE + 0x40ca8, 0x50505);
+ outpdw(MDP_BASE + 0x40cac, 0x50505);
+ outpdw(MDP_BASE + 0x40cb0, 0x50505);
+ outpdw(MDP_BASE + 0x40cb4, 0x50505);
+ outpdw(MDP_BASE + 0x40cb8, 0x60606);
+ outpdw(MDP_BASE + 0x40cbc, 0x60606);
+ outpdw(MDP_BASE + 0x40cc0, 0x60606);
+ outpdw(MDP_BASE + 0x40cc4, 0x70707);
+ outpdw(MDP_BASE + 0x40cc8, 0x70707);
+ outpdw(MDP_BASE + 0x40ccc, 0x70707);
+ outpdw(MDP_BASE + 0x40cd0, 0x70707);
+ outpdw(MDP_BASE + 0x40cd4, 0x80808);
+ outpdw(MDP_BASE + 0x40cd8, 0x80808);
+ outpdw(MDP_BASE + 0x40cdc, 0x80808);
+ outpdw(MDP_BASE + 0x40ce0, 0x90909);
+ outpdw(MDP_BASE + 0x40ce4, 0x90909);
+ outpdw(MDP_BASE + 0x40ce8, 0xa0a0a);
+ outpdw(MDP_BASE + 0x40cec, 0xa0a0a);
+ outpdw(MDP_BASE + 0x40cf0, 0xa0a0a);
+ outpdw(MDP_BASE + 0x40cf4, 0xb0b0b);
+ outpdw(MDP_BASE + 0x40cf8, 0xb0b0b);
+ outpdw(MDP_BASE + 0x40cfc, 0xb0b0b);
+ outpdw(MDP_BASE + 0x40d00, 0xc0c0c);
+ outpdw(MDP_BASE + 0x40d04, 0xc0c0c);
+ outpdw(MDP_BASE + 0x40d08, 0xd0d0d);
+ outpdw(MDP_BASE + 0x40d0c, 0xd0d0d);
+ outpdw(MDP_BASE + 0x40d10, 0xe0e0e);
+ outpdw(MDP_BASE + 0x40d14, 0xe0e0e);
+ outpdw(MDP_BASE + 0x40d18, 0xe0e0e);
+ outpdw(MDP_BASE + 0x40d1c, 0xf0f0f);
+ outpdw(MDP_BASE + 0x40d20, 0xf0f0f);
+ outpdw(MDP_BASE + 0x40d24, 0x101010);
+ outpdw(MDP_BASE + 0x40d28, 0x101010);
+ outpdw(MDP_BASE + 0x40d2c, 0x111111);
+ outpdw(MDP_BASE + 0x40d30, 0x111111);
+ outpdw(MDP_BASE + 0x40d34, 0x121212);
+ outpdw(MDP_BASE + 0x40d38, 0x121212);
+ outpdw(MDP_BASE + 0x40d3c, 0x131313);
+ outpdw(MDP_BASE + 0x40d40, 0x131313);
+ outpdw(MDP_BASE + 0x40d44, 0x141414);
+ outpdw(MDP_BASE + 0x40d48, 0x151515);
+ outpdw(MDP_BASE + 0x40d4c, 0x151515);
+ outpdw(MDP_BASE + 0x40d50, 0x161616);
+ outpdw(MDP_BASE + 0x40d54, 0x161616);
+ outpdw(MDP_BASE + 0x40d58, 0x171717);
+ outpdw(MDP_BASE + 0x40d5c, 0x171717);
+ outpdw(MDP_BASE + 0x40d60, 0x181818);
+ outpdw(MDP_BASE + 0x40d64, 0x191919);
+ outpdw(MDP_BASE + 0x40d68, 0x191919);
+ outpdw(MDP_BASE + 0x40d6c, 0x1a1a1a);
+ outpdw(MDP_BASE + 0x40d70, 0x1b1b1b);
+ outpdw(MDP_BASE + 0x40d74, 0x1b1b1b);
+ outpdw(MDP_BASE + 0x40d78, 0x1c1c1c);
+ outpdw(MDP_BASE + 0x40d7c, 0x1c1c1c);
+ outpdw(MDP_BASE + 0x40d80, 0x1d1d1d);
+ outpdw(MDP_BASE + 0x40d84, 0x1e1e1e);
+ outpdw(MDP_BASE + 0x40d88, 0x1f1f1f);
+ outpdw(MDP_BASE + 0x40d8c, 0x1f1f1f);
+ outpdw(MDP_BASE + 0x40d90, 0x202020);
+ outpdw(MDP_BASE + 0x40d94, 0x212121);
+ outpdw(MDP_BASE + 0x40d98, 0x212121);
+ outpdw(MDP_BASE + 0x40d9c, 0x222222);
+ outpdw(MDP_BASE + 0x40da0, 0x232323);
+ outpdw(MDP_BASE + 0x40da4, 0x242424);
+ outpdw(MDP_BASE + 0x40da8, 0x242424);
+ outpdw(MDP_BASE + 0x40dac, 0x252525);
+ outpdw(MDP_BASE + 0x40db0, 0x262626);
+ outpdw(MDP_BASE + 0x40db4, 0x272727);
+ outpdw(MDP_BASE + 0x40db8, 0x272727);
+ outpdw(MDP_BASE + 0x40dbc, 0x282828);
+ outpdw(MDP_BASE + 0x40dc0, 0x292929);
+ outpdw(MDP_BASE + 0x40dc4, 0x2a2a2a);
+ outpdw(MDP_BASE + 0x40dc8, 0x2b2b2b);
+ outpdw(MDP_BASE + 0x40dcc, 0x2c2c2c);
+ outpdw(MDP_BASE + 0x40dd0, 0x2c2c2c);
+ outpdw(MDP_BASE + 0x40dd4, 0x2d2d2d);
+ outpdw(MDP_BASE + 0x40dd8, 0x2e2e2e);
+ outpdw(MDP_BASE + 0x40ddc, 0x2f2f2f);
+ outpdw(MDP_BASE + 0x40de0, 0x303030);
+ outpdw(MDP_BASE + 0x40de4, 0x313131);
+ outpdw(MDP_BASE + 0x40de8, 0x323232);
+ outpdw(MDP_BASE + 0x40dec, 0x333333);
+ outpdw(MDP_BASE + 0x40df0, 0x333333);
+ outpdw(MDP_BASE + 0x40df4, 0x343434);
+ outpdw(MDP_BASE + 0x40df8, 0x353535);
+ outpdw(MDP_BASE + 0x40dfc, 0x363636);
+ outpdw(MDP_BASE + 0x40e00, 0x373737);
+ outpdw(MDP_BASE + 0x40e04, 0x383838);
+ outpdw(MDP_BASE + 0x40e08, 0x393939);
+ outpdw(MDP_BASE + 0x40e0c, 0x3a3a3a);
+ outpdw(MDP_BASE + 0x40e10, 0x3b3b3b);
+ outpdw(MDP_BASE + 0x40e14, 0x3c3c3c);
+ outpdw(MDP_BASE + 0x40e18, 0x3d3d3d);
+ outpdw(MDP_BASE + 0x40e1c, 0x3e3e3e);
+ outpdw(MDP_BASE + 0x40e20, 0x3f3f3f);
+ outpdw(MDP_BASE + 0x40e24, 0x404040);
+ outpdw(MDP_BASE + 0x40e28, 0x414141);
+ outpdw(MDP_BASE + 0x40e2c, 0x424242);
+ outpdw(MDP_BASE + 0x40e30, 0x434343);
+ outpdw(MDP_BASE + 0x40e34, 0x444444);
+ outpdw(MDP_BASE + 0x40e38, 0x464646);
+ outpdw(MDP_BASE + 0x40e3c, 0x474747);
+ outpdw(MDP_BASE + 0x40e40, 0x484848);
+ outpdw(MDP_BASE + 0x40e44, 0x494949);
+ outpdw(MDP_BASE + 0x40e48, 0x4a4a4a);
+ outpdw(MDP_BASE + 0x40e4c, 0x4b4b4b);
+ outpdw(MDP_BASE + 0x40e50, 0x4c4c4c);
+ outpdw(MDP_BASE + 0x40e54, 0x4d4d4d);
+ outpdw(MDP_BASE + 0x40e58, 0x4f4f4f);
+ outpdw(MDP_BASE + 0x40e5c, 0x505050);
+ outpdw(MDP_BASE + 0x40e60, 0x515151);
+ outpdw(MDP_BASE + 0x40e64, 0x525252);
+ outpdw(MDP_BASE + 0x40e68, 0x535353);
+ outpdw(MDP_BASE + 0x40e6c, 0x545454);
+ outpdw(MDP_BASE + 0x40e70, 0x565656);
+ outpdw(MDP_BASE + 0x40e74, 0x575757);
+ outpdw(MDP_BASE + 0x40e78, 0x585858);
+ outpdw(MDP_BASE + 0x40e7c, 0x595959);
+ outpdw(MDP_BASE + 0x40e80, 0x5b5b5b);
+ outpdw(MDP_BASE + 0x40e84, 0x5c5c5c);
+ outpdw(MDP_BASE + 0x40e88, 0x5d5d5d);
+ outpdw(MDP_BASE + 0x40e8c, 0x5e5e5e);
+ outpdw(MDP_BASE + 0x40e90, 0x606060);
+ outpdw(MDP_BASE + 0x40e94, 0x616161);
+ outpdw(MDP_BASE + 0x40e98, 0x626262);
+ outpdw(MDP_BASE + 0x40e9c, 0x646464);
+ outpdw(MDP_BASE + 0x40ea0, 0x656565);
+ outpdw(MDP_BASE + 0x40ea4, 0x666666);
+ outpdw(MDP_BASE + 0x40ea8, 0x686868);
+ outpdw(MDP_BASE + 0x40eac, 0x696969);
+ outpdw(MDP_BASE + 0x40eb0, 0x6a6a6a);
+ outpdw(MDP_BASE + 0x40eb4, 0x6c6c6c);
+ outpdw(MDP_BASE + 0x40eb8, 0x6d6d6d);
+ outpdw(MDP_BASE + 0x40ebc, 0x6f6f6f);
+ outpdw(MDP_BASE + 0x40ec0, 0x707070);
+ outpdw(MDP_BASE + 0x40ec4, 0x717171);
+ outpdw(MDP_BASE + 0x40ec8, 0x737373);
+ outpdw(MDP_BASE + 0x40ecc, 0x747474);
+ outpdw(MDP_BASE + 0x40ed0, 0x767676);
+ outpdw(MDP_BASE + 0x40ed4, 0x777777);
+ outpdw(MDP_BASE + 0x40ed8, 0x797979);
+ outpdw(MDP_BASE + 0x40edc, 0x7a7a7a);
+ outpdw(MDP_BASE + 0x40ee0, 0x7c7c7c);
+ outpdw(MDP_BASE + 0x40ee4, 0x7d7d7d);
+ outpdw(MDP_BASE + 0x40ee8, 0x7f7f7f);
+ outpdw(MDP_BASE + 0x40eec, 0x808080);
+ outpdw(MDP_BASE + 0x40ef0, 0x828282);
+ outpdw(MDP_BASE + 0x40ef4, 0x838383);
+ outpdw(MDP_BASE + 0x40ef8, 0x858585);
+ outpdw(MDP_BASE + 0x40efc, 0x868686);
+ outpdw(MDP_BASE + 0x40f00, 0x888888);
+ outpdw(MDP_BASE + 0x40f04, 0x898989);
+ outpdw(MDP_BASE + 0x40f08, 0x8b8b8b);
+ outpdw(MDP_BASE + 0x40f0c, 0x8d8d8d);
+ outpdw(MDP_BASE + 0x40f10, 0x8e8e8e);
+ outpdw(MDP_BASE + 0x40f14, 0x909090);
+ outpdw(MDP_BASE + 0x40f18, 0x919191);
+ outpdw(MDP_BASE + 0x40f1c, 0x939393);
+ outpdw(MDP_BASE + 0x40f20, 0x959595);
+ outpdw(MDP_BASE + 0x40f24, 0x969696);
+ outpdw(MDP_BASE + 0x40f28, 0x989898);
+ outpdw(MDP_BASE + 0x40f2c, 0x9a9a9a);
+ outpdw(MDP_BASE + 0x40f30, 0x9b9b9b);
+ outpdw(MDP_BASE + 0x40f34, 0x9d9d9d);
+ outpdw(MDP_BASE + 0x40f38, 0x9f9f9f);
+ outpdw(MDP_BASE + 0x40f3c, 0xa1a1a1);
+ outpdw(MDP_BASE + 0x40f40, 0xa2a2a2);
+ outpdw(MDP_BASE + 0x40f44, 0xa4a4a4);
+ outpdw(MDP_BASE + 0x40f48, 0xa6a6a6);
+ outpdw(MDP_BASE + 0x40f4c, 0xa7a7a7);
+ outpdw(MDP_BASE + 0x40f50, 0xa9a9a9);
+ outpdw(MDP_BASE + 0x40f54, 0xababab);
+ outpdw(MDP_BASE + 0x40f58, 0xadadad);
+ outpdw(MDP_BASE + 0x40f5c, 0xafafaf);
+ outpdw(MDP_BASE + 0x40f60, 0xb0b0b0);
+ outpdw(MDP_BASE + 0x40f64, 0xb2b2b2);
+ outpdw(MDP_BASE + 0x40f68, 0xb4b4b4);
+ outpdw(MDP_BASE + 0x40f6c, 0xb6b6b6);
+ outpdw(MDP_BASE + 0x40f70, 0xb8b8b8);
+ outpdw(MDP_BASE + 0x40f74, 0xbababa);
+ outpdw(MDP_BASE + 0x40f78, 0xbbbbbb);
+ outpdw(MDP_BASE + 0x40f7c, 0xbdbdbd);
+ outpdw(MDP_BASE + 0x40f80, 0xbfbfbf);
+ outpdw(MDP_BASE + 0x40f84, 0xc1c1c1);
+ outpdw(MDP_BASE + 0x40f88, 0xc3c3c3);
+ outpdw(MDP_BASE + 0x40f8c, 0xc5c5c5);
+ outpdw(MDP_BASE + 0x40f90, 0xc7c7c7);
+ outpdw(MDP_BASE + 0x40f94, 0xc9c9c9);
+ outpdw(MDP_BASE + 0x40f98, 0xcbcbcb);
+ outpdw(MDP_BASE + 0x40f9c, 0xcdcdcd);
+ outpdw(MDP_BASE + 0x40fa0, 0xcfcfcf);
+ outpdw(MDP_BASE + 0x40fa4, 0xd1d1d1);
+ outpdw(MDP_BASE + 0x40fa8, 0xd3d3d3);
+ outpdw(MDP_BASE + 0x40fac, 0xd5d5d5);
+ outpdw(MDP_BASE + 0x40fb0, 0xd7d7d7);
+ outpdw(MDP_BASE + 0x40fb4, 0xd9d9d9);
+ outpdw(MDP_BASE + 0x40fb8, 0xdbdbdb);
+ outpdw(MDP_BASE + 0x40fbc, 0xdddddd);
+ outpdw(MDP_BASE + 0x40fc0, 0xdfdfdf);
+ outpdw(MDP_BASE + 0x40fc4, 0xe1e1e1);
+ outpdw(MDP_BASE + 0x40fc8, 0xe3e3e3);
+ outpdw(MDP_BASE + 0x40fcc, 0xe5e5e5);
+ outpdw(MDP_BASE + 0x40fd0, 0xe7e7e7);
+ outpdw(MDP_BASE + 0x40fd4, 0xe9e9e9);
+ outpdw(MDP_BASE + 0x40fd8, 0xebebeb);
+ outpdw(MDP_BASE + 0x40fdc, 0xeeeeee);
+ outpdw(MDP_BASE + 0x40fe0, 0xf0f0f0);
+ outpdw(MDP_BASE + 0x40fe4, 0xf2f2f2);
+ outpdw(MDP_BASE + 0x40fe8, 0xf4f4f4);
+ outpdw(MDP_BASE + 0x40fec, 0xf6f6f6);
+ outpdw(MDP_BASE + 0x40ff0, 0xf8f8f8);
+ outpdw(MDP_BASE + 0x40ff4, 0xfbfbfb);
+ outpdw(MDP_BASE + 0x40ff8, 0xfdfdfd);
+ outpdw(MDP_BASE + 0x40ffc, 0xffffff);
+}
+
+#define IRQ_EN_1__MDP_IRQ___M 0x00000800
+
+void mdp_hw_init(void)
+{
+ int i;
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ /* debug interface write access */
+ outpdw(MDP_BASE + 0x60, 1);
+
+ outp32(MDP_INTR_ENABLE, MDP_ANY_INTR_MASK);
+ outp32(MDP_EBI2_PORTMAP_MODE, 0x3);
+ outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8, 0x0);
+ outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc, 0x0);
+ outpdw(MDP_BASE + 0x60, 0x1);
+ mdp_load_lut_param();
+
+ /*
+ * clear up unused fg/main registers
+ */
+ /* comp.plane 2&3 ystride */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0120, 0x0);
+ /* unpacked pattern */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x012c, 0x0);
+ /* unpacked pattern */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0130, 0x0);
+ /* unpacked pattern */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0134, 0x0);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0158, 0x0);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x15c, 0x0);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0160, 0x0);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0170, 0x0);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0174, 0x0);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x017c, 0x0);
+
+ /* comp.plane 2 */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0114, 0x0);
+ /* comp.plane 3 */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0118, 0x0);
+
+ /* clear up unused bg registers */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c8, 0);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d0, 0);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01dc, 0);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0, 0);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4, 0);
+
+#ifndef CONFIG_FB_MSM_MDP22
+ MDP_OUTP(MDP_BASE + 0xE0000, 0);
+ MDP_OUTP(MDP_BASE + 0x100, 0xffffffff);
+ MDP_OUTP(MDP_BASE + 0x90070, 0);
+ MDP_OUTP(MDP_BASE + 0x94010, 1);
+ MDP_OUTP(MDP_BASE + 0x9401c, 2);
+#endif
+
+ /*
+ * limit vector
+ * pre gets applied before color matrix conversion
+ * post is after ccs
+ */
+ writel(mdp_plv[0], MDP_CSC_PRE_LV1n(0));
+ writel(mdp_plv[1], MDP_CSC_PRE_LV1n(1));
+ writel(mdp_plv[2], MDP_CSC_PRE_LV1n(2));
+ writel(mdp_plv[3], MDP_CSC_PRE_LV1n(3));
+
+#ifdef CONFIG_FB_MSM_MDP31
+ writel(mdp_plv[2], MDP_CSC_PRE_LV1n(4));
+ writel(mdp_plv[3], MDP_CSC_PRE_LV1n(5));
+
+ writel(0, MDP_CSC_POST_LV1n(0));
+ writel(0xff, MDP_CSC_POST_LV1n(1));
+ writel(0, MDP_CSC_POST_LV1n(2));
+ writel(0xff, MDP_CSC_POST_LV1n(3));
+ writel(0, MDP_CSC_POST_LV1n(4));
+ writel(0xff, MDP_CSC_POST_LV1n(5));
+
+ writel(0, MDP_CSC_PRE_LV2n(0));
+ writel(0xff, MDP_CSC_PRE_LV2n(1));
+ writel(0, MDP_CSC_PRE_LV2n(2));
+ writel(0xff, MDP_CSC_PRE_LV2n(3));
+ writel(0, MDP_CSC_PRE_LV2n(4));
+ writel(0xff, MDP_CSC_PRE_LV2n(5));
+
+ writel(mdp_plv[0], MDP_CSC_POST_LV2n(0));
+ writel(mdp_plv[1], MDP_CSC_POST_LV2n(1));
+ writel(mdp_plv[2], MDP_CSC_POST_LV2n(2));
+ writel(mdp_plv[3], MDP_CSC_POST_LV2n(3));
+ writel(mdp_plv[2], MDP_CSC_POST_LV2n(4));
+ writel(mdp_plv[3], MDP_CSC_POST_LV2n(5));
+#endif
+
+ /* primary forward matrix */
+ for (i = 0; i < MDP_CCS_SIZE; i++)
+ writel(mdp_ccs_rgb2yuv.ccs[i], MDP_CSC_PFMVn(i));
+
+#ifdef CONFIG_FB_MSM_MDP31
+ for (i = 0; i < MDP_BV_SIZE; i++)
+ writel(mdp_ccs_rgb2yuv.bv[i], MDP_CSC_POST_BV2n(i));
+
+ writel(0, MDP_CSC_PRE_BV2n(0));
+ writel(0, MDP_CSC_PRE_BV2n(1));
+ writel(0, MDP_CSC_PRE_BV2n(2));
+#endif
+ /* primary reverse matrix */
+ for (i = 0; i < MDP_CCS_SIZE; i++)
+ writel(mdp_ccs_yuv2rgb.ccs[i], MDP_CSC_PRMVn(i));
+
+ for (i = 0; i < MDP_BV_SIZE; i++)
+ writel(mdp_ccs_yuv2rgb.bv[i], MDP_CSC_PRE_BV1n(i));
+
+#ifdef CONFIG_FB_MSM_MDP31
+ writel(0, MDP_CSC_POST_BV1n(0));
+ writel(0, MDP_CSC_POST_BV1n(1));
+ writel(0, MDP_CSC_POST_BV1n(2));
+
+ outpdw(MDP_BASE + 0x30010, 0x03e0);
+ outpdw(MDP_BASE + 0x30014, 0x0360);
+ outpdw(MDP_BASE + 0x30018, 0x0120);
+ outpdw(MDP_BASE + 0x3001c, 0x0140);
+#endif
+ mdp_init_scale_table();
+
+#ifndef CONFIG_FB_MSM_MDP31
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0104,
+ ((16 << 6) << 16) | (16) << 6);
+#endif
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
\ No newline at end of file
diff --git a/drivers/staging/msm/mdp_ppp.c b/drivers/staging/msm/mdp_ppp.c
new file mode 100644
index 0000000..c35a6ae
--- /dev/null
+++ b/drivers/staging/msm/mdp_ppp.c
@@ -0,0 +1,1502 @@
+/* drivers/video/msm/src/drv/mdp/mdp_ppp.c
+ *
+ * Copyright (C) 2007 Google Incorporated
+ * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <msm_mdp.h>
+#include <linux/file.h>
+#include <linux/major.h>
+
+#include "linux/proc_fs.h"
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+
+#define MDP_IS_IMGTYPE_BAD(x) (((x) >= MDP_IMGTYPE_LIMIT) && \
+ (((x) < MDP_IMGTYPE2_START) || \
+ ((x) >= MDP_IMGTYPE_LIMIT2)))
+
+static uint32_t bytes_per_pixel[] = {
+ [MDP_RGB_565] = 2,
+ [MDP_RGB_888] = 3,
+ [MDP_XRGB_8888] = 4,
+ [MDP_ARGB_8888] = 4,
+ [MDP_RGBA_8888] = 4,
+ [MDP_BGRA_8888] = 4,
+ [MDP_Y_CBCR_H2V1] = 1,
+ [MDP_Y_CBCR_H2V2] = 1,
+ [MDP_Y_CRCB_H2V1] = 1,
+ [MDP_Y_CRCB_H2V2] = 1,
+ [MDP_YCRYCB_H2V1] = 2,
+ [MDP_BGR_565] = 2
+};
+
+extern uint32 mdp_plv[];
+extern struct semaphore mdp_ppp_mutex;
+
+uint32_t mdp_get_bytes_per_pixel(uint32_t format)
+{
+ uint32_t bpp = 0;
+ if (format < ARRAY_SIZE(bytes_per_pixel))
+ bpp = bytes_per_pixel[format];
+
+ BUG_ON(!bpp);
+ return bpp;
+}
+
+static uint32 mdp_conv_matx_rgb2yuv(uint32 input_pixel,
+ uint16 *matrix_and_bias_vector,
+ uint32 *clamp_vector,
+ uint32 *look_up_table)
+{
+ uint8 input_C2, input_C0, input_C1;
+ uint32 output;
+ int32 comp_C2, comp_C1, comp_C0, temp;
+ int32 temp1, temp2, temp3;
+ int32 matrix[9];
+ int32 bias_vector[3];
+ int32 Y_low_limit, Y_high_limit, C_low_limit, C_high_limit;
+ int32 i;
+ uint32 _is_lookup_table_enabled;
+
+ input_C2 = (input_pixel >> 16) & 0xFF;
+ input_C1 = (input_pixel >> 8) & 0xFF;
+ input_C0 = (input_pixel >> 0) & 0xFF;
+
+ comp_C0 = input_C0;
+ comp_C1 = input_C1;
+ comp_C2 = input_C2;
+
+ for (i = 0; i < 9; i++)
+ matrix[i] =
+ ((int32) (((int32) matrix_and_bias_vector[i]) << 20)) >> 20;
+
+ bias_vector[0] = (int32) (matrix_and_bias_vector[9] & 0xFF);
+ bias_vector[1] = (int32) (matrix_and_bias_vector[10] & 0xFF);
+ bias_vector[2] = (int32) (matrix_and_bias_vector[11] & 0xFF);
+
+ Y_low_limit = (int32) clamp_vector[0];
+ Y_high_limit = (int32) clamp_vector[1];
+ C_low_limit = (int32) clamp_vector[2];
+ C_high_limit = (int32) clamp_vector[3];
+
+ if (look_up_table == 0) /* check for NULL point */
+ _is_lookup_table_enabled = 0;
+ else
+ _is_lookup_table_enabled = 1;
+
+ if (_is_lookup_table_enabled == 1) {
+ comp_C2 = (look_up_table[comp_C2] >> 16) & 0xFF;
+ comp_C1 = (look_up_table[comp_C1] >> 8) & 0xFF;
+ comp_C0 = (look_up_table[comp_C0] >> 0) & 0xFF;
+ }
+ /*
+ * Color Conversion
+ * reorder input colors
+ */
+ temp = comp_C2;
+ comp_C2 = comp_C1;
+ comp_C1 = comp_C0;
+ comp_C0 = temp;
+
+ /* matrix multiplication */
+ temp1 = comp_C0 * matrix[0] + comp_C1 * matrix[1] + comp_C2 * matrix[2];
+ temp2 = comp_C0 * matrix[3] + comp_C1 * matrix[4] + comp_C2 * matrix[5];
+ temp3 = comp_C0 * matrix[6] + comp_C1 * matrix[7] + comp_C2 * matrix[8];
+
+ comp_C0 = temp1 + 0x100;
+ comp_C1 = temp2 + 0x100;
+ comp_C2 = temp3 + 0x100;
+
+ /* take interger part */
+ comp_C0 >>= 9;
+ comp_C1 >>= 9;
+ comp_C2 >>= 9;
+
+ /* post bias (+) */
+ comp_C0 += bias_vector[0];
+ comp_C1 += bias_vector[1];
+ comp_C2 += bias_vector[2];
+
+ /* limit pixel to 8-bit */
+ if (comp_C0 < 0)
+ comp_C0 = 0;
+
+ if (comp_C0 > 255)
+ comp_C0 = 255;
+
+ if (comp_C1 < 0)
+ comp_C1 = 0;
+
+ if (comp_C1 > 255)
+ comp_C1 = 255;
+
+ if (comp_C2 < 0)
+ comp_C2 = 0;
+
+ if (comp_C2 > 255)
+ comp_C2 = 255;
+
+ /* clamp */
+ if (comp_C0 < Y_low_limit)
+ comp_C0 = Y_low_limit;
+
+ if (comp_C0 > Y_high_limit)
+ comp_C0 = Y_high_limit;
+
+ if (comp_C1 < C_low_limit)
+ comp_C1 = C_low_limit;
+
+ if (comp_C1 > C_high_limit)
+ comp_C1 = C_high_limit;
+
+ if (comp_C2 < C_low_limit)
+ comp_C2 = C_low_limit;
+
+ if (comp_C2 > C_high_limit)
+ comp_C2 = C_high_limit;
+
+ output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0;
+ return output;
+}
+
+uint32 mdp_conv_matx_yuv2rgb(uint32 input_pixel,
+ uint16 *matrix_and_bias_vector,
+ uint32 *clamp_vector, uint32 *look_up_table)
+{
+ uint8 input_C2, input_C0, input_C1;
+ uint32 output;
+ int32 comp_C2, comp_C1, comp_C0, temp;
+ int32 temp1, temp2, temp3;
+ int32 matrix[9];
+ int32 bias_vector[3];
+ int32 Y_low_limit, Y_high_limit, C_low_limit, C_high_limit;
+ int32 i;
+ uint32 _is_lookup_table_enabled;
+
+ input_C2 = (input_pixel >> 16) & 0xFF;
+ input_C1 = (input_pixel >> 8) & 0xFF;
+ input_C0 = (input_pixel >> 0) & 0xFF;
+
+ comp_C0 = input_C0;
+ comp_C1 = input_C1;
+ comp_C2 = input_C2;
+
+ for (i = 0; i < 9; i++)
+ matrix[i] =
+ ((int32) (((int32) matrix_and_bias_vector[i]) << 20)) >> 20;
+
+ bias_vector[0] = (int32) (matrix_and_bias_vector[9] & 0xFF);
+ bias_vector[1] = (int32) (matrix_and_bias_vector[10] & 0xFF);
+ bias_vector[2] = (int32) (matrix_and_bias_vector[11] & 0xFF);
+
+ Y_low_limit = (int32) clamp_vector[0];
+ Y_high_limit = (int32) clamp_vector[1];
+ C_low_limit = (int32) clamp_vector[2];
+ C_high_limit = (int32) clamp_vector[3];
+
+ if (look_up_table == 0) /* check for NULL point */
+ _is_lookup_table_enabled = 0;
+ else
+ _is_lookup_table_enabled = 1;
+
+ /* clamp */
+ if (comp_C0 < Y_low_limit)
+ comp_C0 = Y_low_limit;
+
+ if (comp_C0 > Y_high_limit)
+ comp_C0 = Y_high_limit;
+
+ if (comp_C1 < C_low_limit)
+ comp_C1 = C_low_limit;
+
+ if (comp_C1 > C_high_limit)
+ comp_C1 = C_high_limit;
+
+ if (comp_C2 < C_low_limit)
+ comp_C2 = C_low_limit;
+
+ if (comp_C2 > C_high_limit)
+ comp_C2 = C_high_limit;
+
+ /*
+ * Color Conversion
+ * pre bias (-)
+ */
+ comp_C0 -= bias_vector[0];
+ comp_C1 -= bias_vector[1];
+ comp_C2 -= bias_vector[2];
+
+ /* matrix multiplication */
+ temp1 = comp_C0 * matrix[0] + comp_C1 * matrix[1] + comp_C2 * matrix[2];
+ temp2 = comp_C0 * matrix[3] + comp_C1 * matrix[4] + comp_C2 * matrix[5];
+ temp3 = comp_C0 * matrix[6] + comp_C1 * matrix[7] + comp_C2 * matrix[8];
+
+ comp_C0 = temp1 + 0x100;
+ comp_C1 = temp2 + 0x100;
+ comp_C2 = temp3 + 0x100;
+
+ /* take interger part */
+ comp_C0 >>= 9;
+ comp_C1 >>= 9;
+ comp_C2 >>= 9;
+
+ /* reorder output colors */
+ temp = comp_C0;
+ comp_C0 = comp_C1;
+ comp_C1 = comp_C2;
+ comp_C2 = temp;
+
+ /* limit pixel to 8-bit */
+ if (comp_C0 < 0)
+ comp_C0 = 0;
+
+ if (comp_C0 > 255)
+ comp_C0 = 255;
+
+ if (comp_C1 < 0)
+ comp_C1 = 0;
+
+ if (comp_C1 > 255)
+ comp_C1 = 255;
+
+ if (comp_C2 < 0)
+ comp_C2 = 0;
+
+ if (comp_C2 > 255)
+ comp_C2 = 255;
+
+ /* Look-up table */
+ if (_is_lookup_table_enabled == 1) {
+ comp_C2 = (look_up_table[comp_C2] >> 16) & 0xFF;
+ comp_C1 = (look_up_table[comp_C1] >> 8) & 0xFF;
+ comp_C0 = (look_up_table[comp_C0] >> 0) & 0xFF;
+ }
+
+ output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0;
+ return output;
+}
+
+static uint32 mdp_calc_tpval(MDPIMG *mdpImg)
+{
+ uint32 tpVal;
+ uint8 plane_tp;
+
+ tpVal = 0;
+ if ((mdpImg->imgType == MDP_RGB_565)
+ || (mdpImg->imgType == MDP_BGR_565)) {
+ /*
+ * transparent color conversion into 24 bpp
+ *
+ * C2R_8BIT
+ * left shift the entire bit and or it with the upper most bits
+ */
+ plane_tp = (uint8) ((mdpImg->tpVal & 0xF800) >> 11);
+ tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 16;
+
+ /* C1B_8BIT */
+ plane_tp = (uint8) (mdpImg->tpVal & 0x1F);
+ tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 8;
+
+ /* C0G_8BIT */
+ plane_tp = (uint8) ((mdpImg->tpVal & 0x7E0) >> 5);
+ tpVal |= ((plane_tp << 2) | ((plane_tp & 0x30) >> 4));
+ } else {
+ /* 24bit RGB to RBG conversion */
+
+ tpVal = (mdpImg->tpVal & 0xFF00) >> 8;
+ tpVal |= (mdpImg->tpVal & 0xFF) << 8;
+ tpVal |= (mdpImg->tpVal & 0xFF0000);
+ }
+
+ return tpVal;
+}
+
+static uint8 *mdp_get_chroma_addr(MDPIBUF *iBuf)
+{
+ uint8 *dest1;
+
+ dest1 = NULL;
+ switch (iBuf->ibuf_type) {
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CRCB_H2V2:
+ case MDP_Y_CBCR_H2V1:
+ case MDP_Y_CRCB_H2V1:
+ dest1 = (uint8 *) iBuf->buf;
+ dest1 += iBuf->ibuf_width * iBuf->ibuf_height * iBuf->bpp;
+ break;
+
+ default:
+ break;
+ }
+
+ return dest1;
+}
+
+static void mdp_ppp_setbg(MDPIBUF *iBuf)
+{
+ uint8 *bg0_addr;
+ uint8 *bg1_addr;
+ uint32 bg0_ystride, bg1_ystride;
+ uint32 ppp_src_cfg_reg, unpack_pattern;
+ int v_slice, h_slice;
+
+ v_slice = h_slice = 1;
+ bg0_addr = (uint8 *) iBuf->buf;
+ bg1_addr = mdp_get_chroma_addr(iBuf);
+
+ bg0_ystride = iBuf->ibuf_width * iBuf->bpp;
+ bg1_ystride = iBuf->ibuf_width * iBuf->bpp;
+
+ switch (iBuf->ibuf_type) {
+ case MDP_BGR_565:
+ case MDP_RGB_565:
+ /* 888 = 3bytes
+ * RGB = 3Components
+ * RGB interleaved
+ */
+ ppp_src_cfg_reg = PPP_SRC_C2R_5BITS | PPP_SRC_C0G_6BITS |
+ PPP_SRC_C1B_5BITS | PPP_SRC_BPP_INTERLVD_2BYTES |
+ PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
+ PPP_SRC_UNPACK_ALIGN_LSB |
+ PPP_SRC_FETCH_PLANES_INTERLVD;
+
+ if (iBuf->ibuf_type == MDP_RGB_565)
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+ else
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8);
+ break;
+
+ case MDP_RGB_888:
+ /*
+ * 888 = 3bytes
+ * RGB = 3Components
+ * RGB interleaved
+ */
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_3BYTES |
+ PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
+ PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_INTERLVD;
+
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+ break;
+
+ case MDP_BGRA_8888:
+ case MDP_RGBA_8888:
+ case MDP_ARGB_8888:
+ case MDP_XRGB_8888:
+ /*
+ * 8888 = 4bytes
+ * ARGB = 4Components
+ * ARGB interleaved
+ */
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS | PPP_SRC_C3A_8BITS | PPP_SRC_C3_ALPHA_EN |
+ PPP_SRC_BPP_INTERLVD_4BYTES | PPP_SRC_INTERLVD_4COMPONENTS |
+ PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB |
+ PPP_SRC_FETCH_PLANES_INTERLVD;
+
+ if (iBuf->ibuf_type == MDP_BGRA_8888)
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+ 8);
+ else if (iBuf->ibuf_type == MDP_RGBA_8888)
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
+ 8);
+ else
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+ 8);
+ break;
+
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CRCB_H2V2:
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
+ PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS |
+ PPP_SRC_C3A_8BITS |
+ PPP_SRC_BPP_INTERLVD_2BYTES |
+ PPP_SRC_INTERLVD_2COMPONENTS |
+ PPP_SRC_UNPACK_TIGHT |
+ PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
+
+ if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1)
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+ else
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+ v_slice = h_slice = 2;
+ break;
+
+ case MDP_YCRYCB_H2V1:
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
+ PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS |
+ PPP_SRC_C3A_8BITS |
+ PPP_SRC_BPP_INTERLVD_2BYTES |
+ PPP_SRC_INTERLVD_4COMPONENTS |
+ PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB;
+
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8);
+ h_slice = 2;
+ break;
+
+ case MDP_Y_CBCR_H2V1:
+ case MDP_Y_CRCB_H2V1:
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
+ PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS |
+ PPP_SRC_C3A_8BITS |
+ PPP_SRC_BPP_INTERLVD_2BYTES |
+ PPP_SRC_INTERLVD_2COMPONENTS |
+ PPP_SRC_UNPACK_TIGHT |
+ PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
+
+ if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1)
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+ else
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+ h_slice = 2;
+ break;
+
+ default:
+ return;
+ }
+
+ /* starting input address adjustment */
+ mdp_adjust_start_addr(&bg0_addr, &bg1_addr, v_slice, h_slice,
+ iBuf->roi.lcd_x, iBuf->roi.lcd_y,
+ iBuf->ibuf_width, iBuf->ibuf_height, iBuf->bpp,
+ iBuf, 1);
+
+ /*
+ * 0x01c0: background plane 0 addr
+ * 0x01c4: background plane 1 addr
+ * 0x01c8: background plane 2 addr
+ * 0x01cc: bg y stride for plane 0 and 1
+ * 0x01d0: bg y stride for plane 2
+ * 0x01d4: bg src PPP config
+ * 0x01d8: unpack pattern
+ */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c0, bg0_addr);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c4, bg1_addr);
+
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01cc,
+ (bg1_ystride << 16) | bg0_ystride);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d4, ppp_src_cfg_reg);
+
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d8, unpack_pattern);
+}
+
+#define IS_PSEUDOPLNR(img) ((img == MDP_Y_CRCB_H2V2) | \
+ (img == MDP_Y_CBCR_H2V2) | \
+ (img == MDP_Y_CRCB_H2V1) | \
+ (img == MDP_Y_CBCR_H2V1))
+
+#define IMG_LEN(rect_h, w, rect_w, bpp) (((rect_h) * w) * bpp)
+
+#define Y_TO_CRCB_RATIO(format) \
+ ((format == MDP_Y_CBCR_H2V2 || format == MDP_Y_CRCB_H2V2) ? 2 :\
+ (format == MDP_Y_CBCR_H2V1 || format == MDP_Y_CRCB_H2V1) ? 1 : 1)
+
+static void get_len(struct mdp_img *img, struct mdp_rect *rect, uint32_t bpp,
+ uint32_t *len0, uint32_t *len1)
+{
+ *len0 = IMG_LEN(rect->h, img->width, rect->w, bpp);
+ if (IS_PSEUDOPLNR(img->format))
+ *len1 = *len0/Y_TO_CRCB_RATIO(img->format);
+ else
+ *len1 = 0;
+}
+
+static void flush_imgs(struct mdp_blit_req *req, int src_bpp, int dst_bpp,
+ struct file *p_src_file, struct file *p_dst_file)
+{
+#ifdef CONFIG_ANDROID_PMEM
+ uint32_t src0_len, src1_len, dst0_len, dst1_len;
+
+ /* flush src images to memory before dma to mdp */
+ get_len(&req->src, &req->src_rect, src_bpp,
+ &src0_len, &src1_len);
+
+ flush_pmem_file(p_src_file,
+ req->src.offset, src0_len);
+
+ if (IS_PSEUDOPLNR(req->src.format))
+ flush_pmem_file(p_src_file,
+ req->src.offset + src0_len, src1_len);
+
+ get_len(&req->dst, &req->dst_rect, dst_bpp, &dst0_len, &dst1_len);
+ flush_pmem_file(p_dst_file, req->dst.offset, dst0_len);
+
+ if (IS_PSEUDOPLNR(req->dst.format))
+ flush_pmem_file(p_dst_file,
+ req->dst.offset + dst0_len, dst1_len);
+#endif
+}
+
+static void mdp_start_ppp(struct msm_fb_data_type *mfd, MDPIBUF *iBuf,
+struct mdp_blit_req *req, struct file *p_src_file, struct file *p_dst_file)
+{
+ uint8 *src0, *src1;
+ uint8 *dest0, *dest1;
+ uint16 inpBpp;
+ uint32 dest0_ystride;
+ uint32 src_width;
+ uint32 src_height;
+ uint32 src0_ystride;
+ uint32 dst_roi_width;
+ uint32 dst_roi_height;
+ uint32 ppp_src_cfg_reg, ppp_operation_reg, ppp_dst_cfg_reg;
+ uint32 alpha, tpVal;
+ uint32 packPattern;
+ uint32 dst_packPattern;
+ boolean inputRGB, outputRGB, pseudoplanr_output;
+ int sv_slice, sh_slice;
+ int dv_slice, dh_slice;
+ boolean perPixelAlpha = FALSE;
+ boolean ppp_lookUp_enable = FALSE;
+
+ sv_slice = sh_slice = dv_slice = dh_slice = 1;
+ alpha = tpVal = 0;
+ src_width = iBuf->mdpImg.width;
+ src_height = iBuf->roi.y + iBuf->roi.height;
+ src1 = NULL;
+ dest1 = NULL;
+
+ inputRGB = outputRGB = TRUE;
+ pseudoplanr_output = FALSE;
+ ppp_operation_reg = 0;
+ ppp_dst_cfg_reg = 0;
+ ppp_src_cfg_reg = 0;
+
+ /* Wait for the pipe to clear */
+ do { } while (mdp_ppp_pipe_wait() <= 0);
+
+ /*
+ * destination config
+ */
+ switch (iBuf->ibuf_type) {
+ case MDP_RGB_888:
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+ ppp_dst_cfg_reg =
+ PPP_DST_C0G_8BIT | PPP_DST_C1B_8BIT | PPP_DST_C2R_8BIT |
+ PPP_DST_PACKET_CNT_INTERLVD_3ELEM | PPP_DST_PACK_TIGHT |
+ PPP_DST_PACK_ALIGN_LSB | PPP_DST_OUT_SEL_AXI |
+ PPP_DST_BPP_3BYTES | PPP_DST_PLANE_INTERLVD;
+ break;
+
+ case MDP_XRGB_8888:
+ case MDP_ARGB_8888:
+ case MDP_RGBA_8888:
+ if (iBuf->ibuf_type == MDP_BGRA_8888)
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+ 8);
+ else if (iBuf->ibuf_type == MDP_RGBA_8888)
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
+ 8);
+ else
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+ 8);
+
+ ppp_dst_cfg_reg = PPP_DST_C0G_8BIT |
+ PPP_DST_C1B_8BIT |
+ PPP_DST_C2R_8BIT |
+ PPP_DST_C3A_8BIT |
+ PPP_DST_C3ALPHA_EN |
+ PPP_DST_PACKET_CNT_INTERLVD_4ELEM |
+ PPP_DST_PACK_TIGHT |
+ PPP_DST_PACK_ALIGN_LSB |
+ PPP_DST_OUT_SEL_AXI |
+ PPP_DST_BPP_4BYTES | PPP_DST_PLANE_INTERLVD;
+ break;
+
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CRCB_H2V2:
+ if (iBuf->ibuf_type == MDP_Y_CBCR_H2V2)
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+ else
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+
+ ppp_dst_cfg_reg = PPP_DST_C2R_8BIT |
+ PPP_DST_C0G_8BIT |
+ PPP_DST_C1B_8BIT |
+ PPP_DST_C3A_8BIT |
+ PPP_DST_PACKET_CNT_INTERLVD_2ELEM |
+ PPP_DST_PACK_TIGHT |
+ PPP_DST_PACK_ALIGN_LSB |
+ PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES;
+
+ ppp_operation_reg |= PPP_OP_DST_CHROMA_420;
+ outputRGB = FALSE;
+ pseudoplanr_output = TRUE;
+ /*
+ * vertically (y direction) and horizontally (x direction)
+ * sample reduction by 2
+ */
+
+ /*
+ * H2V2(YUV420) Cosite
+ *
+ * Y Y Y Y
+ * CbCr CbCr
+ * Y Y Y Y
+ * Y Y Y Y
+ * CbCr CbCr
+ * Y Y Y Y
+ */
+ dv_slice = dh_slice = 2;
+
+ /* (x,y) and (width,height) must be even numbern */
+ iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
+ iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
+ iBuf->roi.x = (iBuf->roi.x / 2) * 2;
+ iBuf->roi.width = (iBuf->roi.width / 2) * 2;
+
+ iBuf->roi.lcd_y = (iBuf->roi.lcd_y / 2) * 2;
+ iBuf->roi.dst_height = (iBuf->roi.dst_height / 2) * 2;
+ iBuf->roi.y = (iBuf->roi.y / 2) * 2;
+ iBuf->roi.height = (iBuf->roi.height / 2) * 2;
+ break;
+
+ case MDP_YCRYCB_H2V1:
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8);
+ ppp_dst_cfg_reg =
+ PPP_DST_C2R_8BIT | PPP_DST_C0G_8BIT | PPP_DST_C1B_8BIT |
+ PPP_DST_C3A_8BIT | PPP_DST_PACKET_CNT_INTERLVD_4ELEM |
+ PPP_DST_PACK_TIGHT | PPP_DST_PACK_ALIGN_LSB |
+ PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES |
+ PPP_DST_PLANE_INTERLVD;
+
+ ppp_operation_reg |= PPP_OP_DST_CHROMA_H2V1;
+ outputRGB = FALSE;
+ /*
+ * horizontally (x direction) sample reduction by 2
+ *
+ * H2V1(YUV422) Cosite
+ *
+ * YCbCr Y YCbCr Y
+ * YCbCr Y YCbCr Y
+ * YCbCr Y YCbCr Y
+ * YCbCr Y YCbCr Y
+ */
+ dh_slice = 2;
+
+ /*
+ * if it's TV-Out/MDP_YCRYCB_H2V1, let's go through the
+ * preloaded gamma setting of 2.2 when the content is
+ * non-linear ppp_lookUp_enable = TRUE;
+ */
+
+ /* x and width must be even number */
+ iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
+ iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
+ iBuf->roi.x = (iBuf->roi.x / 2) * 2;
+ iBuf->roi.width = (iBuf->roi.width / 2) * 2;
+ break;
+
+ case MDP_Y_CBCR_H2V1:
+ case MDP_Y_CRCB_H2V1:
+ if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1)
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+ else
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+
+ ppp_dst_cfg_reg = PPP_DST_C2R_8BIT |
+ PPP_DST_C0G_8BIT |
+ PPP_DST_C1B_8BIT |
+ PPP_DST_C3A_8BIT |
+ PPP_DST_PACKET_CNT_INTERLVD_2ELEM |
+ PPP_DST_PACK_TIGHT |
+ PPP_DST_PACK_ALIGN_LSB |
+ PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES;
+
+ ppp_operation_reg |= PPP_OP_DST_CHROMA_H2V1;
+ outputRGB = FALSE;
+ pseudoplanr_output = TRUE;
+ /* horizontally (x direction) sample reduction by 2 */
+ dh_slice = 2;
+
+ /* x and width must be even number */
+ iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
+ iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
+ iBuf->roi.x = (iBuf->roi.x / 2) * 2;
+ iBuf->roi.width = (iBuf->roi.width / 2) * 2;
+ break;
+
+ case MDP_BGR_565:
+ case MDP_RGB_565:
+ default:
+ if (iBuf->ibuf_type == MDP_RGB_565)
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+ else
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8);
+
+ ppp_dst_cfg_reg = PPP_DST_C0G_6BIT |
+ PPP_DST_C1B_5BIT |
+ PPP_DST_C2R_5BIT |
+ PPP_DST_PACKET_CNT_INTERLVD_3ELEM |
+ PPP_DST_PACK_TIGHT |
+ PPP_DST_PACK_ALIGN_LSB |
+ PPP_DST_OUT_SEL_AXI |
+ PPP_DST_BPP_2BYTES | PPP_DST_PLANE_INTERLVD;
+ break;
+ }
+
+ /* source config */
+ switch (iBuf->mdpImg.imgType) {
+ case MDP_RGB_888:
+ inpBpp = 3;
+ /*
+ * 565 = 2bytes
+ * RGB = 3Components
+ * RGB interleaved
+ */
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_3BYTES |
+ PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
+ PPP_SRC_UNPACK_ALIGN_LSB |
+ PPP_SRC_FETCH_PLANES_INTERLVD;
+
+ packPattern = MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+
+ ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB |
+ PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB;
+ break;
+
+ case MDP_BGRA_8888:
+ case MDP_RGBA_8888:
+ case MDP_ARGB_8888:
+ perPixelAlpha = TRUE;
+ case MDP_XRGB_8888:
+ inpBpp = 4;
+ /*
+ * 8888 = 4bytes
+ * ARGB = 4Components
+ * ARGB interleaved
+ */
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS | PPP_SRC_C3A_8BITS |
+ PPP_SRC_C3_ALPHA_EN | PPP_SRC_BPP_INTERLVD_4BYTES |
+ PPP_SRC_INTERLVD_4COMPONENTS | PPP_SRC_UNPACK_TIGHT |
+ PPP_SRC_UNPACK_ALIGN_LSB |
+ PPP_SRC_FETCH_PLANES_INTERLVD;
+
+ if (iBuf->mdpImg.imgType == MDP_BGRA_8888)
+ packPattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+ 8);
+ else if (iBuf->mdpImg.imgType == MDP_RGBA_8888)
+ packPattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
+ 8);
+ else
+ packPattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+ 8);
+
+ ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB |
+ PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB;
+ break;
+
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CRCB_H2V2:
+ inpBpp = 1;
+ src1 = (uint8 *) iBuf->mdpImg.cbcr_addr;
+
+ /*
+ * CbCr = 2bytes
+ * CbCr = 2Components
+ * Y+CbCr
+ */
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_2BYTES |
+ PPP_SRC_INTERLVD_2COMPONENTS | PPP_SRC_UNPACK_TIGHT |
+ PPP_SRC_UNPACK_ALIGN_LSB |
+ PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
+
+ if (iBuf->mdpImg.imgType == MDP_Y_CRCB_H2V2)
+ packPattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+ else
+ packPattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+
+ ppp_operation_reg |= PPP_OP_COLOR_SPACE_YCBCR |
+ PPP_OP_SRC_CHROMA_420 |
+ PPP_OP_SRC_CHROMA_COSITE |
+ PPP_OP_DST_CHROMA_RGB | PPP_OP_DST_CHROMA_COSITE;
+
+ inputRGB = FALSE;
+ sh_slice = sv_slice = 2;
+ break;
+
+ case MDP_YCRYCB_H2V1:
+ inpBpp = 2;
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
+ PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS |
+ PPP_SRC_C3A_8BITS |
+ PPP_SRC_BPP_INTERLVD_2BYTES |
+ PPP_SRC_INTERLVD_4COMPONENTS |
+ PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB;
+
+ packPattern =
+ MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8);
+
+ ppp_operation_reg |= PPP_OP_SRC_CHROMA_H2V1 |
+ PPP_OP_SRC_CHROMA_COSITE | PPP_OP_DST_CHROMA_COSITE;
+
+ /*
+ * if it's TV-Out/MDP_YCRYCB_H2V1, let's go through the
+ * preloaded inverse gamma setting of 2.2 since they're
+ * symetric when the content is non-linear
+ * ppp_lookUp_enable = TRUE;
+ */
+
+ /* x and width must be even number */
+ iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
+ iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
+ iBuf->roi.x = (iBuf->roi.x / 2) * 2;
+ iBuf->roi.width = (iBuf->roi.width / 2) * 2;
+
+ inputRGB = FALSE;
+ sh_slice = 2;
+ break;
+
+ case MDP_Y_CBCR_H2V1:
+ case MDP_Y_CRCB_H2V1:
+ inpBpp = 1;
+ src1 = (uint8 *) iBuf->mdpImg.cbcr_addr;
+
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
+ PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS |
+ PPP_SRC_C3A_8BITS |
+ PPP_SRC_BPP_INTERLVD_2BYTES |
+ PPP_SRC_INTERLVD_2COMPONENTS |
+ PPP_SRC_UNPACK_TIGHT |
+ PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
+
+ if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V1)
+ packPattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+ else
+ packPattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+
+ ppp_operation_reg |= PPP_OP_SRC_CHROMA_H2V1 |
+ PPP_OP_SRC_CHROMA_COSITE | PPP_OP_DST_CHROMA_COSITE;
+ inputRGB = FALSE;
+ sh_slice = 2;
+ break;
+
+ case MDP_BGR_565:
+ case MDP_RGB_565:
+ default:
+ inpBpp = 2;
+ /*
+ * 565 = 2bytes
+ * RGB = 3Components
+ * RGB interleaved
+ */
+ ppp_src_cfg_reg = PPP_SRC_C2R_5BITS | PPP_SRC_C0G_6BITS |
+ PPP_SRC_C1B_5BITS | PPP_SRC_BPP_INTERLVD_2BYTES |
+ PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
+ PPP_SRC_UNPACK_ALIGN_LSB |
+ PPP_SRC_FETCH_PLANES_INTERLVD;
+
+ if (iBuf->mdpImg.imgType == MDP_RGB_565)
+ packPattern =
+ MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+ else
+ packPattern =
+ MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8);
+
+ ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB |
+ PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB;
+ break;
+
+ }
+
+ if (pseudoplanr_output)
+ ppp_dst_cfg_reg |= PPP_DST_PLANE_PSEUDOPLN;
+
+ /* YCbCr to RGB color conversion flag */
+ if ((!inputRGB) && (outputRGB)) {
+ ppp_operation_reg |= PPP_OP_CONVERT_YCBCR2RGB |
+ PPP_OP_CONVERT_ON;
+
+ /*
+ * primary/secondary is sort of misleading term...but
+ * in mdp2.2/3.0 we only use primary matrix (forward/rev)
+ * in mdp3.1 we use set1(prim) and set2(secd)
+ */
+#ifdef CONFIG_FB_MSM_MDP31
+ ppp_operation_reg |= PPP_OP_CONVERT_MATRIX_SECONDARY |
+ PPP_OP_DST_RGB;
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0240, 0);
+#endif
+
+ if (ppp_lookUp_enable) {
+ ppp_operation_reg |= PPP_OP_LUT_C0_ON |
+ PPP_OP_LUT_C1_ON | PPP_OP_LUT_C2_ON;
+ }
+ }
+ /* RGB to YCbCr color conversion flag */
+ if ((inputRGB) && (!outputRGB)) {
+ ppp_operation_reg |= PPP_OP_CONVERT_RGB2YCBCR |
+ PPP_OP_CONVERT_ON;
+
+#ifdef CONFIG_FB_MSM_MDP31
+ ppp_operation_reg |= PPP_OP_CONVERT_MATRIX_PRIMARY |
+ PPP_OP_DST_YCBCR;
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0240, 0x1e);
+#endif
+
+ if (ppp_lookUp_enable) {
+ ppp_operation_reg |= PPP_OP_LUT_C0_ON |
+ PPP_OP_LUT_C1_ON | PPP_OP_LUT_C2_ON;
+ }
+ }
+ /* YCbCr to YCbCr color conversion flag */
+ if ((!inputRGB) && (!outputRGB)) {
+ if ((ppp_lookUp_enable) &&
+ (iBuf->mdpImg.imgType != iBuf->ibuf_type)) {
+ ppp_operation_reg |= PPP_OP_LUT_C0_ON;
+ }
+ }
+
+ ppp_src_cfg_reg |= (iBuf->roi.x % 2) ? PPP_SRC_BPP_ROI_ODD_X : 0;
+ ppp_src_cfg_reg |= (iBuf->roi.y % 2) ? PPP_SRC_BPP_ROI_ODD_Y : 0;
+
+ if (req->flags & MDP_DEINTERLACE)
+ ppp_operation_reg |= PPP_OP_DEINT_EN;
+
+ /* Dither at DMA side only since iBuf format is RGB888 */
+ if (iBuf->mdpImg.mdpOp & MDPOP_DITHER)
+ ppp_operation_reg |= PPP_OP_DITHER_EN;
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_ROTATION) {
+ ppp_operation_reg |= PPP_OP_ROT_ON;
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
+ ppp_operation_reg |= PPP_OP_ROT_90;
+ }
+ if (iBuf->mdpImg.mdpOp & MDPOP_LR) {
+ ppp_operation_reg |= PPP_OP_FLIP_LR;
+ }
+ if (iBuf->mdpImg.mdpOp & MDPOP_UD) {
+ ppp_operation_reg |= PPP_OP_FLIP_UD;
+ }
+ }
+
+ src0_ystride = src_width * inpBpp;
+ dest0_ystride = iBuf->ibuf_width * iBuf->bpp;
+
+ /* no need to care about rotation since it's the real-XY. */
+ dst_roi_width = iBuf->roi.dst_width;
+ dst_roi_height = iBuf->roi.dst_height;
+
+ src0 = (uint8 *) iBuf->mdpImg.bmy_addr;
+ dest0 = (uint8 *) iBuf->buf;
+
+ /* Jumping from Y-Plane to Chroma Plane */
+ dest1 = mdp_get_chroma_addr(iBuf);
+
+ /* first pixel addr calculation */
+ mdp_adjust_start_addr(&src0, &src1, sv_slice, sh_slice, iBuf->roi.x,
+ iBuf->roi.y, src_width, src_height, inpBpp, iBuf,
+ 0);
+ mdp_adjust_start_addr(&dest0, &dest1, dv_slice, dh_slice,
+ iBuf->roi.lcd_x, iBuf->roi.lcd_y,
+ iBuf->ibuf_width, iBuf->ibuf_height, iBuf->bpp,
+ iBuf, 2);
+
+ /* set scale operation */
+ mdp_set_scale(iBuf, dst_roi_width, dst_roi_height,
+ inputRGB, outputRGB, &ppp_operation_reg);
+
+ /*
+ * setting background source for blending
+ */
+ mdp_set_blend_attr(iBuf, &alpha, &tpVal, perPixelAlpha,
+ &ppp_operation_reg);
+
+ if (ppp_operation_reg & PPP_OP_BLEND_ON) {
+ mdp_ppp_setbg(iBuf);
+
+ if (iBuf->ibuf_type == MDP_YCRYCB_H2V1) {
+ ppp_operation_reg |= PPP_OP_BG_CHROMA_H2V1;
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) {
+ tpVal = mdp_conv_matx_rgb2yuv(tpVal,
+ (uint16 *) &
+ mdp_ccs_rgb2yuv,
+ &mdp_plv[0], NULL);
+ }
+ }
+ }
+
+ /*
+ * 0x0004: enable dbg bus
+ * 0x0100: "don't care" Edge Condit until scaling is on
+ * 0x0104: xrc tile x&y size u7.6 format = 7bit.6bit
+ * 0x0108: src pixel size
+ * 0x010c: component plane 0 starting address
+ * 0x011c: component plane 0 ystride
+ * 0x0124: PPP source config register
+ * 0x0128: unpacked pattern from lsb to msb (eg. RGB->BGR)
+ */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0108, (iBuf->roi.height << 16 |
+ iBuf->roi.width));
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x010c, src0); /* comp.plane 0 */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0110, src1); /* comp.plane 1 */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x011c,
+ (src0_ystride << 16 | src0_ystride));
+
+ /* setup for rgb 565 */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0124, ppp_src_cfg_reg);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0128, packPattern);
+ /*
+ * 0x0138: PPP destination operation register
+ * 0x014c: constant_alpha|transparent_color
+ * 0x0150: PPP destination config register
+ * 0x0154: PPP packing pattern
+ */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0138, ppp_operation_reg);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x014c, alpha << 24 | tpVal);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0150, ppp_dst_cfg_reg);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0154, dst_packPattern);
+
+ /*
+ * 0x0164: ROI height and width
+ * 0x0168: Component Plane 0 starting addr
+ * 0x016c: Component Plane 1 starting addr
+ * 0x0178: Component Plane 1/0 y stride
+ */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0164,
+ (dst_roi_height << 16 | dst_roi_width));
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0168, dest0);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x016c, dest1);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0178,
+ (dest0_ystride << 16 | dest0_ystride));
+
+ flush_imgs(req, inpBpp, iBuf->bpp, p_src_file, p_dst_file);
+#ifdef CONFIG_MDP_PPP_ASYNC_OP
+ mdp_ppp_process_curr_djob();
+#else
+ mdp_pipe_kickoff(MDP_PPP_TERM, mfd);
+#endif
+}
+
+static int mdp_ppp_verify_req(struct mdp_blit_req *req)
+{
+ u32 src_width, src_height, dst_width, dst_height;
+
+ if (req == NULL)
+ return -1;
+
+ if (MDP_IS_IMGTYPE_BAD(req->src.format) ||
+ MDP_IS_IMGTYPE_BAD(req->dst.format))
+ return -1;
+
+ if ((req->src.width == 0) || (req->src.height == 0) ||
+ (req->src_rect.w == 0) || (req->src_rect.h == 0) ||
+ (req->dst.width == 0) || (req->dst.height == 0) ||
+ (req->dst_rect.w == 0) || (req->dst_rect.h == 0))
+
+ return -1;
+
+ if (((req->src_rect.x + req->src_rect.w) > req->src.width) ||
+ ((req->src_rect.y + req->src_rect.h) > req->src.height))
+ return -1;
+
+ if (((req->dst_rect.x + req->dst_rect.w) > req->dst.width) ||
+ ((req->dst_rect.y + req->dst_rect.h) > req->dst.height))
+ return -1;
+
+ /*
+ * scaling range check
+ */
+ src_width = req->src_rect.w;
+ src_height = req->src_rect.h;
+
+ if (req->flags & MDP_ROT_90) {
+ dst_width = req->dst_rect.h;
+ dst_height = req->dst_rect.w;
+ } else {
+ dst_width = req->dst_rect.w;
+ dst_height = req->dst_rect.h;
+ }
+
+ switch (req->dst.format) {
+ case MDP_Y_CRCB_H2V2:
+ case MDP_Y_CBCR_H2V2:
+ src_width = (src_width / 2) * 2;
+ src_height = (src_height / 2) * 2;
+ dst_width = (src_width / 2) * 2;
+ dst_height = (src_height / 2) * 2;
+ break;
+
+ case MDP_Y_CRCB_H2V1:
+ case MDP_Y_CBCR_H2V1:
+ case MDP_YCRYCB_H2V1:
+ src_width = (src_width / 2) * 2;
+ dst_width = (src_width / 2) * 2;
+ break;
+
+ default:
+ break;
+ }
+
+ if (((MDP_SCALE_Q_FACTOR * dst_width) / src_width >
+ MDP_MAX_X_SCALE_FACTOR)
+ || ((MDP_SCALE_Q_FACTOR * dst_width) / src_width <
+ MDP_MIN_X_SCALE_FACTOR))
+ return -1;
+
+ if (((MDP_SCALE_Q_FACTOR * dst_height) / src_height >
+ MDP_MAX_Y_SCALE_FACTOR)
+ || ((MDP_SCALE_Q_FACTOR * dst_height) / src_height <
+ MDP_MIN_Y_SCALE_FACTOR))
+ return -1;
+
+ return 0;
+}
+
+/**
+ * get_gem_img() - retrieve drm obj's start address and size
+ * @img: contains drm file descriptor and gem handle
+ * @start: repository of starting address of drm obj allocated memory
+ * @len: repository of size of drm obj alloacted memory
+ *
+ **/
+int get_gem_img(struct mdp_img *img, unsigned long *start, unsigned long *len)
+{
+ panic("waaaaaaaah");
+ //return kgsl_gem_obj_addr(img->memory_id, (int)img->priv, start, len);
+}
+
+int get_img(struct mdp_img *img, struct fb_info *info, unsigned long *start,
+ unsigned long *len, struct file **pp_file)
+{
+ int put_needed, ret = 0;
+ struct file *file;
+ unsigned long vstart;
+#ifdef CONFIG_ANDROID_PMEM
+ if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file))
+ return 0;
+#endif
+ file = fget_light(img->memory_id, &put_needed);
+ if (file == NULL)
+ return -1;
+
+ if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
+ *start = info->fix.smem_start;
+ *len = info->fix.smem_len;
+ *pp_file = file;
+ } else {
+ ret = -1;
+ fput_light(file, put_needed);
+ }
+ return ret;
+}
+
+int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req,
+ struct file **pp_src_file, struct file **pp_dst_file)
+{
+ unsigned long src_start, dst_start;
+ unsigned long src_len = 0;
+ unsigned long dst_len = 0;
+ MDPIBUF iBuf;
+ u32 dst_width, dst_height;
+ struct file *p_src_file = 0 , *p_dst_file = 0;
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ if (req->dst.format == MDP_FB_FORMAT)
+ req->dst.format = mfd->fb_imgType;
+ if (req->src.format == MDP_FB_FORMAT)
+ req->src.format = mfd->fb_imgType;
+
+ if (req->flags & MDP_BLIT_SRC_GEM) {
+ if (get_gem_img(&req->src, &src_start, &src_len) < 0)
+ return -1;
+ } else {
+ get_img(&req->src, info, &src_start, &src_len, &p_src_file);
+ }
+ if (src_len == 0) {
+ printk(KERN_ERR "mdp_ppp: could not retrieve image from "
+ "memory\n");
+ return -1;
+ }
+
+ if (req->flags & MDP_BLIT_DST_GEM) {
+ if (get_gem_img(&req->dst, &dst_start, &dst_len) < 0)
+ return -1;
+ } else {
+ get_img(&req->dst, info, &dst_start, &dst_len, &p_dst_file);
+ }
+ if (dst_len == 0) {
+ printk(KERN_ERR "mdp_ppp: could not retrieve image from "
+ "memory\n");
+ return -1;
+ }
+ *pp_src_file = p_src_file;
+ *pp_dst_file = p_dst_file;
+ if (mdp_ppp_verify_req(req)) {
+ printk(KERN_ERR "mdp_ppp: invalid image!\n");
+ return -1;
+ }
+
+ iBuf.ibuf_width = req->dst.width;
+ iBuf.ibuf_height = req->dst.height;
+ iBuf.bpp = bytes_per_pixel[req->dst.format];
+
+ iBuf.ibuf_type = req->dst.format;
+ iBuf.buf = (uint8 *) dst_start;
+ iBuf.buf += req->dst.offset;
+
+ iBuf.roi.lcd_x = req->dst_rect.x;
+ iBuf.roi.lcd_y = req->dst_rect.y;
+ iBuf.roi.dst_width = req->dst_rect.w;
+ iBuf.roi.dst_height = req->dst_rect.h;
+
+ iBuf.roi.x = req->src_rect.x;
+ iBuf.roi.width = req->src_rect.w;
+ iBuf.roi.y = req->src_rect.y;
+ iBuf.roi.height = req->src_rect.h;
+
+ iBuf.mdpImg.width = req->src.width;
+ iBuf.mdpImg.imgType = req->src.format;
+
+ iBuf.mdpImg.bmy_addr = (uint32 *) (src_start + req->src.offset);
+ iBuf.mdpImg.cbcr_addr =
+ (uint32 *) ((uint32) iBuf.mdpImg.bmy_addr +
+ req->src.width * req->src.height);
+
+ iBuf.mdpImg.mdpOp = MDPOP_NOP;
+
+ /* blending check */
+ if (req->transp_mask != MDP_TRANSP_NOP) {
+ iBuf.mdpImg.mdpOp |= MDPOP_TRANSP;
+ iBuf.mdpImg.tpVal = req->transp_mask;
+ iBuf.mdpImg.tpVal = mdp_calc_tpval(&iBuf.mdpImg);
+ }
+
+ req->alpha &= 0xff;
+ if (req->alpha < MDP_ALPHA_NOP) {
+ iBuf.mdpImg.mdpOp |= MDPOP_ALPHAB;
+ iBuf.mdpImg.alpha = req->alpha;
+ }
+
+ /* rotation check */
+ if (req->flags & MDP_FLIP_LR)
+ iBuf.mdpImg.mdpOp |= MDPOP_LR;
+ if (req->flags & MDP_FLIP_UD)
+ iBuf.mdpImg.mdpOp |= MDPOP_UD;
+ if (req->flags & MDP_ROT_90)
+ iBuf.mdpImg.mdpOp |= MDPOP_ROT90;
+ if (req->flags & MDP_DITHER)
+ iBuf.mdpImg.mdpOp |= MDPOP_DITHER;
+
+ if (req->flags & MDP_BLEND_FG_PREMULT) {
+#ifdef CONFIG_FB_MSM_MDP31
+ iBuf.mdpImg.mdpOp |= MDPOP_FG_PM_ALPHA;
+#else
+ return -EINVAL;
+#endif
+ }
+
+ if (req->flags & MDP_DEINTERLACE) {
+#ifdef CONFIG_FB_MSM_MDP31
+ if ((req->src.format != MDP_Y_CBCR_H2V2) &&
+ (req->src.format != MDP_Y_CRCB_H2V2))
+#endif
+ return -EINVAL;
+ }
+
+ /* scale check */
+ if (req->flags & MDP_ROT_90) {
+ dst_width = req->dst_rect.h;
+ dst_height = req->dst_rect.w;
+ } else {
+ dst_width = req->dst_rect.w;
+ dst_height = req->dst_rect.h;
+ }
+
+ if ((iBuf.roi.width != dst_width) || (iBuf.roi.height != dst_height))
+ iBuf.mdpImg.mdpOp |= MDPOP_ASCALE;
+
+ if (req->flags & MDP_BLUR) {
+#ifdef CONFIG_FB_MSM_MDP31
+ if (req->flags & MDP_SHARPENING)
+ printk(KERN_WARNING
+ "mdp: MDP_SHARPENING is set with MDP_BLUR!\n");
+ req->flags |= MDP_SHARPENING;
+ req->sharpening_strength = -127;
+#else
+ iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_BLUR;
+
+#endif
+ }
+
+ if (req->flags & MDP_SHARPENING) {
+#ifdef CONFIG_FB_MSM_MDP31
+ if ((req->sharpening_strength > 127) ||
+ (req->sharpening_strength < -127)) {
+ printk(KERN_ERR
+ "%s: sharpening strength out of range\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_SHARPENING;
+ iBuf.mdpImg.sp_value = req->sharpening_strength & 0xff;
+#else
+ return -EINVAL;
+#endif
+ }
+
+ down(&mdp_ppp_mutex);
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+#ifdef CONFIG_FB_MSM_MDP31
+ mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
+#else
+ /* bg tile fetching HW workaround */
+ if (((iBuf.mdpImg.mdpOp & (MDPOP_TRANSP | MDPOP_ALPHAB)) ||
+ (req->src.format == MDP_ARGB_8888) ||
+ (req->src.format == MDP_BGRA_8888) ||
+ (req->src.format == MDP_RGBA_8888)) &&
+ (iBuf.mdpImg.mdpOp & MDPOP_ROT90) && (req->dst_rect.w <= 16)) {
+ int dst_h, src_w, i;
+
+ src_w = req->src_rect.w;
+ dst_h = iBuf.roi.dst_height;
+
+ for (i = 0; i < (req->dst_rect.h / 16); i++) {
+ /* this tile size */
+ iBuf.roi.dst_height = 16;
+ iBuf.roi.width =
+ (16 * req->src_rect.w) / req->dst_rect.h;
+
+ /* if it's out of scale range... */
+ if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+ iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR)
+ iBuf.roi.width =
+ (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+ MDP_MAX_X_SCALE_FACTOR;
+ else if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+ iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR)
+ iBuf.roi.width =
+ (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+ MDP_MIN_X_SCALE_FACTOR;
+
+ mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
+
+ /* next tile location */
+ iBuf.roi.lcd_y += 16;
+ iBuf.roi.x += iBuf.roi.width;
+
+ /* this is for a remainder update */
+ dst_h -= 16;
+ src_w -= iBuf.roi.width;
+ }
+
+ if ((dst_h < 0) || (src_w < 0))
+ printk
+ ("msm_fb: mdp_blt_ex() unexpected result! line:%d\n",
+ __LINE__);
+
+ /* remainder update */
+ if ((dst_h > 0) && (src_w > 0)) {
+ u32 tmp_v;
+
+ iBuf.roi.dst_height = dst_h;
+ iBuf.roi.width = src_w;
+
+ if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+ iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR) {
+ tmp_v =
+ (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+ MDP_MAX_X_SCALE_FACTOR +
+ (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) %
+ MDP_MAX_X_SCALE_FACTOR ? 1 : 0;
+
+ /* move x location as roi width gets bigger */
+ iBuf.roi.x -= tmp_v - iBuf.roi.width;
+ iBuf.roi.width = tmp_v;
+ } else
+ if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+ iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR) {
+ tmp_v =
+ (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+ MDP_MIN_X_SCALE_FACTOR +
+ (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) %
+ MDP_MIN_X_SCALE_FACTOR ? 1 : 0;
+
+ /*
+ * we don't move x location for continuity of
+ * source image
+ */
+ iBuf.roi.width = tmp_v;
+ }
+
+ mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
+ }
+ } else {
+ mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
+ }
+#endif
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ up(&mdp_ppp_mutex);
+
+ return 0;
+}
diff --git a/drivers/staging/msm/mdp_ppp_dq.c b/drivers/staging/msm/mdp_ppp_dq.c
new file mode 100644
index 0000000..3dc1c0c
--- /dev/null
+++ b/drivers/staging/msm/mdp_ppp_dq.c
@@ -0,0 +1,347 @@
+/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "mdp.h"
+
+static boolean mdp_ppp_intr_flag = FALSE;
+static boolean mdp_ppp_busy_flag = FALSE;
+
+/* Queue to keep track of the completed jobs for cleaning */
+static LIST_HEAD(mdp_ppp_djob_clnrq);
+static DEFINE_SPINLOCK(mdp_ppp_djob_clnrq_lock);
+
+/* Worker to cleanup Display Jobs */
+static struct workqueue_struct *mdp_ppp_djob_clnr;
+
+/* Display Queue (DQ) for MDP PPP Block */
+static LIST_HEAD(mdp_ppp_dq);
+static DEFINE_SPINLOCK(mdp_ppp_dq_lock);
+
+/* Current Display Job for MDP PPP */
+static struct mdp_ppp_djob *curr_djob;
+
+/* Track ret code for the last opeartion */
+static int mdp_ppp_ret_code;
+
+inline int mdp_ppp_get_ret_code(void)
+{
+ return mdp_ppp_ret_code;
+}
+
+/* Push <Reg, Val> pair into DQ (if available) to later
+ * program the MDP PPP Block */
+inline void mdp_ppp_outdw(uint32_t addr, uint32_t data)
+{
+ if (curr_djob) {
+
+ /* get the last node of the list. */
+ struct mdp_ppp_roi_cmd_set *node =
+ list_entry(curr_djob->roi_cmd_list.prev,
+ struct mdp_ppp_roi_cmd_set, node);
+
+ /* If a node is already full, create a new one and add it to
+ * the list (roi_cmd_list).
+ */
+ if (node->ncmds == MDP_PPP_ROI_NODE_SIZE) {
+ node = kmalloc(sizeof(struct mdp_ppp_roi_cmd_set),
+ GFP_KERNEL);
+ if (!node) {
+ printk(KERN_ERR
+ "MDP_PPP: not enough memory.\n");
+ mdp_ppp_ret_code = -EINVAL;
+ return;
+ }
+
+ /* no ROI commands initially */
+ node->ncmds = 0;
+
+ /* add one node to roi_cmd_list. */
+ list_add_tail(&node->node, &curr_djob->roi_cmd_list);
+ }
+
+ /* register ROI commands */
+ node->cmd[node->ncmds].reg = addr;
+ node->cmd[node->ncmds].val = data;
+ node->ncmds++;
+ } else
+ /* program MDP PPP block now */
+ outpdw((addr), (data));
+}
+
+/* Initialize DQ */
+inline void mdp_ppp_dq_init(void)
+{
+ mdp_ppp_djob_clnr = create_singlethread_workqueue("MDPDJobClnrThrd");
+}
+
+/* Release resources of a job (DJob). */
+static void mdp_ppp_del_djob(struct mdp_ppp_djob *job)
+{
+ struct mdp_ppp_roi_cmd_set *node, *tmp;
+
+ /* release mem */
+ mdp_ppp_put_img(job->p_src_file, job->p_dst_file);
+
+ /* release roi_cmd_list */
+ list_for_each_entry_safe(node, tmp, &job->roi_cmd_list, node) {
+ list_del(&node->node);
+ kfree(node);
+ }
+
+ /* release job struct */
+ kfree(job);
+}
+
+/* Worker thread to reclaim resources once a display job is done */
+static void mdp_ppp_djob_cleaner(struct work_struct *work)
+{
+ struct mdp_ppp_djob *job;
+
+ MDP_PPP_DEBUG_MSG("mdp ppp display job cleaner started \n");
+
+ /* cleanup display job */
+ job = container_of(work, struct mdp_ppp_djob, cleaner.work);
+ if (likely(work && job))
+ mdp_ppp_del_djob(job);
+}
+
+/* Create a new Display Job (DJob) */
+inline struct mdp_ppp_djob *mdp_ppp_new_djob(void)
+{
+ struct mdp_ppp_djob *job;
+ struct mdp_ppp_roi_cmd_set *node;
+
+ /* create a new djob */
+ job = kmalloc(sizeof(struct mdp_ppp_djob), GFP_KERNEL);
+ if (!job)
+ return NULL;
+
+ /* add the first node to curr_djob->roi_cmd_list */
+ node = kmalloc(sizeof(struct mdp_ppp_roi_cmd_set), GFP_KERNEL);
+ if (!node) {
+ kfree(job);
+ return NULL;
+ }
+
+ /* make this current djob container to keep track of the curr djob not
+ * used in the async path i.e. no sync needed
+ *
+ * Should not contain any references from the past djob
+ */
+ BUG_ON(curr_djob);
+ curr_djob = job;
+ INIT_LIST_HEAD(&curr_djob->roi_cmd_list);
+
+ /* no ROI commands initially */
+ node->ncmds = 0;
+ INIT_LIST_HEAD(&node->node);
+ list_add_tail(&node->node, &curr_djob->roi_cmd_list);
+
+ /* register this djob with the djob cleaner
+ * initializes 'work' data struct
+ */
+ INIT_DELAYED_WORK(&curr_djob->cleaner, mdp_ppp_djob_cleaner);
+ INIT_LIST_HEAD(&curr_djob->entry);
+
+ curr_djob->p_src_file = 0;
+ curr_djob->p_dst_file = 0;
+
+ return job;
+}
+
+/* Undo the effect of mdp_ppp_new_djob() */
+inline void mdp_ppp_clear_curr_djob(void)
+{
+ if (likely(curr_djob)) {
+ mdp_ppp_del_djob(curr_djob);
+ curr_djob = NULL;
+ }
+}
+
+/* Cleanup dirty djobs */
+static void mdp_ppp_flush_dirty_djobs(void *cond)
+{
+ unsigned long flags;
+ struct mdp_ppp_djob *job;
+
+ /* Flush the jobs from the djob clnr queue */
+ while (cond && test_bit(0, (unsigned long *)cond)) {
+
+ /* Until we are done with the cleanup queue */
+ spin_lock_irqsave(&mdp_ppp_djob_clnrq_lock, flags);
+ if (list_empty(&mdp_ppp_djob_clnrq)) {
+ spin_unlock_irqrestore(&mdp_ppp_djob_clnrq_lock, flags);
+ break;
+ }
+
+ MDP_PPP_DEBUG_MSG("flushing djobs ... loop \n");
+
+ /* Retrieve the job that needs to be cleaned */
+ job = list_entry(mdp_ppp_djob_clnrq.next,
+ struct mdp_ppp_djob, entry);
+ list_del_init(&job->entry);
+ spin_unlock_irqrestore(&mdp_ppp_djob_clnrq_lock, flags);
+
+ /* Keep mem state coherent */
+ msm_fb_ensure_mem_coherency_after_dma(job->info, &job->req, 1);
+
+ /* Schedule jobs for cleanup
+ * A seperate worker thread does this */
+ queue_delayed_work(mdp_ppp_djob_clnr, &job->cleaner,
+ mdp_timer_duration);
+ }
+}
+
+/* If MDP PPP engine is busy, wait until it is available again */
+void mdp_ppp_wait(void)
+{
+ unsigned long flags;
+ int cond = 1;
+
+ /* keep flushing dirty djobs as long as MDP PPP engine is busy */
+ mdp_ppp_flush_dirty_djobs(&mdp_ppp_busy_flag);
+
+ /* block if MDP PPP engine is still busy */
+ spin_lock_irqsave(&mdp_ppp_dq_lock, flags);
+ if (test_bit(0, (unsigned long *)&mdp_ppp_busy_flag)) {
+
+ /* prepare for the wakeup event */
+ test_and_set_bit(0, (unsigned long *)&mdp_ppp_waiting);
+ INIT_COMPLETION(mdp_ppp_comp);
+ spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
+
+ /* block uninterruptibly until available */
+ MDP_PPP_DEBUG_MSG("waiting for mdp... \n");
+ wait_for_completion_killable(&mdp_ppp_comp);
+
+ /* if MDP PPP engine is still free,
+ * disable INT_MDP if enabled
+ */
+ spin_lock_irqsave(&mdp_ppp_dq_lock, flags);
+ if (!test_bit(0, (unsigned long *)&mdp_ppp_busy_flag) &&
+ test_and_clear_bit(0, (unsigned long *)&mdp_ppp_intr_flag))
+ mdp_disable_irq(MDP_PPP_TERM);
+ }
+ spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
+
+ /* flush remaining dirty djobs, if any */
+ mdp_ppp_flush_dirty_djobs(&cond);
+}
+
+/* Program MDP PPP block to process this ROI */
+static void mdp_ppp_process_roi(struct list_head *roi_cmd_list)
+{
+
+ /* program PPP engine with registered ROI commands */
+ struct mdp_ppp_roi_cmd_set *node;
+ list_for_each_entry(node, roi_cmd_list, node) {
+ int i = 0;
+ for (; i < node->ncmds; i++) {
+ MDP_PPP_DEBUG_MSG("%d: reg: 0x%x val: 0x%x \n",
+ i, node->cmd[i].reg, node->cmd[i].val);
+ outpdw(node->cmd[i].reg, node->cmd[i].val);
+ }
+ }
+
+ /* kickoff MDP PPP engine */
+ MDP_PPP_DEBUG_MSG("kicking off mdp \n");
+ outpdw(MDP_BASE + 0x30, 0x1000);
+}
+
+/* Submit this display job to MDP PPP engine */
+static void mdp_ppp_dispatch_djob(struct mdp_ppp_djob *job)
+{
+ /* enable INT_MDP if disabled */
+ if (!test_and_set_bit(0, (unsigned long *)&mdp_ppp_intr_flag))
+ mdp_enable_irq(MDP_PPP_TERM);
+
+ /* turn on PPP and CMD blocks */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ /* process this ROI */
+ mdp_ppp_process_roi(&job->roi_cmd_list);
+}
+
+/* Enqueue this display job to be cleaned up later in "mdp_ppp_djob_done" */
+static inline void mdp_ppp_enqueue_djob(struct mdp_ppp_djob *job)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&mdp_ppp_dq_lock, flags);
+ list_add_tail(&job->entry, &mdp_ppp_dq);
+ spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
+}
+
+/* First enqueue display job for cleanup and dispatch immediately
+ * if MDP PPP engine is free */
+void mdp_ppp_process_curr_djob(void)
+{
+ /* enqueue djob */
+ mdp_ppp_enqueue_djob(curr_djob);
+
+ /* dispatch now if MDP PPP engine is free */
+ if (!test_and_set_bit(0, (unsigned long *)&mdp_ppp_busy_flag))
+ mdp_ppp_dispatch_djob(curr_djob);
+
+ /* done with the current djob */
+ curr_djob = NULL;
+}
+
+/* Called from mdp_isr - cleanup finished job and start with next
+ * if available else set MDP PPP engine free */
+void mdp_ppp_djob_done(void)
+{
+ struct mdp_ppp_djob *curr, *next;
+ unsigned long flags;
+
+ /* dequeue current */
+ spin_lock_irqsave(&mdp_ppp_dq_lock, flags);
+ curr = list_entry(mdp_ppp_dq.next, struct mdp_ppp_djob, entry);
+ list_del_init(&curr->entry);
+ spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
+
+ /* cleanup current - enqueue in the djob clnr queue */
+ spin_lock_irqsave(&mdp_ppp_djob_clnrq_lock, flags);
+ list_add_tail(&curr->entry, &mdp_ppp_djob_clnrq);
+ spin_unlock_irqrestore(&mdp_ppp_djob_clnrq_lock, flags);
+
+ /* grab next pending */
+ spin_lock_irqsave(&mdp_ppp_dq_lock, flags);
+ if (!list_empty(&mdp_ppp_dq)) {
+ next = list_entry(mdp_ppp_dq.next, struct mdp_ppp_djob,
+ entry);
+ spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
+
+ /* process next in the queue */
+ mdp_ppp_process_roi(&next->roi_cmd_list);
+ } else {
+ /* no pending display job */
+ spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
+
+ /* turn off PPP and CMD blocks - "in_isr" is TRUE */
+ mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+
+ /* notify if waiting */
+ if (test_and_clear_bit(0, (unsigned long *)&mdp_ppp_waiting))
+ complete(&mdp_ppp_comp);
+
+ /* set free */
+ test_and_clear_bit(0, (unsigned long *)&mdp_ppp_busy_flag);
+ }
+}
diff --git a/drivers/staging/msm/mdp_ppp_dq.h b/drivers/staging/msm/mdp_ppp_dq.h
new file mode 100644
index 0000000..03e4e9a
--- /dev/null
+++ b/drivers/staging/msm/mdp_ppp_dq.h
@@ -0,0 +1,86 @@
+/* Copyright (c) 2009-2010, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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 MDP_PPP_DQ_H
+#define MDP_PPP_DQ_H
+
+#include "msm_fb_def.h"
+
+#define MDP_PPP_DEBUG_MSG MSM_FB_DEBUG
+
+/* The maximum number of <Reg,Val> pairs in an mdp_ppp_roi_cmd_set structure (a
+ * node)
+ */
+#define MDP_PPP_ROI_NODE_SIZE 32
+
+/* ROI config command (<Reg,Val> pair) for MDP PPP block */
+struct mdp_ppp_roi_cmd {
+ uint32_t reg;
+ uint32_t val;
+};
+
+/* ROI config commands for MDP PPP block are stored in a list of
+ * mdp_ppp_roi_cmd_set structures (nodes).
+ */
+struct mdp_ppp_roi_cmd_set {
+ struct list_head node;
+ uint32_t ncmds; /* number of commands in this set (node). */
+ struct mdp_ppp_roi_cmd cmd[MDP_PPP_ROI_NODE_SIZE];
+};
+
+/* MDP PPP Display Job (DJob) */
+struct mdp_ppp_djob {
+ struct list_head entry;
+ /* One ROI per MDP PPP DJob */
+ struct list_head roi_cmd_list;
+ struct mdp_blit_req req;
+ struct fb_info *info;
+ struct delayed_work cleaner;
+ struct file *p_src_file, *p_dst_file;
+};
+
+extern struct completion mdp_ppp_comp;
+extern boolean mdp_ppp_waiting;
+extern unsigned long mdp_timer_duration;
+
+unsigned int mdp_ppp_async_op_get(void);
+void mdp_ppp_async_op_set(unsigned int flag);
+void msm_fb_ensure_mem_coherency_after_dma(struct fb_info *info,
+ struct mdp_blit_req *req_list, int req_list_count);
+void mdp_ppp_put_img(struct file *p_src_file, struct file *p_dst_file);
+void mdp_ppp_dq_init(void);
+void mdp_ppp_outdw(uint32_t addr, uint32_t data);
+struct mdp_ppp_djob *mdp_ppp_new_djob(void);
+void mdp_ppp_clear_curr_djob(void);
+void mdp_ppp_process_curr_djob(void);
+int mdp_ppp_get_ret_code(void);
+void mdp_ppp_djob_done(void);
+void mdp_ppp_wait(void);
+
+#endif /* MDP_PPP_DQ_H */
diff --git a/drivers/staging/msm/mdp_ppp_v20.c b/drivers/staging/msm/mdp_ppp_v20.c
new file mode 100644
index 0000000..b5b7271
--- /dev/null
+++ b/drivers/staging/msm/mdp_ppp_v20.c
@@ -0,0 +1,2486 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include "linux/proc_fs.h"
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <asm/div64.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+
+static MDP_SCALE_MODE mdp_curr_up_scale_xy;
+static MDP_SCALE_MODE mdp_curr_down_scale_x;
+static MDP_SCALE_MODE mdp_curr_down_scale_y;
+
+static long long mdp_do_div(long long num, long long den)
+{
+ do_div(num, den);
+ return num;
+}
+
+struct mdp_table_entry mdp_gaussian_blur_table[] = {
+ /* max variance */
+ { 0x5fffc, 0x20000080 },
+ { 0x50280, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50284, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50288, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5028c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50290, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50294, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50298, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5029c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502a0, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502a4, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502a8, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502ac, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502b0, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502b4, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502b8, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502bc, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502c0, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502c4, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502c8, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502cc, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502d0, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502d4, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502d8, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502dc, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502e0, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502e4, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502e8, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502ec, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502f0, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502f4, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502f8, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x502fc, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50300, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50304, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50308, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5030c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50310, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50314, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50318, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5031c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50320, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50324, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50328, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5032c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50330, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50334, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50338, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5033c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50340, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50344, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50348, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5034c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50350, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50354, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50358, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5035c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50360, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50364, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50368, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5036c, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50370, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50374, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x50378, 0x20000080 },
+ { 0x5fffc, 0x20000080 },
+ { 0x5037c, 0x20000080 },
+};
+
+static void load_scale_table(
+ struct mdp_table_entry *table, int len)
+{
+ int i;
+ for (i = 0; i < len; i++)
+ MDP_OUTP(MDP_BASE + table[i].reg, table[i].val);
+}
+
+static void mdp_load_pr_upscale_table(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50200, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50204, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50208, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5020c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50210, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50214, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50218, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5021c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50220, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50224, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50228, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5022c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50230, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50234, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50238, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5023c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50240, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50244, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50248, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5024c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50250, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50254, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50258, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5025c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50260, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50264, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50268, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5026c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50270, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50274, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50278, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5027c, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_x_point2TOpoint4(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502c0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502c4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502c8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502cc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502d0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502d4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502d8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502dc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502e0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502e4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502e8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502ec, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502f0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502f4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502f8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502fc, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_y_point2TOpoint4(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50340, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50344, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50348, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5034c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50350, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50354, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50358, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5035c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50360, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50364, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50368, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5036c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50370, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50374, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50378, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5037c, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_x_point4TOpoint6(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502c0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502c4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502c8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502cc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502d0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502d4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502d8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502dc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502e0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502e4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502e8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502ec, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502f0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502f4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502f8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502fc, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_y_point4TOpoint6(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50340, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50344, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50348, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5034c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50350, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50354, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50358, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5035c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50360, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50364, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50368, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5036c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50370, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50374, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50378, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5037c, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_x_point6TOpoint8(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502c0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502c4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502c8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502cc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502d0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502d4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502d8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502dc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502e0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502e4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502e8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502ec, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502f0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502f4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502f8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502fc, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_y_point6TOpoint8(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50340, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50344, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50348, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5034c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50350, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50354, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50358, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5035c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50360, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50364, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50368, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5036c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50370, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50374, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50378, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5037c, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_x_point8TO1(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502c0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502c4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502c8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502cc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502d0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502d4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502d8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502dc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502e0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502e4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502e8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502ec, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502f0, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502f4, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502f8, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x502fc, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_y_point8TO1(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50340, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50344, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50348, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5034c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50350, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50354, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50358, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5035c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50360, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50364, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50368, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5036c, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50370, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50374, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x50378, 0x0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+ MDP_OUTP(MDP_BASE + 0x5037c, 0x0);
+}
+
+static void mdp_load_bc_upscale_table(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50200, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xff80000d);
+ MDP_OUTP(MDP_BASE + 0x50204, 0x7ec003f9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec0001c);
+ MDP_OUTP(MDP_BASE + 0x50208, 0x7d4003f3);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40002b);
+ MDP_OUTP(MDP_BASE + 0x5020c, 0x7b8003ed);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfd80003c);
+ MDP_OUTP(MDP_BASE + 0x50210, 0x794003e8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc0004d);
+ MDP_OUTP(MDP_BASE + 0x50214, 0x76c003e4);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfc40005f);
+ MDP_OUTP(MDP_BASE + 0x50218, 0x73c003e0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb800071);
+ MDP_OUTP(MDP_BASE + 0x5021c, 0x708003de);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfac00085);
+ MDP_OUTP(MDP_BASE + 0x50220, 0x6d0003db);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa000098);
+ MDP_OUTP(MDP_BASE + 0x50224, 0x698003d9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf98000ac);
+ MDP_OUTP(MDP_BASE + 0x50228, 0x654003d8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8c000c1);
+ MDP_OUTP(MDP_BASE + 0x5022c, 0x610003d7);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf84000d5);
+ MDP_OUTP(MDP_BASE + 0x50230, 0x5c8003d7);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf7c000e9);
+ MDP_OUTP(MDP_BASE + 0x50234, 0x580003d7);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf74000fd);
+ MDP_OUTP(MDP_BASE + 0x50238, 0x534003d8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c00112);
+ MDP_OUTP(MDP_BASE + 0x5023c, 0x4e8003d8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6800126);
+ MDP_OUTP(MDP_BASE + 0x50240, 0x494003da);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600013a);
+ MDP_OUTP(MDP_BASE + 0x50244, 0x448003db);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600014d);
+ MDP_OUTP(MDP_BASE + 0x50248, 0x3f4003dd);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00160);
+ MDP_OUTP(MDP_BASE + 0x5024c, 0x3a4003df);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00172);
+ MDP_OUTP(MDP_BASE + 0x50250, 0x354003e1);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00184);
+ MDP_OUTP(MDP_BASE + 0x50254, 0x304003e3);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6000195);
+ MDP_OUTP(MDP_BASE + 0x50258, 0x2b0003e6);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf64001a6);
+ MDP_OUTP(MDP_BASE + 0x5025c, 0x260003e8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c001b4);
+ MDP_OUTP(MDP_BASE + 0x50260, 0x214003eb);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf78001c2);
+ MDP_OUTP(MDP_BASE + 0x50264, 0x1c4003ee);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf80001cf);
+ MDP_OUTP(MDP_BASE + 0x50268, 0x17c003f1);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf90001db);
+ MDP_OUTP(MDP_BASE + 0x5026c, 0x134003f3);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa0001e5);
+ MDP_OUTP(MDP_BASE + 0x50270, 0xf0003f6);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb4001ee);
+ MDP_OUTP(MDP_BASE + 0x50274, 0xac003f9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc001f5);
+ MDP_OUTP(MDP_BASE + 0x50278, 0x70003fb);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe4001fb);
+ MDP_OUTP(MDP_BASE + 0x5027c, 0x34003fe);
+}
+
+static void mdp_load_bc_downscale_table_x_point2TOpoint4(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac00084);
+ MDP_OUTP(MDP_BASE + 0x50280, 0x23400083);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b000084);
+ MDP_OUTP(MDP_BASE + 0x50284, 0x23000083);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400084);
+ MDP_OUTP(MDP_BASE + 0x50288, 0x23000082);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400085);
+ MDP_OUTP(MDP_BASE + 0x5028c, 0x23000081);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b800085);
+ MDP_OUTP(MDP_BASE + 0x50290, 0x23000080);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc00086);
+ MDP_OUTP(MDP_BASE + 0x50294, 0x22c0007f);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c000086);
+ MDP_OUTP(MDP_BASE + 0x50298, 0x2280007f);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c400086);
+ MDP_OUTP(MDP_BASE + 0x5029c, 0x2280007e);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c800086);
+ MDP_OUTP(MDP_BASE + 0x502a0, 0x2280007d);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00086);
+ MDP_OUTP(MDP_BASE + 0x502a4, 0x2240007d);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00087);
+ MDP_OUTP(MDP_BASE + 0x502a8, 0x2240007c);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d000087);
+ MDP_OUTP(MDP_BASE + 0x502ac, 0x2240007b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400087);
+ MDP_OUTP(MDP_BASE + 0x502b0, 0x2200007b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400088);
+ MDP_OUTP(MDP_BASE + 0x502b4, 0x22400079);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d800088);
+ MDP_OUTP(MDP_BASE + 0x502b8, 0x22400078);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00088);
+ MDP_OUTP(MDP_BASE + 0x502bc, 0x22400077);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00089);
+ MDP_OUTP(MDP_BASE + 0x502c0, 0x22000077);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e000089);
+ MDP_OUTP(MDP_BASE + 0x502c4, 0x22000076);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e400089);
+ MDP_OUTP(MDP_BASE + 0x502c8, 0x22000075);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00088);
+ MDP_OUTP(MDP_BASE + 0x502cc, 0x21c00075);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00089);
+ MDP_OUTP(MDP_BASE + 0x502d0, 0x21c00074);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f000089);
+ MDP_OUTP(MDP_BASE + 0x502d4, 0x21c00073);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f400089);
+ MDP_OUTP(MDP_BASE + 0x502d8, 0x21800073);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f40008a);
+ MDP_OUTP(MDP_BASE + 0x502dc, 0x21800072);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f80008a);
+ MDP_OUTP(MDP_BASE + 0x502e0, 0x21800071);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008a);
+ MDP_OUTP(MDP_BASE + 0x502e4, 0x21800070);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008b);
+ MDP_OUTP(MDP_BASE + 0x502e8, 0x2180006f);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x2000008c);
+ MDP_OUTP(MDP_BASE + 0x502ec, 0x2140006e);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x2040008c);
+ MDP_OUTP(MDP_BASE + 0x502f0, 0x2140006d);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x2080008c);
+ MDP_OUTP(MDP_BASE + 0x502f4, 0x2100006d);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008c);
+ MDP_OUTP(MDP_BASE + 0x502f8, 0x2100006c);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008d);
+ MDP_OUTP(MDP_BASE + 0x502fc, 0x2100006b);
+}
+
+static void mdp_load_bc_downscale_table_y_point2TOpoint4(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac00084);
+ MDP_OUTP(MDP_BASE + 0x50300, 0x23400083);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b000084);
+ MDP_OUTP(MDP_BASE + 0x50304, 0x23000083);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400084);
+ MDP_OUTP(MDP_BASE + 0x50308, 0x23000082);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400085);
+ MDP_OUTP(MDP_BASE + 0x5030c, 0x23000081);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b800085);
+ MDP_OUTP(MDP_BASE + 0x50310, 0x23000080);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc00086);
+ MDP_OUTP(MDP_BASE + 0x50314, 0x22c0007f);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c000086);
+ MDP_OUTP(MDP_BASE + 0x50318, 0x2280007f);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c400086);
+ MDP_OUTP(MDP_BASE + 0x5031c, 0x2280007e);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c800086);
+ MDP_OUTP(MDP_BASE + 0x50320, 0x2280007d);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00086);
+ MDP_OUTP(MDP_BASE + 0x50324, 0x2240007d);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00087);
+ MDP_OUTP(MDP_BASE + 0x50328, 0x2240007c);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d000087);
+ MDP_OUTP(MDP_BASE + 0x5032c, 0x2240007b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400087);
+ MDP_OUTP(MDP_BASE + 0x50330, 0x2200007b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400088);
+ MDP_OUTP(MDP_BASE + 0x50334, 0x22400079);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d800088);
+ MDP_OUTP(MDP_BASE + 0x50338, 0x22400078);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00088);
+ MDP_OUTP(MDP_BASE + 0x5033c, 0x22400077);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00089);
+ MDP_OUTP(MDP_BASE + 0x50340, 0x22000077);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e000089);
+ MDP_OUTP(MDP_BASE + 0x50344, 0x22000076);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e400089);
+ MDP_OUTP(MDP_BASE + 0x50348, 0x22000075);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00088);
+ MDP_OUTP(MDP_BASE + 0x5034c, 0x21c00075);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00089);
+ MDP_OUTP(MDP_BASE + 0x50350, 0x21c00074);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f000089);
+ MDP_OUTP(MDP_BASE + 0x50354, 0x21c00073);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f400089);
+ MDP_OUTP(MDP_BASE + 0x50358, 0x21800073);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f40008a);
+ MDP_OUTP(MDP_BASE + 0x5035c, 0x21800072);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f80008a);
+ MDP_OUTP(MDP_BASE + 0x50360, 0x21800071);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008a);
+ MDP_OUTP(MDP_BASE + 0x50364, 0x21800070);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008b);
+ MDP_OUTP(MDP_BASE + 0x50368, 0x2180006f);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x2000008c);
+ MDP_OUTP(MDP_BASE + 0x5036c, 0x2140006e);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x2040008c);
+ MDP_OUTP(MDP_BASE + 0x50370, 0x2140006d);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x2080008c);
+ MDP_OUTP(MDP_BASE + 0x50374, 0x2100006d);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008c);
+ MDP_OUTP(MDP_BASE + 0x50378, 0x2100006c);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008d);
+ MDP_OUTP(MDP_BASE + 0x5037c, 0x2100006b);
+}
+
+static void mdp_load_bc_downscale_table_x_point4TOpoint6(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x740008c);
+ MDP_OUTP(MDP_BASE + 0x50280, 0x33800088);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x800008e);
+ MDP_OUTP(MDP_BASE + 0x50284, 0x33400084);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x8400092);
+ MDP_OUTP(MDP_BASE + 0x50288, 0x33000080);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x9000094);
+ MDP_OUTP(MDP_BASE + 0x5028c, 0x3300007b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x9c00098);
+ MDP_OUTP(MDP_BASE + 0x50290, 0x32400077);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xa40009b);
+ MDP_OUTP(MDP_BASE + 0x50294, 0x32000073);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xb00009d);
+ MDP_OUTP(MDP_BASE + 0x50298, 0x31c0006f);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xbc000a0);
+ MDP_OUTP(MDP_BASE + 0x5029c, 0x3140006b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xc8000a2);
+ MDP_OUTP(MDP_BASE + 0x502a0, 0x31000067);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xd8000a5);
+ MDP_OUTP(MDP_BASE + 0x502a4, 0x30800062);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xe4000a8);
+ MDP_OUTP(MDP_BASE + 0x502a8, 0x2fc0005f);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xec000aa);
+ MDP_OUTP(MDP_BASE + 0x502ac, 0x2fc0005b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8000ad);
+ MDP_OUTP(MDP_BASE + 0x502b0, 0x2f400057);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x108000b0);
+ MDP_OUTP(MDP_BASE + 0x502b4, 0x2e400054);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x114000b2);
+ MDP_OUTP(MDP_BASE + 0x502b8, 0x2e000050);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x124000b4);
+ MDP_OUTP(MDP_BASE + 0x502bc, 0x2d80004c);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x130000b6);
+ MDP_OUTP(MDP_BASE + 0x502c0, 0x2d000049);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x140000b8);
+ MDP_OUTP(MDP_BASE + 0x502c4, 0x2c800045);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x150000b9);
+ MDP_OUTP(MDP_BASE + 0x502c8, 0x2c000042);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x15c000bd);
+ MDP_OUTP(MDP_BASE + 0x502cc, 0x2b40003e);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x16c000bf);
+ MDP_OUTP(MDP_BASE + 0x502d0, 0x2a80003b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x17c000bf);
+ MDP_OUTP(MDP_BASE + 0x502d4, 0x2a000039);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x188000c2);
+ MDP_OUTP(MDP_BASE + 0x502d8, 0x29400036);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x19c000c4);
+ MDP_OUTP(MDP_BASE + 0x502dc, 0x28800032);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac000c5);
+ MDP_OUTP(MDP_BASE + 0x502e0, 0x2800002f);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc000c7);
+ MDP_OUTP(MDP_BASE + 0x502e4, 0x2740002c);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc000c8);
+ MDP_OUTP(MDP_BASE + 0x502e8, 0x26c00029);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc000c9);
+ MDP_OUTP(MDP_BASE + 0x502ec, 0x26000027);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec000cc);
+ MDP_OUTP(MDP_BASE + 0x502f0, 0x25000024);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x200000cc);
+ MDP_OUTP(MDP_BASE + 0x502f4, 0x24800021);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x210000cd);
+ MDP_OUTP(MDP_BASE + 0x502f8, 0x23800020);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x220000ce);
+ MDP_OUTP(MDP_BASE + 0x502fc, 0x2300001d);
+}
+
+static void mdp_load_bc_downscale_table_y_point4TOpoint6(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x740008c);
+ MDP_OUTP(MDP_BASE + 0x50300, 0x33800088);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x800008e);
+ MDP_OUTP(MDP_BASE + 0x50304, 0x33400084);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x8400092);
+ MDP_OUTP(MDP_BASE + 0x50308, 0x33000080);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x9000094);
+ MDP_OUTP(MDP_BASE + 0x5030c, 0x3300007b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x9c00098);
+ MDP_OUTP(MDP_BASE + 0x50310, 0x32400077);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xa40009b);
+ MDP_OUTP(MDP_BASE + 0x50314, 0x32000073);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xb00009d);
+ MDP_OUTP(MDP_BASE + 0x50318, 0x31c0006f);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xbc000a0);
+ MDP_OUTP(MDP_BASE + 0x5031c, 0x3140006b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xc8000a2);
+ MDP_OUTP(MDP_BASE + 0x50320, 0x31000067);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xd8000a5);
+ MDP_OUTP(MDP_BASE + 0x50324, 0x30800062);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xe4000a8);
+ MDP_OUTP(MDP_BASE + 0x50328, 0x2fc0005f);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xec000aa);
+ MDP_OUTP(MDP_BASE + 0x5032c, 0x2fc0005b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8000ad);
+ MDP_OUTP(MDP_BASE + 0x50330, 0x2f400057);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x108000b0);
+ MDP_OUTP(MDP_BASE + 0x50334, 0x2e400054);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x114000b2);
+ MDP_OUTP(MDP_BASE + 0x50338, 0x2e000050);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x124000b4);
+ MDP_OUTP(MDP_BASE + 0x5033c, 0x2d80004c);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x130000b6);
+ MDP_OUTP(MDP_BASE + 0x50340, 0x2d000049);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x140000b8);
+ MDP_OUTP(MDP_BASE + 0x50344, 0x2c800045);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x150000b9);
+ MDP_OUTP(MDP_BASE + 0x50348, 0x2c000042);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x15c000bd);
+ MDP_OUTP(MDP_BASE + 0x5034c, 0x2b40003e);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x16c000bf);
+ MDP_OUTP(MDP_BASE + 0x50350, 0x2a80003b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x17c000bf);
+ MDP_OUTP(MDP_BASE + 0x50354, 0x2a000039);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x188000c2);
+ MDP_OUTP(MDP_BASE + 0x50358, 0x29400036);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x19c000c4);
+ MDP_OUTP(MDP_BASE + 0x5035c, 0x28800032);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac000c5);
+ MDP_OUTP(MDP_BASE + 0x50360, 0x2800002f);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc000c7);
+ MDP_OUTP(MDP_BASE + 0x50364, 0x2740002c);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc000c8);
+ MDP_OUTP(MDP_BASE + 0x50368, 0x26c00029);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc000c9);
+ MDP_OUTP(MDP_BASE + 0x5036c, 0x26000027);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec000cc);
+ MDP_OUTP(MDP_BASE + 0x50370, 0x25000024);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x200000cc);
+ MDP_OUTP(MDP_BASE + 0x50374, 0x24800021);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x210000cd);
+ MDP_OUTP(MDP_BASE + 0x50378, 0x23800020);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x220000ce);
+ MDP_OUTP(MDP_BASE + 0x5037c, 0x2300001d);
+}
+
+static void mdp_load_bc_downscale_table_x_point6TOpoint8(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000070);
+ MDP_OUTP(MDP_BASE + 0x50280, 0x4bc00068);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000078);
+ MDP_OUTP(MDP_BASE + 0x50284, 0x4bc00060);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000080);
+ MDP_OUTP(MDP_BASE + 0x50288, 0x4b800059);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000089);
+ MDP_OUTP(MDP_BASE + 0x5028c, 0x4b000052);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe400091);
+ MDP_OUTP(MDP_BASE + 0x50290, 0x4a80004b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40009a);
+ MDP_OUTP(MDP_BASE + 0x50294, 0x4a000044);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe8000a3);
+ MDP_OUTP(MDP_BASE + 0x50298, 0x4940003d);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec000ac);
+ MDP_OUTP(MDP_BASE + 0x5029c, 0x48400037);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xff0000b4);
+ MDP_OUTP(MDP_BASE + 0x502a0, 0x47800031);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xff8000bd);
+ MDP_OUTP(MDP_BASE + 0x502a4, 0x4640002b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xc5);
+ MDP_OUTP(MDP_BASE + 0x502a8, 0x45000026);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x8000ce);
+ MDP_OUTP(MDP_BASE + 0x502ac, 0x43800021);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x10000d6);
+ MDP_OUTP(MDP_BASE + 0x502b0, 0x4240001c);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x18000df);
+ MDP_OUTP(MDP_BASE + 0x502b4, 0x40800018);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x24000e6);
+ MDP_OUTP(MDP_BASE + 0x502b8, 0x3f000014);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x30000ee);
+ MDP_OUTP(MDP_BASE + 0x502bc, 0x3d400010);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x40000f5);
+ MDP_OUTP(MDP_BASE + 0x502c0, 0x3b80000c);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x50000fc);
+ MDP_OUTP(MDP_BASE + 0x502c4, 0x39800009);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x6000102);
+ MDP_OUTP(MDP_BASE + 0x502c8, 0x37c00006);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x7000109);
+ MDP_OUTP(MDP_BASE + 0x502cc, 0x35800004);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x840010e);
+ MDP_OUTP(MDP_BASE + 0x502d0, 0x33800002);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x9800114);
+ MDP_OUTP(MDP_BASE + 0x502d4, 0x31400000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xac00119);
+ MDP_OUTP(MDP_BASE + 0x502d8, 0x2f4003fe);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xc40011e);
+ MDP_OUTP(MDP_BASE + 0x502dc, 0x2d0003fc);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xdc00121);
+ MDP_OUTP(MDP_BASE + 0x502e0, 0x2b0003fb);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf400125);
+ MDP_OUTP(MDP_BASE + 0x502e4, 0x28c003fa);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x11000128);
+ MDP_OUTP(MDP_BASE + 0x502e8, 0x268003f9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x12c0012a);
+ MDP_OUTP(MDP_BASE + 0x502ec, 0x244003f9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1480012c);
+ MDP_OUTP(MDP_BASE + 0x502f0, 0x224003f8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1640012e);
+ MDP_OUTP(MDP_BASE + 0x502f4, 0x200003f8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1800012f);
+ MDP_OUTP(MDP_BASE + 0x502f8, 0x1e0003f8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1a00012f);
+ MDP_OUTP(MDP_BASE + 0x502fc, 0x1c0003f8);
+}
+
+static void mdp_load_bc_downscale_table_y_point6TOpoint8(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000070);
+ MDP_OUTP(MDP_BASE + 0x50300, 0x4bc00068);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000078);
+ MDP_OUTP(MDP_BASE + 0x50304, 0x4bc00060);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000080);
+ MDP_OUTP(MDP_BASE + 0x50308, 0x4b800059);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000089);
+ MDP_OUTP(MDP_BASE + 0x5030c, 0x4b000052);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe400091);
+ MDP_OUTP(MDP_BASE + 0x50310, 0x4a80004b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40009a);
+ MDP_OUTP(MDP_BASE + 0x50314, 0x4a000044);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe8000a3);
+ MDP_OUTP(MDP_BASE + 0x50318, 0x4940003d);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec000ac);
+ MDP_OUTP(MDP_BASE + 0x5031c, 0x48400037);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xff0000b4);
+ MDP_OUTP(MDP_BASE + 0x50320, 0x47800031);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xff8000bd);
+ MDP_OUTP(MDP_BASE + 0x50324, 0x4640002b);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xc5);
+ MDP_OUTP(MDP_BASE + 0x50328, 0x45000026);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x8000ce);
+ MDP_OUTP(MDP_BASE + 0x5032c, 0x43800021);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x10000d6);
+ MDP_OUTP(MDP_BASE + 0x50330, 0x4240001c);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x18000df);
+ MDP_OUTP(MDP_BASE + 0x50334, 0x40800018);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x24000e6);
+ MDP_OUTP(MDP_BASE + 0x50338, 0x3f000014);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x30000ee);
+ MDP_OUTP(MDP_BASE + 0x5033c, 0x3d400010);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x40000f5);
+ MDP_OUTP(MDP_BASE + 0x50340, 0x3b80000c);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x50000fc);
+ MDP_OUTP(MDP_BASE + 0x50344, 0x39800009);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x6000102);
+ MDP_OUTP(MDP_BASE + 0x50348, 0x37c00006);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x7000109);
+ MDP_OUTP(MDP_BASE + 0x5034c, 0x35800004);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x840010e);
+ MDP_OUTP(MDP_BASE + 0x50350, 0x33800002);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x9800114);
+ MDP_OUTP(MDP_BASE + 0x50354, 0x31400000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xac00119);
+ MDP_OUTP(MDP_BASE + 0x50358, 0x2f4003fe);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xc40011e);
+ MDP_OUTP(MDP_BASE + 0x5035c, 0x2d0003fc);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xdc00121);
+ MDP_OUTP(MDP_BASE + 0x50360, 0x2b0003fb);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf400125);
+ MDP_OUTP(MDP_BASE + 0x50364, 0x28c003fa);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x11000128);
+ MDP_OUTP(MDP_BASE + 0x50368, 0x268003f9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x12c0012a);
+ MDP_OUTP(MDP_BASE + 0x5036c, 0x244003f9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1480012c);
+ MDP_OUTP(MDP_BASE + 0x50370, 0x224003f8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1640012e);
+ MDP_OUTP(MDP_BASE + 0x50374, 0x200003f8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1800012f);
+ MDP_OUTP(MDP_BASE + 0x50378, 0x1e0003f8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x1a00012f);
+ MDP_OUTP(MDP_BASE + 0x5037c, 0x1c0003f8);
+}
+
+static void mdp_load_bc_downscale_table_x_point8TO1(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xff80000d);
+ MDP_OUTP(MDP_BASE + 0x50284, 0x7ec003f9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec0001c);
+ MDP_OUTP(MDP_BASE + 0x50288, 0x7d4003f3);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40002b);
+ MDP_OUTP(MDP_BASE + 0x5028c, 0x7b8003ed);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfd80003c);
+ MDP_OUTP(MDP_BASE + 0x50290, 0x794003e8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc0004d);
+ MDP_OUTP(MDP_BASE + 0x50294, 0x76c003e4);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfc40005f);
+ MDP_OUTP(MDP_BASE + 0x50298, 0x73c003e0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb800071);
+ MDP_OUTP(MDP_BASE + 0x5029c, 0x708003de);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfac00085);
+ MDP_OUTP(MDP_BASE + 0x502a0, 0x6d0003db);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa000098);
+ MDP_OUTP(MDP_BASE + 0x502a4, 0x698003d9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf98000ac);
+ MDP_OUTP(MDP_BASE + 0x502a8, 0x654003d8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8c000c1);
+ MDP_OUTP(MDP_BASE + 0x502ac, 0x610003d7);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf84000d5);
+ MDP_OUTP(MDP_BASE + 0x502b0, 0x5c8003d7);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf7c000e9);
+ MDP_OUTP(MDP_BASE + 0x502b4, 0x580003d7);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf74000fd);
+ MDP_OUTP(MDP_BASE + 0x502b8, 0x534003d8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c00112);
+ MDP_OUTP(MDP_BASE + 0x502bc, 0x4e8003d8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6800126);
+ MDP_OUTP(MDP_BASE + 0x502c0, 0x494003da);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600013a);
+ MDP_OUTP(MDP_BASE + 0x502c4, 0x448003db);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600014d);
+ MDP_OUTP(MDP_BASE + 0x502c8, 0x3f4003dd);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00160);
+ MDP_OUTP(MDP_BASE + 0x502cc, 0x3a4003df);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00172);
+ MDP_OUTP(MDP_BASE + 0x502d0, 0x354003e1);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00184);
+ MDP_OUTP(MDP_BASE + 0x502d4, 0x304003e3);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6000195);
+ MDP_OUTP(MDP_BASE + 0x502d8, 0x2b0003e6);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf64001a6);
+ MDP_OUTP(MDP_BASE + 0x502dc, 0x260003e8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c001b4);
+ MDP_OUTP(MDP_BASE + 0x502e0, 0x214003eb);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf78001c2);
+ MDP_OUTP(MDP_BASE + 0x502e4, 0x1c4003ee);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf80001cf);
+ MDP_OUTP(MDP_BASE + 0x502e8, 0x17c003f1);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf90001db);
+ MDP_OUTP(MDP_BASE + 0x502ec, 0x134003f3);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa0001e5);
+ MDP_OUTP(MDP_BASE + 0x502f0, 0xf0003f6);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb4001ee);
+ MDP_OUTP(MDP_BASE + 0x502f4, 0xac003f9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc001f5);
+ MDP_OUTP(MDP_BASE + 0x502f8, 0x70003fb);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe4001fb);
+ MDP_OUTP(MDP_BASE + 0x502fc, 0x34003fe);
+}
+
+static void mdp_load_bc_downscale_table_y_point8TO1(void)
+{
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+ MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xff80000d);
+ MDP_OUTP(MDP_BASE + 0x50304, 0x7ec003f9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec0001c);
+ MDP_OUTP(MDP_BASE + 0x50308, 0x7d4003f3);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40002b);
+ MDP_OUTP(MDP_BASE + 0x5030c, 0x7b8003ed);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfd80003c);
+ MDP_OUTP(MDP_BASE + 0x50310, 0x794003e8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc0004d);
+ MDP_OUTP(MDP_BASE + 0x50314, 0x76c003e4);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfc40005f);
+ MDP_OUTP(MDP_BASE + 0x50318, 0x73c003e0);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb800071);
+ MDP_OUTP(MDP_BASE + 0x5031c, 0x708003de);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfac00085);
+ MDP_OUTP(MDP_BASE + 0x50320, 0x6d0003db);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa000098);
+ MDP_OUTP(MDP_BASE + 0x50324, 0x698003d9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf98000ac);
+ MDP_OUTP(MDP_BASE + 0x50328, 0x654003d8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8c000c1);
+ MDP_OUTP(MDP_BASE + 0x5032c, 0x610003d7);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf84000d5);
+ MDP_OUTP(MDP_BASE + 0x50330, 0x5c8003d7);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf7c000e9);
+ MDP_OUTP(MDP_BASE + 0x50334, 0x580003d7);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf74000fd);
+ MDP_OUTP(MDP_BASE + 0x50338, 0x534003d8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c00112);
+ MDP_OUTP(MDP_BASE + 0x5033c, 0x4e8003d8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6800126);
+ MDP_OUTP(MDP_BASE + 0x50340, 0x494003da);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600013a);
+ MDP_OUTP(MDP_BASE + 0x50344, 0x448003db);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600014d);
+ MDP_OUTP(MDP_BASE + 0x50348, 0x3f4003dd);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00160);
+ MDP_OUTP(MDP_BASE + 0x5034c, 0x3a4003df);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00172);
+ MDP_OUTP(MDP_BASE + 0x50350, 0x354003e1);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00184);
+ MDP_OUTP(MDP_BASE + 0x50354, 0x304003e3);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6000195);
+ MDP_OUTP(MDP_BASE + 0x50358, 0x2b0003e6);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf64001a6);
+ MDP_OUTP(MDP_BASE + 0x5035c, 0x260003e8);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c001b4);
+ MDP_OUTP(MDP_BASE + 0x50360, 0x214003eb);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf78001c2);
+ MDP_OUTP(MDP_BASE + 0x50364, 0x1c4003ee);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf80001cf);
+ MDP_OUTP(MDP_BASE + 0x50368, 0x17c003f1);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xf90001db);
+ MDP_OUTP(MDP_BASE + 0x5036c, 0x134003f3);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa0001e5);
+ MDP_OUTP(MDP_BASE + 0x50370, 0xf0003f6);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb4001ee);
+ MDP_OUTP(MDP_BASE + 0x50374, 0xac003f9);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc001f5);
+ MDP_OUTP(MDP_BASE + 0x50378, 0x70003fb);
+ MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe4001fb);
+ MDP_OUTP(MDP_BASE + 0x5037c, 0x34003fe);
+}
+
+static int mdp_get_edge_cond(MDPIBUF *iBuf, uint32 *dup, uint32 *dup2)
+{
+ uint32 reg;
+ uint32 dst_roi_width; /* Dimensions of DST ROI. */
+ uint32 dst_roi_height; /* Used to calculate scaling ratios. */
+
+ /*
+ * positions of the luma pixel(relative to the image ) required for
+ * scaling the ROI
+ */
+ int32 luma_interp_point_left = 0; /* left-most luma pixel needed */
+ int32 luma_interp_point_right = 0; /* right-most luma pixel needed */
+ int32 luma_interp_point_top = 0; /* top-most luma pixel needed */
+ int32 luma_interp_point_bottom = 0; /* bottom-most luma pixel needed */
+
+ /*
+ * positions of the chroma pixel(relative to the image ) required for
+ * interpolating a chroma value at all required luma positions
+ */
+ /* left-most chroma pixel needed */
+ int32 chroma_interp_point_left = 0;
+ /* right-most chroma pixel needed */
+ int32 chroma_interp_point_right = 0;
+ /* top-most chroma pixel needed */
+ int32 chroma_interp_point_top = 0;
+ /* bottom-most chroma pixel needed */
+ int32 chroma_interp_point_bottom = 0;
+
+ /*
+ * a rectangular region within the chroma plane of the "image".
+ * Chroma pixels falling inside of this rectangle belongs to the ROI
+ */
+ int32 chroma_bound_left = 0;
+ int32 chroma_bound_right = 0;
+ int32 chroma_bound_top = 0;
+ int32 chroma_bound_bottom = 0;
+
+ /*
+ * number of chroma pixels to replicate on the left, right,
+ * top and bottom edge of the ROI.
+ */
+ int32 chroma_repeat_left = 0;
+ int32 chroma_repeat_right = 0;
+ int32 chroma_repeat_top = 0;
+ int32 chroma_repeat_bottom = 0;
+
+ /*
+ * number of luma pixels to replicate on the left, right,
+ * top and bottom edge of the ROI.
+ */
+ int32 luma_repeat_left = 0;
+ int32 luma_repeat_right = 0;
+ int32 luma_repeat_top = 0;
+ int32 luma_repeat_bottom = 0;
+
+ boolean chroma_edge_enable;
+
+ uint32 _is_scale_enabled = 0;
+ uint32 _is_yuv_offsite_vertical = 0;
+
+ /* fg edge duplicate */
+ reg = 0x0;
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_ASCALE) { /* if scaling enabled */
+
+ _is_scale_enabled = 1;
+
+ /*
+ * if rotation mode involves a 90 deg rotation, flip
+ * dst_roi_width with dst_roi_height.
+ * Scaling ratios is based on source ROI dimensions, and
+ * dst ROI dimensions before rotation.
+ */
+ if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
+ dst_roi_width = iBuf->roi.dst_height;
+ dst_roi_height = iBuf->roi.dst_width;
+ } else {
+ dst_roi_width = iBuf->roi.dst_width;
+ dst_roi_height = iBuf->roi.dst_height;
+ }
+
+ /*
+ * Find out the luma pixels needed for scaling in the
+ * x direction (LEFT and RIGHT). Locations of pixels are
+ * relative to the ROI. Upper-left corner of ROI corresponds
+ * to coordinates (0,0). Also set the number of luma pixel
+ * to repeat.
+ */
+ if (iBuf->roi.width > 3 * dst_roi_width) {
+ /* scale factor < 1/3 */
+ luma_interp_point_left = 0;
+ luma_interp_point_right = (iBuf->roi.width - 1);
+ luma_repeat_left = 0;
+ luma_repeat_right = 0;
+ } else if (iBuf->roi.width == 3 * dst_roi_width) {
+ /* scale factor == 1/3 */
+ luma_interp_point_left = 0;
+ luma_interp_point_right = (iBuf->roi.width - 1) + 1;
+ luma_repeat_left = 0;
+ luma_repeat_right = 1;
+ } else if ((iBuf->roi.width > dst_roi_width) &&
+ (iBuf->roi.width < 3 * dst_roi_width)) {
+ /* 1/3 < scale factor < 1 */
+ luma_interp_point_left = -1;
+ luma_interp_point_right = (iBuf->roi.width - 1) + 1;
+ luma_repeat_left = 1;
+ luma_repeat_right = 1;
+ }
+
+ else if (iBuf->roi.width == dst_roi_width) {
+ /* scale factor == 1 */
+ luma_interp_point_left = -1;
+ luma_interp_point_right = (iBuf->roi.width - 1) + 2;
+ luma_repeat_left = 1;
+ luma_repeat_right = 2;
+ } else { /* (iBuf->roi.width < dst_roi_width) */
+ /* scale factor > 1 */
+ luma_interp_point_left = -2;
+ luma_interp_point_right = (iBuf->roi.width - 1) + 2;
+ luma_repeat_left = 2;
+ luma_repeat_right = 2;
+ }
+
+ /*
+ * Find out the number of pixels needed for scaling in the
+ * y direction (TOP and BOTTOM). Locations of pixels are
+ * relative to the ROI. Upper-left corner of ROI corresponds
+ * to coordinates (0,0). Also set the number of luma pixel
+ * to repeat.
+ */
+ if (iBuf->roi.height > 3 * dst_roi_height) {
+ /* scale factor < 1/3 */
+ luma_interp_point_top = 0;
+ luma_interp_point_bottom = (iBuf->roi.height - 1);
+ luma_repeat_top = 0;
+ luma_repeat_bottom = 0;
+ } else if (iBuf->roi.height == 3 * dst_roi_height) {
+ /* scale factor == 1/3 */
+ luma_interp_point_top = 0;
+ luma_interp_point_bottom = (iBuf->roi.height - 1) + 1;
+ luma_repeat_top = 0;
+ luma_repeat_bottom = 1;
+ } else if ((iBuf->roi.height > dst_roi_height) &&
+ (iBuf->roi.height < 3 * dst_roi_height)) {
+ /* 1/3 < scale factor < 1 */
+ luma_interp_point_top = -1;
+ luma_interp_point_bottom = (iBuf->roi.height - 1) + 1;
+ luma_repeat_top = 1;
+ luma_repeat_bottom = 1;
+ } else if (iBuf->roi.height == dst_roi_height) {
+ /* scale factor == 1 */
+ luma_interp_point_top = -1;
+ luma_interp_point_bottom = (iBuf->roi.height - 1) + 2;
+ luma_repeat_top = 1;
+ luma_repeat_bottom = 2;
+ } else { /* (iBuf->roi.height < dst_roi_height) */
+ /* scale factor > 1 */
+ luma_interp_point_top = -2;
+ luma_interp_point_bottom = (iBuf->roi.height - 1) + 2;
+ luma_repeat_top = 2;
+ luma_repeat_bottom = 2;
+ }
+ } /* if (iBuf->scale.scale_flag) */
+ else { /* scaling disabled */
+ /*
+ * Since no scaling needed, Tile Fetch does not require any
+ * more luma pixel than what the ROI contains.
+ */
+ luma_interp_point_left = (int32) 0;
+ luma_interp_point_right = (int32) (iBuf->roi.width - 1);
+ luma_interp_point_top = (int32) 0;
+ luma_interp_point_bottom = (int32) (iBuf->roi.height - 1);
+
+ luma_repeat_left = 0;
+ luma_repeat_right = 0;
+ luma_repeat_top = 0;
+ luma_repeat_bottom = 0;
+ }
+
+ /* After adding the ROI offsets, we have locations of
+ * luma_interp_points relative to the image.
+ */
+ luma_interp_point_left += (int32) (iBuf->roi.x);
+ luma_interp_point_right += (int32) (iBuf->roi.x);
+ luma_interp_point_top += (int32) (iBuf->roi.y);
+ luma_interp_point_bottom += (int32) (iBuf->roi.y);
+
+ /*
+ * After adding the ROI offsets, we have locations of
+ * chroma_interp_points relative to the image.
+ */
+ chroma_interp_point_left = luma_interp_point_left;
+ chroma_interp_point_right = luma_interp_point_right;
+ chroma_interp_point_top = luma_interp_point_top;
+ chroma_interp_point_bottom = luma_interp_point_bottom;
+
+ chroma_edge_enable = TRUE;
+ /* find out which chroma pixels are needed for chroma upsampling. */
+ switch (iBuf->mdpImg.imgType) {
+ /*
+ * cosite in horizontal axis
+ * fully sampled in vertical axis
+ */
+ case MDP_Y_CBCR_H2V1:
+ case MDP_Y_CRCB_H2V1:
+ case MDP_YCRYCB_H2V1:
+ /* floor( luma_interp_point_left / 2 ); */
+ chroma_interp_point_left = luma_interp_point_left >> 1;
+ /* floor( ( luma_interp_point_right + 1 ) / 2 ); */
+ chroma_interp_point_right = (luma_interp_point_right + 1) >> 1;
+
+ chroma_interp_point_top = luma_interp_point_top;
+ chroma_interp_point_bottom = luma_interp_point_bottom;
+ break;
+
+ /*
+ * cosite in horizontal axis
+ * offsite in vertical axis
+ */
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CRCB_H2V2:
+ /* floor( luma_interp_point_left / 2) */
+ chroma_interp_point_left = luma_interp_point_left >> 1;
+
+ /* floor( ( luma_interp_point_right + 1 )/ 2 ) */
+ chroma_interp_point_right = (luma_interp_point_right + 1) >> 1;
+
+ /* floor( (luma_interp_point_top - 1 ) / 2 ) */
+ chroma_interp_point_top = (luma_interp_point_top - 1) >> 1;
+
+ /* floor( ( luma_interp_point_bottom + 1 ) / 2 ) */
+ chroma_interp_point_bottom =
+ (luma_interp_point_bottom + 1) >> 1;
+
+ _is_yuv_offsite_vertical = 1;
+ break;
+
+ default:
+ chroma_edge_enable = FALSE;
+ chroma_interp_point_left = luma_interp_point_left;
+ chroma_interp_point_right = luma_interp_point_right;
+ chroma_interp_point_top = luma_interp_point_top;
+ chroma_interp_point_bottom = luma_interp_point_bottom;
+
+ break;
+ }
+
+ /* only if the image type is in YUV domain, we calculate chroma edge */
+ if (chroma_edge_enable) {
+ /* Defines which chroma pixels belongs to the roi */
+ switch (iBuf->mdpImg.imgType) {
+ /*
+ * Cosite in horizontal direction, and fully sampled
+ * in vertical direction.
+ */
+ case MDP_Y_CBCR_H2V1:
+ case MDP_Y_CRCB_H2V1:
+ case MDP_YCRYCB_H2V1:
+ /*
+ * width of chroma ROI is 1/2 of size of luma ROI
+ * height of chroma ROI same as size of luma ROI
+ */
+ chroma_bound_left = iBuf->roi.x / 2;
+
+ /* there are half as many chroma pixel as luma pixels */
+ chroma_bound_right =
+ (iBuf->roi.width + iBuf->roi.x - 1) / 2;
+ chroma_bound_top = iBuf->roi.y;
+ chroma_bound_bottom =
+ (iBuf->roi.height + iBuf->roi.y - 1);
+ break;
+
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CRCB_H2V2:
+ /*
+ * cosite in horizontal dir, and offsite in vertical dir
+ * width of chroma ROI is 1/2 of size of luma ROI
+ * height of chroma ROI is 1/2 of size of luma ROI
+ */
+
+ chroma_bound_left = iBuf->roi.x / 2;
+ chroma_bound_right =
+ (iBuf->roi.width + iBuf->roi.x - 1) / 2;
+ chroma_bound_top = iBuf->roi.y / 2;
+ chroma_bound_bottom =
+ (iBuf->roi.height + iBuf->roi.y - 1) / 2;
+ break;
+
+ default:
+ /*
+ * If no valid chroma sub-sampling format specified,
+ * assume 4:4:4 ( i.e. fully sampled). Set ROI
+ * boundaries for chroma same as ROI boundaries for
+ * luma.
+ */
+ chroma_bound_left = iBuf->roi.x;
+ chroma_bound_right = iBuf->roi.width + iBuf->roi.x - 1;
+ chroma_bound_top = iBuf->roi.y;
+ chroma_bound_bottom =
+ (iBuf->roi.height + iBuf->roi.y - 1);
+ break;
+ }
+
+ /*
+ * Knowing which chroma pixels are needed, and which chroma
+ * pixels belong to the ROI (i.e. available for fetching ),
+ * calculate how many chroma pixels Tile Fetch needs to
+ * duplicate. If any required chroma pixels falls outside
+ * of the ROI, Tile Fetch must obtain them by replicating
+ * pixels.
+ */
+ if (chroma_bound_left > chroma_interp_point_left)
+ chroma_repeat_left =
+ chroma_bound_left - chroma_interp_point_left;
+ else
+ chroma_repeat_left = 0;
+
+ if (chroma_interp_point_right > chroma_bound_right)
+ chroma_repeat_right =
+ chroma_interp_point_right - chroma_bound_right;
+ else
+ chroma_repeat_right = 0;
+
+ if (chroma_bound_top > chroma_interp_point_top)
+ chroma_repeat_top =
+ chroma_bound_top - chroma_interp_point_top;
+ else
+ chroma_repeat_top = 0;
+
+ if (chroma_interp_point_bottom > chroma_bound_bottom)
+ chroma_repeat_bottom =
+ chroma_interp_point_bottom - chroma_bound_bottom;
+ else
+ chroma_repeat_bottom = 0;
+
+ if (_is_scale_enabled && (iBuf->roi.height == 1)
+ && _is_yuv_offsite_vertical) {
+ chroma_repeat_bottom = 3;
+ chroma_repeat_top = 0;
+ }
+ }
+ /* make sure chroma repeats are non-negative */
+ if ((chroma_repeat_left < 0) || (chroma_repeat_right < 0) ||
+ (chroma_repeat_top < 0) || (chroma_repeat_bottom < 0))
+ return -1;
+
+ /* make sure chroma repeats are no larger than 3 pixels */
+ if ((chroma_repeat_left > 3) || (chroma_repeat_right > 3) ||
+ (chroma_repeat_top > 3) || (chroma_repeat_bottom > 3))
+ return -1;
+
+ /* make sure luma repeats are non-negative */
+ if ((luma_repeat_left < 0) || (luma_repeat_right < 0) ||
+ (luma_repeat_top < 0) || (luma_repeat_bottom < 0))
+ return -1;
+
+ /* make sure luma repeats are no larger than 3 pixels */
+ if ((luma_repeat_left > 3) || (luma_repeat_right > 3) ||
+ (luma_repeat_top > 3) || (luma_repeat_bottom > 3))
+ return -1;
+
+ /* write chroma_repeat_left to register */
+ reg |= (chroma_repeat_left & 3) << MDP_LEFT_CHROMA;
+
+ /* write chroma_repeat_right to register */
+ reg |= (chroma_repeat_right & 3) << MDP_RIGHT_CHROMA;
+
+ /* write chroma_repeat_top to register */
+ reg |= (chroma_repeat_top & 3) << MDP_TOP_CHROMA;
+
+ /* write chroma_repeat_bottom to register */
+ reg |= (chroma_repeat_bottom & 3) << MDP_BOTTOM_CHROMA;
+
+ /* write luma_repeat_left to register */
+ reg |= (luma_repeat_left & 3) << MDP_LEFT_LUMA;
+
+ /* write luma_repeat_right to register */
+ reg |= (luma_repeat_right & 3) << MDP_RIGHT_LUMA;
+
+ /* write luma_repeat_top to register */
+ reg |= (luma_repeat_top & 3) << MDP_TOP_LUMA;
+
+ /* write luma_repeat_bottom to register */
+ reg |= (luma_repeat_bottom & 3) << MDP_BOTTOM_LUMA;
+
+ /* done with reg */
+ *dup = reg;
+
+ /* bg edge duplicate */
+ reg = 0x0;
+
+ switch (iBuf->ibuf_type) {
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CRCB_H2V2:
+ /*
+ * Edge condition for MDP_Y_CRCB/CBCR_H2V2 cosite only.
+ * For 420 cosite, 1 chroma replicated on all sides except
+ * left, so reg 101b8 should be 0x0209. For 420 offsite,
+ * 1 chroma replicated all sides.
+ */
+ if (iBuf->roi.lcd_y == 0) {
+ reg |= BIT(MDP_TOP_CHROMA);
+ }
+
+ if ((iBuf->roi.lcd_y + iBuf->roi.dst_height) ==
+ iBuf->ibuf_height) {
+ reg |= BIT(MDP_BOTTOM_CHROMA);
+ }
+
+ if (((iBuf->roi.lcd_x + iBuf->roi.dst_width) ==
+ iBuf->ibuf_width) && ((iBuf->roi.dst_width % 2) == 0)) {
+ reg |= BIT(MDP_RIGHT_CHROMA);
+ }
+
+ break;
+
+ case MDP_Y_CBCR_H2V1:
+ case MDP_Y_CRCB_H2V1:
+ case MDP_YCRYCB_H2V1:
+ if (((iBuf->roi.lcd_x + iBuf->roi.dst_width) ==
+ iBuf->ibuf_width) && ((iBuf->roi.dst_width % 2) == 0)) {
+ reg |= BIT(MDP_RIGHT_CHROMA);
+ }
+ break;
+ default:
+ break;
+ }
+
+ *dup2 = reg;
+
+ return 0;
+}
+
+#define ADJUST_IP /* for 1/3 scale factor fix */
+
+static int mdp_calc_scale_params(
+/* ROI origin coordinate for the dimension */
+ uint32 org,
+/* src ROI dimension */
+ uint32 dim_in,
+/* scaled ROI dimension*/
+ uint32 dim_out,
+/* is this ROI width dimension? */
+ boolean is_W,
+/* initial phase location address */
+ int32 *phase_init_ptr,
+/* phase increment location address */
+ uint32 *phase_step_ptr,
+/* ROI start over-fetch location address */
+ uint32 *num_repl_beg_ptr,
+/* ROI end over-fetch location address */
+ uint32 *num_repl_end_ptr)
+{
+ boolean rpa_on = FALSE;
+ int init_phase = 0;
+ uint32 beg_of = 0;
+ uint32 end_of = 0;
+ uint64 numer = 0;
+ uint64 denom = 0;
+ /*uint64 inverter = 1; */
+ int64 point5 = 1;
+ int64 one = 1;
+ int64 k1, k2, k3, k4; /* linear equation coefficients */
+ uint64 int_mask;
+ uint64 fract_mask;
+ uint64 Os;
+ int64 Osprime;
+ int64 Od;
+ int64 Odprime;
+ int64 Oreq;
+ uint64 Es;
+ uint64 Ed;
+ uint64 Ereq;
+#ifdef ADJUST_IP
+ int64 IP64;
+ int64 delta;
+#endif
+ uint32 mult;
+
+ /*
+ * The phase accumulator should really be rational for all cases in a
+ * general purpose polyphase scaler for a tiled architecture with
+ * non-zero * origin capability because there is no way to represent
+ * certain scale factors in fixed point regardless of precision.
+ * The error incurred in attempting to use fixed point is most
+ * eggregious for SF where 1/SF is an integral multiple of 1/3.
+ *
+ * However, since the MDP2 has already been committed to HW, we
+ * only use the rational phase accumulator (RPA) when 1/SF is an
+ * integral multiple of 1/3. This will help minimize regressions in
+ * matching the HW to the C-Sim.
+ */
+ /*
+ * Set the RPA flag for this dimension.
+ *
+ * In order for 1/SF (dim_in/dim_out) to be an integral multiple of
+ * 1/3, dim_out must be an integral multiple of 3.
+ */
+ if (!(dim_out % 3)) {
+ mult = dim_out / 3;
+ rpa_on = (!(dim_in % mult));
+ }
+
+ numer = dim_out;
+ denom = dim_in;
+
+ /*
+ * convert to U30.34 before division
+ *
+ * The K vectors carry 4 extra bits of precision
+ * and are rounded.
+ *
+ * We initially go 5 bits over then round by adding
+ * 1 and right shifting by 1
+ * so final result is U31.33
+ */
+ numer <<= PQF_PLUS_5;
+
+ /* now calculate the scale factor (aka k3) */
+ k3 = ((mdp_do_div(numer, denom) + 1) >> 1);
+
+ /* check scale factor for legal range [0.25 - 4.0] */
+ if (((k3 >> 4) < (1LL << PQF_MINUS_2)) ||
+ ((k3 >> 4) > (1LL << PQF_PLUS_2))) {
+ return -1;
+ }
+
+ /* calculate inverse scale factor (aka k1) for phase init */
+ numer = dim_in;
+ denom = dim_out;
+ numer <<= PQF_PLUS_5;
+ k1 = ((mdp_do_div(numer, denom) + 1) >> 1);
+
+ /*
+ * calculate initial phase and ROI overfetch
+ */
+ /* convert point5 & one to S39.24 (will always be positive) */
+ point5 <<= (PQF_PLUS_4 - 1);
+ one <<= PQF_PLUS_4;
+ k2 = ((k1 - one) >> 1);
+ init_phase = (int)(k2 >> 4);
+ k4 = ((k3 - one) >> 1);
+ if (k3 == one) {
+ /* the simple case; SF = 1.0 */
+ beg_of = 1;
+ end_of = 2;
+ } else {
+ /* calculate the masks */
+ fract_mask = one - 1;
+ int_mask = ~fract_mask;
+
+ if (!rpa_on) {
+ /*
+ * FIXED POINT IMPLEMENTATION
+ */
+ if (!org) {
+ /* A fairly simple case; ROI origin = 0 */
+ if (k1 < one) {
+ /* upscaling */
+ beg_of = end_of = 2;
+ }
+ /* 0.33 <= SF < 1.0 */
+ else if (k1 < (3LL << PQF_PLUS_4))
+ beg_of = end_of = 1;
+ /* 0.33 == SF */
+ else if (k1 == (3LL << PQF_PLUS_4)) {
+ beg_of = 0;
+ end_of = 1;
+ }
+ /* 0.25 <= SF < 0.33 */
+ else
+ beg_of = end_of = 0;
+ } else {
+ /*
+ * The complicated case; ROI origin != 0
+ * init_phase needs to be adjusted
+ * OF is also position dependent
+ */
+
+ /* map (org - .5) into destination space */
+ Os = ((uint64) org << 1) - 1;
+ Od = ((k3 * Os) >> 1) + k4;
+
+ /* take the ceiling */
+ Odprime = (Od & int_mask);
+ if (Odprime != Od)
+ Odprime += one;
+
+ /* now map that back to source space */
+ Osprime = (k1 * (Odprime >> PQF_PLUS_4)) + k2;
+
+ /* then floor & decrement to calculate the required
+ starting coordinate */
+ Oreq = (Osprime & int_mask) - one;
+
+ /* calculate end coord in destination space then map to
+ source space */
+ Ed = Odprime +
+ ((uint64) dim_out << PQF_PLUS_4) - one;
+ Es = (k1 * (Ed >> PQF_PLUS_4)) + k2;
+
+ /* now floor & increment by 2 to calculate the required
+ ending coordinate */
+ Ereq = (Es & int_mask) + (one << 1);
+
+ /* calculate initial phase */
+#ifdef ADJUST_IP
+
+ IP64 = Osprime - Oreq;
+ delta = ((int64) (org) << PQF_PLUS_4) - Oreq;
+ IP64 -= delta;
+
+ /* limit to valid range before the left shift */
+ delta = (IP64 & (1LL << 63)) ? 4 : -4;
+ delta <<= PQF_PLUS_4;
+ while (abs((int)(IP64 >> PQF_PLUS_4)) > 4)
+ IP64 += delta;
+
+ /* right shift to account for extra bits of precision */
+ init_phase = (int)(IP64 >> 4);
+
+#else /* ADJUST_IP */
+
+ /* just calculate the real initial phase */
+ init_phase = (int)((Osprime - Oreq) >> 4);
+
+#endif /* ADJUST_IP */
+
+ /* calculate the overfetch */
+ beg_of = org - (uint32) (Oreq >> PQF_PLUS_4);
+ end_of =
+ (uint32) (Ereq >> PQF_PLUS_4) - (org +
+ dim_in -
+ 1);
+ }
+ } else {
+ /*
+ * RPA IMPLEMENTATION
+ *
+ * init_phase needs to be calculated in all RPA_on cases
+ * because it's a numerator, not a fixed point value.
+ */
+
+ /* map (org - .5) into destination space */
+ Os = ((uint64) org << PQF_PLUS_4) - point5;
+ Od = mdp_do_div((dim_out * (Os + point5)),
+ dim_in) - point5;
+
+ /* take the ceiling */
+ Odprime = (Od & int_mask);
+ if (Odprime != Od)
+ Odprime += one;
+
+ /* now map that back to source space */
+ Osprime =
+ mdp_do_div((dim_in * (Odprime + point5)),
+ dim_out) - point5;
+
+ /* then floor & decrement to calculate the required
+ starting coordinate */
+ Oreq = (Osprime & int_mask) - one;
+
+ /* calculate end coord in destination space then map to
+ source space */
+ Ed = Odprime + ((uint64) dim_out << PQF_PLUS_4) - one;
+ Es = mdp_do_div((dim_in * (Ed + point5)),
+ dim_out) - point5;
+
+ /* now floor & increment by 2 to calculate the required
+ ending coordinate */
+ Ereq = (Es & int_mask) + (one << 1);
+
+ /* calculate initial phase */
+
+#ifdef ADJUST_IP
+
+ IP64 = Osprime - Oreq;
+ delta = ((int64) (org) << PQF_PLUS_4) - Oreq;
+ IP64 -= delta;
+
+ /* limit to valid range before the left shift */
+ delta = (IP64 & (1LL << 63)) ? 4 : -4;
+ delta <<= PQF_PLUS_4;
+ while (abs((int)(IP64 >> PQF_PLUS_4)) > 4)
+ IP64 += delta;
+
+ /* right shift to account for extra bits of precision */
+ init_phase = (int)(IP64 >> 4);
+
+#else /* ADJUST_IP */
+
+ /* just calculate the real initial phase */
+ init_phase = (int)((Osprime - Oreq) >> 4);
+
+#endif /* ADJUST_IP */
+
+ /* calculate the overfetch */
+ beg_of = org - (uint32) (Oreq >> PQF_PLUS_4);
+ end_of =
+ (uint32) (Ereq >> PQF_PLUS_4) - (org + dim_in - 1);
+ }
+ }
+
+ /* return the scale parameters */
+ *phase_init_ptr = init_phase;
+ *phase_step_ptr = (uint32) (k1 >> 4);
+ *num_repl_beg_ptr = beg_of;
+ *num_repl_end_ptr = end_of;
+
+ return 0;
+}
+
+static uint8 *mdp_adjust_rot_addr(MDPIBUF *iBuf, uint8 *addr, uint32 uv)
+{
+ uint32 dest_ystride = iBuf->ibuf_width * iBuf->bpp;
+ uint32 h_slice = 1;
+
+ if (uv && ((iBuf->ibuf_type == MDP_Y_CBCR_H2V2) ||
+ (iBuf->ibuf_type == MDP_Y_CRCB_H2V2)))
+ h_slice = 2;
+
+ if (MDP_CHKBIT(iBuf->mdpImg.mdpOp, MDPOP_ROT90) ^
+ MDP_CHKBIT(iBuf->mdpImg.mdpOp, MDPOP_LR)) {
+ addr =
+ addr + (iBuf->roi.dst_width -
+ MIN(16, iBuf->roi.dst_width)) * iBuf->bpp;
+ }
+ if (MDP_CHKBIT(iBuf->mdpImg.mdpOp, MDPOP_UD)) {
+ addr =
+ addr + ((iBuf->roi.dst_height -
+ MIN(16, iBuf->roi.dst_height))/h_slice) * dest_ystride;
+ }
+
+ return addr;
+}
+
+void mdp_set_scale(MDPIBUF *iBuf,
+ uint32 dst_roi_width,
+ uint32 dst_roi_height,
+ boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr)
+{
+ uint32 dst_roi_width_scale;
+ uint32 dst_roi_height_scale;
+ boolean use_pr;
+ uint32 phasex_step = 0;
+ uint32 phasey_step = 0;
+ int32 phasex_init = 0;
+ int32 phasey_init = 0;
+ uint32 lines_dup = 0;
+ uint32 lines_dup_bg = 0;
+ uint32 dummy;
+ uint32 mdp_blur = 0;
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_ASCALE) {
+ if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
+ dst_roi_width_scale = dst_roi_height;
+ dst_roi_height_scale = dst_roi_width;
+ } else {
+ dst_roi_width_scale = dst_roi_width;
+ dst_roi_height_scale = dst_roi_height;
+ }
+
+ mdp_blur = iBuf->mdpImg.mdpOp & MDPOP_BLUR;
+
+ if ((dst_roi_width_scale != iBuf->roi.width) ||
+ (dst_roi_height_scale != iBuf->roi.height) ||
+ mdp_blur) {
+ *pppop_reg_ptr |=
+ (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
+
+ /* let's use SHIM logic to calculate the partial ROI scaling */
+#if 0
+ phasex_step =
+ (uint32) mdp_do_div(0x20000000 * iBuf->roi.width,
+ dst_roi_width_scale);
+ phasey_step =
+ (uint32) mdp_do_div(0x20000000 * iBuf->roi.height,
+ dst_roi_height_scale);
+
+/*
+ phasex_step= ((long long) iBuf->roi.width * 0x20000000)/dst_roi_width_scale;
+ phasey_step= ((long long)iBuf->roi.height * 0x20000000)/dst_roi_height_scale;
+*/
+
+ phasex_init =
+ (((long long)phasex_step - 0x20000000) >> 1);
+ phasey_init =
+ (((long long)phasey_step - 0x20000000) >> 1);
+
+#else
+ mdp_calc_scale_params(iBuf->roi.x, iBuf->roi.width,
+ dst_roi_width_scale, 1,
+ &phasex_init, &phasex_step,
+ &dummy, &dummy);
+ mdp_calc_scale_params(iBuf->roi.y, iBuf->roi.height,
+ dst_roi_height_scale, 0,
+ &phasey_init, &phasey_step,
+ &dummy, &dummy);
+#endif
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x013c,
+ phasex_init);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0140,
+ phasey_init);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0144,
+ phasex_step);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0148,
+ phasey_step);
+
+ use_pr = (inputRGB) && (outputRGB);
+
+ if ((dst_roi_width_scale > iBuf->roi.width) ||
+ (dst_roi_height_scale > iBuf->roi.height)) {
+ if ((use_pr)
+ && (mdp_curr_up_scale_xy !=
+ MDP_PR_SCALE_UP)) {
+ mdp_load_pr_upscale_table();
+ mdp_curr_up_scale_xy = MDP_PR_SCALE_UP;
+ } else if ((!use_pr)
+ && (mdp_curr_up_scale_xy !=
+ MDP_BC_SCALE_UP)) {
+ mdp_load_bc_upscale_table();
+ mdp_curr_up_scale_xy = MDP_BC_SCALE_UP;
+ }
+ }
+
+ if (mdp_blur) {
+ load_scale_table(mdp_gaussian_blur_table,
+ ARRAY_SIZE(mdp_gaussian_blur_table));
+ mdp_curr_down_scale_x = MDP_SCALE_BLUR;
+ mdp_curr_down_scale_y = MDP_SCALE_BLUR;
+ }
+
+ /* 0.2 < x <= 1 scaling factor */
+ if ((dst_roi_width_scale <= iBuf->roi.width) &&
+ !mdp_blur) {
+ if (((dst_roi_width_scale * 10) /
+ iBuf->roi.width) > 8) {
+ if ((use_pr)
+ && (mdp_curr_down_scale_x !=
+ MDP_PR_SCALE_POINT8_1)) {
+ mdp_load_pr_downscale_table_x_point8TO1
+ ();
+ mdp_curr_down_scale_x =
+ MDP_PR_SCALE_POINT8_1;
+ } else if ((!use_pr)
+ && (mdp_curr_down_scale_x !=
+ MDP_BC_SCALE_POINT8_1)) {
+ mdp_load_bc_downscale_table_x_point8TO1
+ ();
+ mdp_curr_down_scale_x =
+ MDP_BC_SCALE_POINT8_1;
+ }
+ } else
+ if (((dst_roi_width_scale * 10) /
+ iBuf->roi.width) > 6) {
+ if ((use_pr)
+ && (mdp_curr_down_scale_x !=
+ MDP_PR_SCALE_POINT6_POINT8)) {
+ mdp_load_pr_downscale_table_x_point6TOpoint8
+ ();
+ mdp_curr_down_scale_x =
+ MDP_PR_SCALE_POINT6_POINT8;
+ } else if ((!use_pr)
+ && (mdp_curr_down_scale_x !=
+ MDP_BC_SCALE_POINT6_POINT8))
+ {
+ mdp_load_bc_downscale_table_x_point6TOpoint8
+ ();
+ mdp_curr_down_scale_x =
+ MDP_BC_SCALE_POINT6_POINT8;
+ }
+ } else
+ if (((dst_roi_width_scale * 10) /
+ iBuf->roi.width) > 4) {
+ if ((use_pr)
+ && (mdp_curr_down_scale_x !=
+ MDP_PR_SCALE_POINT4_POINT6)) {
+ mdp_load_pr_downscale_table_x_point4TOpoint6
+ ();
+ mdp_curr_down_scale_x =
+ MDP_PR_SCALE_POINT4_POINT6;
+ } else if ((!use_pr)
+ && (mdp_curr_down_scale_x !=
+ MDP_BC_SCALE_POINT4_POINT6))
+ {
+ mdp_load_bc_downscale_table_x_point4TOpoint6
+ ();
+ mdp_curr_down_scale_x =
+ MDP_BC_SCALE_POINT4_POINT6;
+ }
+ } else {
+ if ((use_pr)
+ && (mdp_curr_down_scale_x !=
+ MDP_PR_SCALE_POINT2_POINT4)) {
+ mdp_load_pr_downscale_table_x_point2TOpoint4
+ ();
+ mdp_curr_down_scale_x =
+ MDP_PR_SCALE_POINT2_POINT4;
+ } else if ((!use_pr)
+ && (mdp_curr_down_scale_x !=
+ MDP_BC_SCALE_POINT2_POINT4))
+ {
+ mdp_load_bc_downscale_table_x_point2TOpoint4
+ ();
+ mdp_curr_down_scale_x =
+ MDP_BC_SCALE_POINT2_POINT4;
+ }
+ }
+ }
+ /* 0.2 < y <= 1 scaling factor */
+ if ((dst_roi_height_scale <= iBuf->roi.height) &&
+ !mdp_blur) {
+ if (((dst_roi_height_scale * 10) /
+ iBuf->roi.height) > 8) {
+ if ((use_pr)
+ && (mdp_curr_down_scale_y !=
+ MDP_PR_SCALE_POINT8_1)) {
+ mdp_load_pr_downscale_table_y_point8TO1
+ ();
+ mdp_curr_down_scale_y =
+ MDP_PR_SCALE_POINT8_1;
+ } else if ((!use_pr)
+ && (mdp_curr_down_scale_y !=
+ MDP_BC_SCALE_POINT8_1)) {
+ mdp_load_bc_downscale_table_y_point8TO1
+ ();
+ mdp_curr_down_scale_y =
+ MDP_BC_SCALE_POINT8_1;
+ }
+ } else
+ if (((dst_roi_height_scale * 10) /
+ iBuf->roi.height) > 6) {
+ if ((use_pr)
+ && (mdp_curr_down_scale_y !=
+ MDP_PR_SCALE_POINT6_POINT8)) {
+ mdp_load_pr_downscale_table_y_point6TOpoint8
+ ();
+ mdp_curr_down_scale_y =
+ MDP_PR_SCALE_POINT6_POINT8;
+ } else if ((!use_pr)
+ && (mdp_curr_down_scale_y !=
+ MDP_BC_SCALE_POINT6_POINT8))
+ {
+ mdp_load_bc_downscale_table_y_point6TOpoint8
+ ();
+ mdp_curr_down_scale_y =
+ MDP_BC_SCALE_POINT6_POINT8;
+ }
+ } else
+ if (((dst_roi_height_scale * 10) /
+ iBuf->roi.height) > 4) {
+ if ((use_pr)
+ && (mdp_curr_down_scale_y !=
+ MDP_PR_SCALE_POINT4_POINT6)) {
+ mdp_load_pr_downscale_table_y_point4TOpoint6
+ ();
+ mdp_curr_down_scale_y =
+ MDP_PR_SCALE_POINT4_POINT6;
+ } else if ((!use_pr)
+ && (mdp_curr_down_scale_y !=
+ MDP_BC_SCALE_POINT4_POINT6))
+ {
+ mdp_load_bc_downscale_table_y_point4TOpoint6
+ ();
+ mdp_curr_down_scale_y =
+ MDP_BC_SCALE_POINT4_POINT6;
+ }
+ } else {
+ if ((use_pr)
+ && (mdp_curr_down_scale_y !=
+ MDP_PR_SCALE_POINT2_POINT4)) {
+ mdp_load_pr_downscale_table_y_point2TOpoint4
+ ();
+ mdp_curr_down_scale_y =
+ MDP_PR_SCALE_POINT2_POINT4;
+ } else if ((!use_pr)
+ && (mdp_curr_down_scale_y !=
+ MDP_BC_SCALE_POINT2_POINT4))
+ {
+ mdp_load_bc_downscale_table_y_point2TOpoint4
+ ();
+ mdp_curr_down_scale_y =
+ MDP_BC_SCALE_POINT2_POINT4;
+ }
+ }
+ }
+ } else {
+ iBuf->mdpImg.mdpOp &= ~(MDPOP_ASCALE);
+ }
+ }
+ /* setting edge condition here after scaling check */
+ if (mdp_get_edge_cond(iBuf, &lines_dup, &lines_dup_bg))
+ printk(KERN_ERR "msm_fb: mdp_get_edge_cond() error!\n");
+
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01b8, lines_dup);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01bc, lines_dup_bg);
+}
+
+void mdp_init_scale_table(void)
+{
+ mdp_curr_up_scale_xy = MDP_INIT_SCALE;
+ mdp_curr_down_scale_x = MDP_INIT_SCALE;
+ mdp_curr_down_scale_y = MDP_INIT_SCALE;
+}
+
+void mdp_adjust_start_addr(uint8 **src0,
+ uint8 **src1,
+ int v_slice,
+ int h_slice,
+ int x,
+ int y,
+ uint32 width,
+ uint32 height, int bpp, MDPIBUF *iBuf, int layer)
+{
+ *src0 += (x + y * width) * bpp;
+
+ /* if it's dest/bg buffer, we need to adjust it for rotation */
+ if (layer != 0)
+ *src0 = mdp_adjust_rot_addr(iBuf, *src0, 0);
+
+ if (*src1) {
+ /*
+ * MDP_Y_CBCR_H2V2/MDP_Y_CRCB_H2V2 cosite for now
+ * we need to shift x direction same as y dir for offsite
+ */
+ *src1 +=
+ ((x / h_slice) * h_slice +
+ ((y == 0) ? 0 : ((y + 1) / v_slice - 1) * width)) * bpp;
+
+ /* if it's dest/bg buffer, we need to adjust it for rotation */
+ if (layer != 0)
+ *src1 = mdp_adjust_rot_addr(iBuf, *src1, 1);
+ }
+}
+
+void mdp_set_blend_attr(MDPIBUF *iBuf,
+ uint32 *alpha,
+ uint32 *tpVal,
+ uint32 perPixelAlpha, uint32 *pppop_reg_ptr)
+{
+ if (perPixelAlpha) {
+ *pppop_reg_ptr |= PPP_OP_ROT_ON |
+ PPP_OP_BLEND_ON | PPP_OP_BLEND_SRCPIXEL_ALPHA;
+ } else {
+ if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+ && (iBuf->mdpImg.alpha == 0xff)) {
+ iBuf->mdpImg.mdpOp &= ~(MDPOP_ALPHAB);
+ }
+
+ if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+ && (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) {
+ *pppop_reg_ptr |=
+ PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
+ PPP_OP_BLEND_CONSTANT_ALPHA |
+ PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
+ PPP_BLEND_CALPHA_TRNASP;
+
+ *alpha = iBuf->mdpImg.alpha;
+ *tpVal = iBuf->mdpImg.tpVal;
+ } else {
+ if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) {
+ *pppop_reg_ptr |= PPP_OP_ROT_ON |
+ PPP_OP_BLEND_ON |
+ PPP_OP_BLEND_SRCPIXEL_TRANSP;
+ *tpVal = iBuf->mdpImg.tpVal;
+ } else if (iBuf->mdpImg.mdpOp & MDPOP_ALPHAB) {
+ *pppop_reg_ptr |= PPP_OP_ROT_ON |
+ PPP_OP_BLEND_ON |
+ PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
+ PPP_OP_BLEND_CONSTANT_ALPHA;
+ *alpha = iBuf->mdpImg.alpha;
+ }
+ }
+ }
+}
diff --git a/drivers/staging/msm/mdp_ppp_v31.c b/drivers/staging/msm/mdp_ppp_v31.c
new file mode 100644
index 0000000..76495db
--- /dev/null
+++ b/drivers/staging/msm/mdp_ppp_v31.c
@@ -0,0 +1,828 @@
+/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include "linux/proc_fs.h"
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <asm/div64.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+
+#define MDP_SCALE_COEFF_NUM 32
+#define MDP_SCALE_0P2_TO_0P4_INDEX 0
+#define MDP_SCALE_0P4_TO_0P6_INDEX 32
+#define MDP_SCALE_0P6_TO_0P8_INDEX 64
+#define MDP_SCALE_0P8_TO_8P0_INDEX 96
+#define MDP_SCALE_COEFF_MASK 0x3ff
+
+#define MDP_SCALE_PR 0
+#define MDP_SCALE_FIR 1
+
+static uint32 mdp_scale_0p8_to_8p0_mode;
+static uint32 mdp_scale_0p6_to_0p8_mode;
+static uint32 mdp_scale_0p4_to_0p6_mode;
+static uint32 mdp_scale_0p2_to_0p4_mode;
+
+/* -------- All scaling range, "pixel repeat" -------- */
+static int16 mdp_scale_pixel_repeat_C0[MDP_SCALE_COEFF_NUM] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static int16 mdp_scale_pixel_repeat_C1[MDP_SCALE_COEFF_NUM] = {
+ 511, 511, 511, 511, 511, 511, 511, 511,
+ 511, 511, 511, 511, 511, 511, 511, 511,
+ 511, 511, 511, 511, 511, 511, 511, 511,
+ 511, 511, 511, 511, 511, 511, 511, 511
+};
+
+static int16 mdp_scale_pixel_repeat_C2[MDP_SCALE_COEFF_NUM] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static int16 mdp_scale_pixel_repeat_C3[MDP_SCALE_COEFF_NUM] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* --------------------------- FIR ------------------------------------- */
+/* -------- Downscale, ranging from 0.8x to 8.0x of original size -------- */
+
+static int16 mdp_scale_0p8_to_8p0_C0[MDP_SCALE_COEFF_NUM] = {
+ 0, -7, -13, -19, -24, -28, -32, -34, -37, -39,
+ -40, -41, -41, -41, -40, -40, -38, -37, -35, -33,
+ -31, -29, -26, -24, -21, -18, -15, -13, -10, -7,
+ -5, -2
+};
+
+static int16 mdp_scale_0p8_to_8p0_C1[MDP_SCALE_COEFF_NUM] = {
+ 511, 507, 501, 494, 485, 475, 463, 450, 436, 422,
+ 405, 388, 370, 352, 333, 314, 293, 274, 253, 233,
+ 213, 193, 172, 152, 133, 113, 95, 77, 60, 43,
+ 28, 13
+};
+
+static int16 mdp_scale_0p8_to_8p0_C2[MDP_SCALE_COEFF_NUM] = {
+ 0, 13, 28, 43, 60, 77, 95, 113, 133, 152,
+ 172, 193, 213, 233, 253, 274, 294, 314, 333, 352,
+ 370, 388, 405, 422, 436, 450, 463, 475, 485, 494,
+ 501, 507,
+};
+
+static int16 mdp_scale_0p8_to_8p0_C3[MDP_SCALE_COEFF_NUM] = {
+ 0, -2, -5, -7, -10, -13, -15, -18, -21, -24,
+ -26, -29, -31, -33, -35, -37, -38, -40, -40, -41,
+ -41, -41, -40, -39, -37, -34, -32, -28, -24, -19,
+ -13, -7
+};
+
+/* -------- Downscale, ranging from 0.6x to 0.8x of original size -------- */
+
+static int16 mdp_scale_0p6_to_0p8_C0[MDP_SCALE_COEFF_NUM] = {
+ 104, 96, 89, 82, 75, 68, 61, 55, 49, 43,
+ 38, 33, 28, 24, 20, 16, 12, 9, 6, 4,
+ 2, 0, -2, -4, -5, -6, -7, -7, -8, -8,
+ -8, -8
+};
+
+static int16 mdp_scale_0p6_to_0p8_C1[MDP_SCALE_COEFF_NUM] = {
+ 303, 303, 302, 300, 298, 296, 293, 289, 286, 281,
+ 276, 270, 265, 258, 252, 245, 238, 230, 223, 214,
+ 206, 197, 189, 180, 172, 163, 154, 145, 137, 128,
+ 120, 112
+};
+
+static int16 mdp_scale_0p6_to_0p8_C2[MDP_SCALE_COEFF_NUM] = {
+ 112, 120, 128, 137, 145, 154, 163, 172, 180, 189,
+ 197, 206, 214, 223, 230, 238, 245, 252, 258, 265,
+ 270, 276, 281, 286, 289, 293, 296, 298, 300, 302,
+ 303, 303
+};
+
+static int16 mdp_scale_0p6_to_0p8_C3[MDP_SCALE_COEFF_NUM] = {
+ -8, -8, -8, -8, -7, -7, -6, -5, -4, -2,
+ 0, 2, 4, 6, 9, 12, 16, 20, 24, 28,
+ 33, 38, 43, 49, 55, 61, 68, 75, 82, 89,
+ 96, 104
+};
+
+/* -------- Downscale, ranging from 0.4x to 0.6x of original size -------- */
+
+static int16 mdp_scale_0p4_to_0p6_C0[MDP_SCALE_COEFF_NUM] = {
+ 136, 132, 128, 123, 119, 115, 111, 107, 103, 98,
+ 95, 91, 87, 84, 80, 76, 73, 69, 66, 62,
+ 59, 57, 54, 50, 47, 44, 41, 39, 36, 33,
+ 32, 29
+};
+
+static int16 mdp_scale_0p4_to_0p6_C1[MDP_SCALE_COEFF_NUM] = {
+ 206, 205, 204, 204, 201, 200, 199, 197, 196, 194,
+ 191, 191, 189, 185, 184, 182, 180, 178, 176, 173,
+ 170, 168, 165, 162, 160, 157, 155, 152, 148, 146,
+ 142, 140
+};
+
+static int16 mdp_scale_0p4_to_0p6_C2[MDP_SCALE_COEFF_NUM] = {
+ 140, 142, 146, 148, 152, 155, 157, 160, 162, 165,
+ 168, 170, 173, 176, 178, 180, 182, 184, 185, 189,
+ 191, 191, 194, 196, 197, 199, 200, 201, 204, 204,
+ 205, 206
+};
+
+static int16 mdp_scale_0p4_to_0p6_C3[MDP_SCALE_COEFF_NUM] = {
+ 29, 32, 33, 36, 39, 41, 44, 47, 50, 54,
+ 57, 59, 62, 66, 69, 73, 76, 80, 84, 87,
+ 91, 95, 98, 103, 107, 111, 115, 119, 123, 128,
+ 132, 136
+};
+
+/* -------- Downscale, ranging from 0.2x to 0.4x of original size -------- */
+
+static int16 mdp_scale_0p2_to_0p4_C0[MDP_SCALE_COEFF_NUM] = {
+ 131, 131, 130, 129, 128, 127, 127, 126, 125, 125,
+ 124, 123, 123, 121, 120, 119, 119, 118, 117, 117,
+ 116, 115, 115, 114, 113, 112, 111, 110, 109, 109,
+ 108, 107
+};
+
+static int16 mdp_scale_0p2_to_0p4_C1[MDP_SCALE_COEFF_NUM] = {
+ 141, 140, 140, 140, 140, 139, 138, 138, 138, 137,
+ 137, 137, 136, 137, 137, 137, 136, 136, 136, 135,
+ 135, 135, 134, 134, 134, 134, 134, 133, 133, 132,
+ 132, 132
+};
+
+static int16 mdp_scale_0p2_to_0p4_C2[MDP_SCALE_COEFF_NUM] = {
+ 132, 132, 132, 133, 133, 134, 134, 134, 134, 134,
+ 135, 135, 135, 136, 136, 136, 137, 137, 137, 136,
+ 137, 137, 137, 138, 138, 138, 139, 140, 140, 140,
+ 140, 141
+};
+
+static int16 mdp_scale_0p2_to_0p4_C3[MDP_SCALE_COEFF_NUM] = {
+ 107, 108, 109, 109, 110, 111, 112, 113, 114, 115,
+ 115, 116, 117, 117, 118, 119, 119, 120, 121, 123,
+ 123, 124, 125, 125, 126, 127, 127, 128, 129, 130,
+ 131, 131
+};
+
+static void mdp_update_scale_table(int index, int16 *c0, int16 *c1,
+ int16 *c2, int16 *c3)
+{
+ int i, val;
+
+ for (i = 0; i < MDP_SCALE_COEFF_NUM; i++) {
+ val =
+ ((MDP_SCALE_COEFF_MASK & c1[i]) << 16) |
+ (MDP_SCALE_COEFF_MASK & c0[i]);
+ MDP_OUTP(MDP_PPP_SCALE_COEFF_LSBn(index), val);
+ val =
+ ((MDP_SCALE_COEFF_MASK & c3[i]) << 16) |
+ (MDP_SCALE_COEFF_MASK & c2[i]);
+ MDP_OUTP(MDP_PPP_SCALE_COEFF_MSBn(index), val);
+ index++;
+ }
+}
+
+void mdp_init_scale_table(void)
+{
+ mdp_scale_0p2_to_0p4_mode = MDP_SCALE_FIR;
+ mdp_update_scale_table(MDP_SCALE_0P2_TO_0P4_INDEX,
+ mdp_scale_0p2_to_0p4_C0,
+ mdp_scale_0p2_to_0p4_C1,
+ mdp_scale_0p2_to_0p4_C2,
+ mdp_scale_0p2_to_0p4_C3);
+
+ mdp_scale_0p4_to_0p6_mode = MDP_SCALE_FIR;
+ mdp_update_scale_table(MDP_SCALE_0P4_TO_0P6_INDEX,
+ mdp_scale_0p4_to_0p6_C0,
+ mdp_scale_0p4_to_0p6_C1,
+ mdp_scale_0p4_to_0p6_C2,
+ mdp_scale_0p4_to_0p6_C3);
+
+ mdp_scale_0p6_to_0p8_mode = MDP_SCALE_FIR;
+ mdp_update_scale_table(MDP_SCALE_0P6_TO_0P8_INDEX,
+ mdp_scale_0p6_to_0p8_C0,
+ mdp_scale_0p6_to_0p8_C1,
+ mdp_scale_0p6_to_0p8_C2,
+ mdp_scale_0p6_to_0p8_C3);
+
+ mdp_scale_0p8_to_8p0_mode = MDP_SCALE_FIR;
+ mdp_update_scale_table(MDP_SCALE_0P8_TO_8P0_INDEX,
+ mdp_scale_0p8_to_8p0_C0,
+ mdp_scale_0p8_to_8p0_C1,
+ mdp_scale_0p8_to_8p0_C2,
+ mdp_scale_0p8_to_8p0_C3);
+}
+
+static long long mdp_do_div(long long num, long long den)
+{
+ do_div(num, den);
+ return num;
+}
+
+#define SCALER_PHASE_BITS 29
+#define HAL_MDP_PHASE_STEP_2P50 0x50000000
+#define HAL_MDP_PHASE_STEP_1P66 0x35555555
+#define HAL_MDP_PHASE_STEP_1P25 0x28000000
+
+struct phase_val {
+ int phase_init_x;
+ int phase_init_y;
+ int phase_step_x;
+ int phase_step_y;
+};
+
+static void mdp_calc_scaleInitPhase_3p1(uint32 in_w,
+ uint32 in_h,
+ uint32 out_w,
+ uint32 out_h,
+ boolean is_rotate,
+ boolean is_pp_x,
+ boolean is_pp_y, struct phase_val *pval)
+{
+ uint64 dst_ROI_width;
+ uint64 dst_ROI_height;
+ uint64 src_ROI_width;
+ uint64 src_ROI_height;
+
+ /*
+ * phase_step_x, phase_step_y, phase_init_x and phase_init_y
+ * are represented in fixed-point, unsigned 3.29 format
+ */
+ uint32 phase_step_x = 0;
+ uint32 phase_step_y = 0;
+ uint32 phase_init_x = 0;
+ uint32 phase_init_y = 0;
+ uint32 yscale_filter_sel, xscale_filter_sel;
+ uint32 scale_unit_sel_x, scale_unit_sel_y;
+
+ uint64 numerator, denominator;
+ uint64 temp_dim;
+
+ src_ROI_width = in_w;
+ src_ROI_height = in_h;
+ dst_ROI_width = out_w;
+ dst_ROI_height = out_h;
+
+ /* if there is a 90 degree rotation */
+ if (is_rotate) {
+ /* decide whether to use FIR or M/N for scaling */
+
+ /* if down-scaling by a factor smaller than 1/4 */
+ if (src_ROI_width > (4 * dst_ROI_height))
+ scale_unit_sel_x = 1; /* use M/N scalar */
+ else
+ scale_unit_sel_x = 0; /* use FIR scalar */
+
+ /* if down-scaling by a factor smaller than 1/4 */
+ if (src_ROI_height > (4 * dst_ROI_width))
+ scale_unit_sel_y = 1; /* use M/N scalar */
+ else
+ scale_unit_sel_y = 0; /* use FIR scalar */
+ } else {
+ /* decide whether to use FIR or M/N for scaling */
+
+ if (src_ROI_width > (4 * dst_ROI_width))
+ scale_unit_sel_x = 1; /* use M/N scalar */
+ else
+ scale_unit_sel_x = 0; /* use FIR scalar */
+
+ if (src_ROI_height > (4 * dst_ROI_height))
+ scale_unit_sel_y = 1; /* use M/N scalar */
+ else
+ scale_unit_sel_y = 0; /* use FIR scalar */
+
+ }
+
+ /* if there is a 90 degree rotation */
+ if (is_rotate) {
+ /* swap the width and height of dst ROI */
+ temp_dim = dst_ROI_width;
+ dst_ROI_width = dst_ROI_height;
+ dst_ROI_height = temp_dim;
+ }
+
+ /* calculate phase step for the x direction */
+
+ /* if destination is only 1 pixel wide, the value of phase_step_x
+ is unimportant. Assigning phase_step_x to src ROI width
+ as an arbitrary value. */
+ if (dst_ROI_width == 1)
+ phase_step_x = (uint32) ((src_ROI_width) << SCALER_PHASE_BITS);
+
+ /* if using FIR scalar */
+ else if (scale_unit_sel_x == 0) {
+
+ /* Calculate the quotient ( src_ROI_width - 1 ) / ( dst_ROI_width - 1)
+ with u3.29 precision. Quotient is rounded up to the larger
+ 29th decimal point. */
+ numerator = (src_ROI_width - 1) << SCALER_PHASE_BITS;
+ denominator = (dst_ROI_width - 1); /* never equals to 0 because of the "( dst_ROI_width == 1 ) case" */
+ phase_step_x = (uint32) mdp_do_div((numerator + denominator - 1), denominator); /* divide and round up to the larger 29th decimal point. */
+
+ }
+
+ /* if M/N scalar */
+ else if (scale_unit_sel_x == 1) {
+ /* Calculate the quotient ( src_ROI_width ) / ( dst_ROI_width)
+ with u3.29 precision. Quotient is rounded down to the
+ smaller 29th decimal point. */
+ numerator = (src_ROI_width) << SCALER_PHASE_BITS;
+ denominator = (dst_ROI_width);
+ phase_step_x = (uint32) mdp_do_div(numerator, denominator);
+ }
+ /* calculate phase step for the y direction */
+
+ /* if destination is only 1 pixel wide, the value of
+ phase_step_x is unimportant. Assigning phase_step_x
+ to src ROI width as an arbitrary value. */
+ if (dst_ROI_height == 1)
+ phase_step_y = (uint32) ((src_ROI_height) << SCALER_PHASE_BITS);
+
+ /* if FIR scalar */
+ else if (scale_unit_sel_y == 0) {
+ /* Calculate the quotient ( src_ROI_height - 1 ) / ( dst_ROI_height - 1)
+ with u3.29 precision. Quotient is rounded up to the larger
+ 29th decimal point. */
+ numerator = (src_ROI_height - 1) << SCALER_PHASE_BITS;
+ denominator = (dst_ROI_height - 1); /* never equals to 0 because of the "( dst_ROI_height == 1 )" case */
+ phase_step_y = (uint32) mdp_do_div((numerator + denominator - 1), denominator); /* Quotient is rounded up to the larger 29th decimal point. */
+
+ }
+
+ /* if M/N scalar */
+ else if (scale_unit_sel_y == 1) {
+ /* Calculate the quotient ( src_ROI_height ) / ( dst_ROI_height)
+ with u3.29 precision. Quotient is rounded down to the smaller
+ 29th decimal point. */
+ numerator = (src_ROI_height) << SCALER_PHASE_BITS;
+ denominator = (dst_ROI_height);
+ phase_step_y = (uint32) mdp_do_div(numerator, denominator);
+ }
+
+ /* decide which set of FIR coefficients to use */
+ if (phase_step_x > HAL_MDP_PHASE_STEP_2P50)
+ xscale_filter_sel = 0;
+ else if (phase_step_x > HAL_MDP_PHASE_STEP_1P66)
+ xscale_filter_sel = 1;
+ else if (phase_step_x > HAL_MDP_PHASE_STEP_1P25)
+ xscale_filter_sel = 2;
+ else
+ xscale_filter_sel = 3;
+
+ if (phase_step_y > HAL_MDP_PHASE_STEP_2P50)
+ yscale_filter_sel = 0;
+ else if (phase_step_y > HAL_MDP_PHASE_STEP_1P66)
+ yscale_filter_sel = 1;
+ else if (phase_step_y > HAL_MDP_PHASE_STEP_1P25)
+ yscale_filter_sel = 2;
+ else
+ yscale_filter_sel = 3;
+
+ /* calculate phase init for the x direction */
+
+ /* if using FIR scalar */
+ if (scale_unit_sel_x == 0) {
+ if (dst_ROI_width == 1)
+ phase_init_x =
+ (uint32) ((src_ROI_width - 1) << SCALER_PHASE_BITS);
+ else
+ phase_init_x = 0;
+
+ }
+ /* M over N scalar */
+ else if (scale_unit_sel_x == 1)
+ phase_init_x = 0;
+
+ /* calculate phase init for the y direction
+ if using FIR scalar */
+ if (scale_unit_sel_y == 0) {
+ if (dst_ROI_height == 1)
+ phase_init_y =
+ (uint32) ((src_ROI_height -
+ 1) << SCALER_PHASE_BITS);
+ else
+ phase_init_y = 0;
+
+ }
+ /* M over N scalar */
+ else if (scale_unit_sel_y == 1)
+ phase_init_y = 0;
+
+ /* write registers */
+ pval->phase_step_x = (uint32) phase_step_x;
+ pval->phase_step_y = (uint32) phase_step_y;
+ pval->phase_init_x = (uint32) phase_init_x;
+ pval->phase_init_y = (uint32) phase_init_y;
+
+ return;
+}
+
+void mdp_set_scale(MDPIBUF *iBuf,
+ uint32 dst_roi_width,
+ uint32 dst_roi_height,
+ boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr)
+{
+ uint32 dst_roi_width_scale;
+ uint32 dst_roi_height_scale;
+ struct phase_val pval;
+ boolean use_pr;
+ uint32 ppp_scale_config = 0;
+
+ if (!inputRGB)
+ ppp_scale_config |= BIT(6);
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_ASCALE) {
+ if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
+ dst_roi_width_scale = dst_roi_height;
+ dst_roi_height_scale = dst_roi_width;
+ } else {
+ dst_roi_width_scale = dst_roi_width;
+ dst_roi_height_scale = dst_roi_height;
+ }
+
+ if ((dst_roi_width_scale != iBuf->roi.width) ||
+ (dst_roi_height_scale != iBuf->roi.height) ||
+ (iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) {
+ *pppop_reg_ptr |=
+ (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
+
+ mdp_calc_scaleInitPhase_3p1(iBuf->roi.width,
+ iBuf->roi.height,
+ dst_roi_width,
+ dst_roi_height,
+ iBuf->mdpImg.
+ mdpOp & MDPOP_ROT90, 1, 1,
+ &pval);
+
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x013c,
+ pval.phase_init_x);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0140,
+ pval.phase_init_y);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0144,
+ pval.phase_step_x);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0148,
+ pval.phase_step_y);
+
+ use_pr = (inputRGB) && (outputRGB);
+
+ /* x-direction */
+ if ((dst_roi_width_scale == iBuf->roi.width) &&
+ !(iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) {
+ *pppop_reg_ptr &= ~PPP_OP_SCALE_X_ON;
+ } else
+ if (((dst_roi_width_scale * 10) / iBuf->roi.width) >
+ 8) {
+ if ((use_pr)
+ && (mdp_scale_0p8_to_8p0_mode !=
+ MDP_SCALE_PR)) {
+ mdp_scale_0p8_to_8p0_mode =
+ MDP_SCALE_PR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P8_TO_8P0_INDEX,
+ mdp_scale_pixel_repeat_C0,
+ mdp_scale_pixel_repeat_C1,
+ mdp_scale_pixel_repeat_C2,
+ mdp_scale_pixel_repeat_C3);
+ } else if ((!use_pr)
+ && (mdp_scale_0p8_to_8p0_mode !=
+ MDP_SCALE_FIR)) {
+ mdp_scale_0p8_to_8p0_mode =
+ MDP_SCALE_FIR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P8_TO_8P0_INDEX,
+ mdp_scale_0p8_to_8p0_C0,
+ mdp_scale_0p8_to_8p0_C1,
+ mdp_scale_0p8_to_8p0_C2,
+ mdp_scale_0p8_to_8p0_C3);
+ }
+ ppp_scale_config |= (SCALE_U1_SET << 2);
+ } else
+ if (((dst_roi_width_scale * 10) / iBuf->roi.width) >
+ 6) {
+ if ((use_pr)
+ && (mdp_scale_0p6_to_0p8_mode !=
+ MDP_SCALE_PR)) {
+ mdp_scale_0p6_to_0p8_mode =
+ MDP_SCALE_PR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P6_TO_0P8_INDEX,
+ mdp_scale_pixel_repeat_C0,
+ mdp_scale_pixel_repeat_C1,
+ mdp_scale_pixel_repeat_C2,
+ mdp_scale_pixel_repeat_C3);
+ } else if ((!use_pr)
+ && (mdp_scale_0p6_to_0p8_mode !=
+ MDP_SCALE_FIR)) {
+ mdp_scale_0p6_to_0p8_mode =
+ MDP_SCALE_FIR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P6_TO_0P8_INDEX,
+ mdp_scale_0p6_to_0p8_C0,
+ mdp_scale_0p6_to_0p8_C1,
+ mdp_scale_0p6_to_0p8_C2,
+ mdp_scale_0p6_to_0p8_C3);
+ }
+ ppp_scale_config |= (SCALE_D2_SET << 2);
+ } else
+ if (((dst_roi_width_scale * 10) / iBuf->roi.width) >
+ 4) {
+ if ((use_pr)
+ && (mdp_scale_0p4_to_0p6_mode !=
+ MDP_SCALE_PR)) {
+ mdp_scale_0p4_to_0p6_mode =
+ MDP_SCALE_PR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P4_TO_0P6_INDEX,
+ mdp_scale_pixel_repeat_C0,
+ mdp_scale_pixel_repeat_C1,
+ mdp_scale_pixel_repeat_C2,
+ mdp_scale_pixel_repeat_C3);
+ } else if ((!use_pr)
+ && (mdp_scale_0p4_to_0p6_mode !=
+ MDP_SCALE_FIR)) {
+ mdp_scale_0p4_to_0p6_mode =
+ MDP_SCALE_FIR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P4_TO_0P6_INDEX,
+ mdp_scale_0p4_to_0p6_C0,
+ mdp_scale_0p4_to_0p6_C1,
+ mdp_scale_0p4_to_0p6_C2,
+ mdp_scale_0p4_to_0p6_C3);
+ }
+ ppp_scale_config |= (SCALE_D1_SET << 2);
+ } else
+ if (((dst_roi_width_scale * 4) / iBuf->roi.width) >=
+ 1) {
+ if ((use_pr)
+ && (mdp_scale_0p2_to_0p4_mode !=
+ MDP_SCALE_PR)) {
+ mdp_scale_0p2_to_0p4_mode =
+ MDP_SCALE_PR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P2_TO_0P4_INDEX,
+ mdp_scale_pixel_repeat_C0,
+ mdp_scale_pixel_repeat_C1,
+ mdp_scale_pixel_repeat_C2,
+ mdp_scale_pixel_repeat_C3);
+ } else if ((!use_pr)
+ && (mdp_scale_0p2_to_0p4_mode !=
+ MDP_SCALE_FIR)) {
+ mdp_scale_0p2_to_0p4_mode =
+ MDP_SCALE_FIR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P2_TO_0P4_INDEX,
+ mdp_scale_0p2_to_0p4_C0,
+ mdp_scale_0p2_to_0p4_C1,
+ mdp_scale_0p2_to_0p4_C2,
+ mdp_scale_0p2_to_0p4_C3);
+ }
+ ppp_scale_config |= (SCALE_D0_SET << 2);
+ } else
+ ppp_scale_config |= BIT(0);
+
+ /* y-direction */
+ if ((dst_roi_height_scale == iBuf->roi.height) &&
+ !(iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) {
+ *pppop_reg_ptr &= ~PPP_OP_SCALE_Y_ON;
+ } else if (((dst_roi_height_scale * 10) /
+ iBuf->roi.height) > 8) {
+ if ((use_pr)
+ && (mdp_scale_0p8_to_8p0_mode !=
+ MDP_SCALE_PR)) {
+ mdp_scale_0p8_to_8p0_mode =
+ MDP_SCALE_PR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P8_TO_8P0_INDEX,
+ mdp_scale_pixel_repeat_C0,
+ mdp_scale_pixel_repeat_C1,
+ mdp_scale_pixel_repeat_C2,
+ mdp_scale_pixel_repeat_C3);
+ } else if ((!use_pr)
+ && (mdp_scale_0p8_to_8p0_mode !=
+ MDP_SCALE_FIR)) {
+ mdp_scale_0p8_to_8p0_mode =
+ MDP_SCALE_FIR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P8_TO_8P0_INDEX,
+ mdp_scale_0p8_to_8p0_C0,
+ mdp_scale_0p8_to_8p0_C1,
+ mdp_scale_0p8_to_8p0_C2,
+ mdp_scale_0p8_to_8p0_C3);
+ }
+ ppp_scale_config |= (SCALE_U1_SET << 4);
+ } else
+ if (((dst_roi_height_scale * 10) /
+ iBuf->roi.height) > 6) {
+ if ((use_pr)
+ && (mdp_scale_0p6_to_0p8_mode !=
+ MDP_SCALE_PR)) {
+ mdp_scale_0p6_to_0p8_mode =
+ MDP_SCALE_PR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P6_TO_0P8_INDEX,
+ mdp_scale_pixel_repeat_C0,
+ mdp_scale_pixel_repeat_C1,
+ mdp_scale_pixel_repeat_C2,
+ mdp_scale_pixel_repeat_C3);
+ } else if ((!use_pr)
+ && (mdp_scale_0p6_to_0p8_mode !=
+ MDP_SCALE_FIR)) {
+ mdp_scale_0p6_to_0p8_mode =
+ MDP_SCALE_FIR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P6_TO_0P8_INDEX,
+ mdp_scale_0p6_to_0p8_C0,
+ mdp_scale_0p6_to_0p8_C1,
+ mdp_scale_0p6_to_0p8_C2,
+ mdp_scale_0p6_to_0p8_C3);
+ }
+ ppp_scale_config |= (SCALE_D2_SET << 4);
+ } else
+ if (((dst_roi_height_scale * 10) /
+ iBuf->roi.height) > 4) {
+ if ((use_pr)
+ && (mdp_scale_0p4_to_0p6_mode !=
+ MDP_SCALE_PR)) {
+ mdp_scale_0p4_to_0p6_mode =
+ MDP_SCALE_PR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P4_TO_0P6_INDEX,
+ mdp_scale_pixel_repeat_C0,
+ mdp_scale_pixel_repeat_C1,
+ mdp_scale_pixel_repeat_C2,
+ mdp_scale_pixel_repeat_C3);
+ } else if ((!use_pr)
+ && (mdp_scale_0p4_to_0p6_mode !=
+ MDP_SCALE_FIR)) {
+ mdp_scale_0p4_to_0p6_mode =
+ MDP_SCALE_FIR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P4_TO_0P6_INDEX,
+ mdp_scale_0p4_to_0p6_C0,
+ mdp_scale_0p4_to_0p6_C1,
+ mdp_scale_0p4_to_0p6_C2,
+ mdp_scale_0p4_to_0p6_C3);
+ }
+ ppp_scale_config |= (SCALE_D1_SET << 4);
+ } else
+ if (((dst_roi_height_scale * 4) /
+ iBuf->roi.height) >= 1) {
+ if ((use_pr)
+ && (mdp_scale_0p2_to_0p4_mode !=
+ MDP_SCALE_PR)) {
+ mdp_scale_0p2_to_0p4_mode =
+ MDP_SCALE_PR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P2_TO_0P4_INDEX,
+ mdp_scale_pixel_repeat_C0,
+ mdp_scale_pixel_repeat_C1,
+ mdp_scale_pixel_repeat_C2,
+ mdp_scale_pixel_repeat_C3);
+ } else if ((!use_pr)
+ && (mdp_scale_0p2_to_0p4_mode !=
+ MDP_SCALE_FIR)) {
+ mdp_scale_0p2_to_0p4_mode =
+ MDP_SCALE_FIR;
+ mdp_update_scale_table
+ (MDP_SCALE_0P2_TO_0P4_INDEX,
+ mdp_scale_0p2_to_0p4_C0,
+ mdp_scale_0p2_to_0p4_C1,
+ mdp_scale_0p2_to_0p4_C2,
+ mdp_scale_0p2_to_0p4_C3);
+ }
+ ppp_scale_config |= (SCALE_D0_SET << 4);
+ } else
+ ppp_scale_config |= BIT(1);
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_SHARPENING) {
+ ppp_scale_config |= BIT(7);
+ MDP_OUTP(MDP_BASE + 0x50020,
+ iBuf->mdpImg.sp_value);
+ }
+
+ MDP_OUTP(MDP_BASE + 0x10230, ppp_scale_config);
+ } else {
+ iBuf->mdpImg.mdpOp &= ~(MDPOP_ASCALE);
+ }
+ }
+}
+
+void mdp_adjust_start_addr(uint8 **src0,
+ uint8 **src1,
+ int v_slice,
+ int h_slice,
+ int x,
+ int y,
+ uint32 width,
+ uint32 height, int bpp, MDPIBUF *iBuf, int layer)
+{
+ switch (layer) {
+ case 0:
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0200, (y << 16) | (x));
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0208,
+ (height << 16) | (width));
+ break;
+
+ case 1:
+ /* MDP 3.1 HW bug workaround */
+ if (iBuf->ibuf_type == MDP_YCRYCB_H2V1) {
+ *src0 += (x + y * width) * bpp;
+ x = y = 0;
+ width = iBuf->roi.dst_width;
+ height = iBuf->roi.dst_height;
+ }
+
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0204, (y << 16) | (x));
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x020c,
+ (height << 16) | (width));
+ break;
+
+ case 2:
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x019c, (y << 16) | (x));
+ break;
+ }
+}
+
+void mdp_set_blend_attr(MDPIBUF *iBuf,
+ uint32 *alpha,
+ uint32 *tpVal,
+ uint32 perPixelAlpha, uint32 *pppop_reg_ptr)
+{
+ int bg_alpha;
+
+ *alpha = iBuf->mdpImg.alpha;
+ *tpVal = iBuf->mdpImg.tpVal;
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_FG_PM_ALPHA) {
+ *pppop_reg_ptr |= PPP_OP_ROT_ON |
+ PPP_OP_BLEND_ON | PPP_OP_BLEND_CONSTANT_ALPHA;
+
+ bg_alpha = PPP_BLEND_BG_USE_ALPHA_SEL |
+ PPP_BLEND_BG_ALPHA_REVERSE;
+
+ if (perPixelAlpha)
+ bg_alpha |= PPP_BLEND_BG_SRCPIXEL_ALPHA;
+ else
+ bg_alpha |= PPP_BLEND_BG_CONSTANT_ALPHA;
+
+ outpdw(MDP_BASE + 0x70010, bg_alpha);
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)
+ *pppop_reg_ptr |= PPP_BLEND_CALPHA_TRNASP;
+ } else if (perPixelAlpha) {
+ *pppop_reg_ptr |= PPP_OP_ROT_ON |
+ PPP_OP_BLEND_ON | PPP_OP_BLEND_SRCPIXEL_ALPHA;
+ } else {
+ if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+ && (iBuf->mdpImg.alpha == 0xff)) {
+ iBuf->mdpImg.mdpOp &= ~(MDPOP_ALPHAB);
+ }
+
+ if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+ || (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) {
+ *pppop_reg_ptr |=
+ PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
+ PPP_OP_BLEND_CONSTANT_ALPHA |
+ PPP_OP_BLEND_ALPHA_BLEND_NORMAL;
+ }
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)
+ *pppop_reg_ptr |= PPP_BLEND_CALPHA_TRNASP;
+ }
+}
diff --git a/drivers/staging/msm/mdp_vsync.c b/drivers/staging/msm/mdp_vsync.c
new file mode 100644
index 0000000..bbd4560
--- /dev/null
+++ b/drivers/staging/msm/mdp_vsync.c
@@ -0,0 +1,389 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
+#include <linux/vmalloc.h>
+#include <linux/clk.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <mach/gpio.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mddihost.h"
+
+#ifdef CONFIG_FB_MSM_MDP40
+#define MDP_SYNC_CFG_0 0x100
+#define MDP_SYNC_STATUS_0 0x10c
+#define MDP_PRIM_VSYNC_OUT_CTRL 0x118
+#define MDP_PRIM_VSYNC_INIT_VAL 0x128
+#else
+#define MDP_SYNC_CFG_0 0x300
+#define MDP_SYNC_STATUS_0 0x30c
+#define MDP_PRIM_VSYNC_OUT_CTRL 0x318
+#define MDP_PRIM_VSYNC_INIT_VAL 0x328
+#endif
+
+extern mddi_lcd_type mddi_lcd_idx;
+extern spinlock_t mdp_spin_lock;
+extern struct workqueue_struct *mdp_vsync_wq;
+extern int lcdc_mode;
+extern int vsync_mode;
+
+#ifdef MDP_HW_VSYNC
+int vsync_above_th = 4;
+int vsync_start_th = 1;
+int vsync_load_cnt;
+
+struct clk *mdp_vsync_clk;
+
+void mdp_hw_vsync_clk_enable(struct msm_fb_data_type *mfd)
+{
+ if (mfd->use_mdp_vsync)
+ clk_enable(mdp_vsync_clk);
+}
+
+void mdp_hw_vsync_clk_disable(struct msm_fb_data_type *mfd)
+{
+ if (mfd->use_mdp_vsync)
+ clk_disable(mdp_vsync_clk);
+}
+#endif
+
+static void mdp_set_vsync(unsigned long data)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data;
+ struct msm_fb_panel_data *pdata = NULL;
+
+ pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+
+ if ((pdata) && (pdata->set_vsync_notifier == NULL))
+ return;
+
+ init_timer(&mfd->vsync_resync_timer);
+ mfd->vsync_resync_timer.function = mdp_set_vsync;
+ mfd->vsync_resync_timer.data = data;
+ mfd->vsync_resync_timer.expires =
+ jiffies + mfd->panel_info.lcd.vsync_notifier_period;
+ add_timer(&mfd->vsync_resync_timer);
+
+ if ((mfd->panel_info.lcd.vsync_enable) && (mfd->panel_power_on)
+ && (!mfd->vsync_handler_pending)) {
+ mfd->vsync_handler_pending = TRUE;
+ if (!queue_work(mdp_vsync_wq, &mfd->vsync_resync_worker)) {
+ MSM_FB_INFO
+ ("mdp_set_vsync: can't queue_work! -> needs to increase vsync_resync_timer_duration\n");
+ }
+ } else {
+ MSM_FB_DEBUG
+ ("mdp_set_vsync failed! EN:%d PWR:%d PENDING:%d\n",
+ mfd->panel_info.lcd.vsync_enable, mfd->panel_power_on,
+ mfd->vsync_handler_pending);
+ }
+}
+
+static void mdp_vsync_handler(void *data)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data;
+
+ if (mfd->use_mdp_vsync) {
+#ifdef MDP_HW_VSYNC
+ if (mfd->panel_power_on)
+ MDP_OUTP(MDP_BASE + MDP_SYNC_STATUS_0, vsync_load_cnt);
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+#endif
+ } else {
+ mfd->last_vsync_timetick = ktime_get_real();
+ }
+
+ mfd->vsync_handler_pending = FALSE;
+}
+
+irqreturn_t mdp_hw_vsync_handler_proxy(int irq, void *data)
+{
+ /*
+ * ToDo: tried enabling/disabling GPIO MDP HW VSYNC interrupt
+ * but getting inaccurate timing in mdp_vsync_handler()
+ * disable_irq(MDP_HW_VSYNC_IRQ);
+ */
+ mdp_vsync_handler(data);
+
+ return IRQ_HANDLED;
+}
+
+#ifdef MDP_HW_VSYNC
+static void mdp_set_sync_cfg_0(struct msm_fb_data_type *mfd, int vsync_cnt)
+{
+ unsigned long cfg;
+
+ cfg = mfd->total_lcd_lines - 1;
+ cfg <<= MDP_SYNCFG_HGT_LOC;
+ if (mfd->panel_info.lcd.hw_vsync_mode)
+ cfg |= MDP_SYNCFG_VSYNC_EXT_EN;
+ cfg |= (MDP_SYNCFG_VSYNC_INT_EN | vsync_cnt);
+
+ MDP_OUTP(MDP_BASE + MDP_SYNC_CFG_0, cfg);
+}
+#endif
+
+void mdp_config_vsync(struct msm_fb_data_type *mfd)
+{
+
+ /* vsync on primary lcd only for now */
+ if ((mfd->dest != DISPLAY_LCD) || (mfd->panel_info.pdest != DISPLAY_1)
+ || (!vsync_mode)) {
+ goto err_handle;
+ }
+
+ if (mfd->panel_info.lcd.vsync_enable) {
+ mfd->total_porch_lines = mfd->panel_info.lcd.v_back_porch +
+ mfd->panel_info.lcd.v_front_porch +
+ mfd->panel_info.lcd.v_pulse_width;
+ mfd->total_lcd_lines =
+ mfd->panel_info.yres + mfd->total_porch_lines;
+ mfd->lcd_ref_usec_time =
+ 100000000 / mfd->panel_info.lcd.refx100;
+ mfd->vsync_handler_pending = FALSE;
+ mfd->last_vsync_timetick.tv.sec = 0;
+ mfd->last_vsync_timetick.tv.nsec = 0;
+
+#ifdef MDP_HW_VSYNC
+ if (mdp_vsync_clk == NULL)
+ mdp_vsync_clk = clk_get(NULL, "mdp_vsync_clk");
+
+ if (IS_ERR(mdp_vsync_clk)) {
+ printk(KERN_ERR "error: can't get mdp_vsync_clk!\n");
+ mfd->use_mdp_vsync = 0;
+ } else
+ mfd->use_mdp_vsync = 1;
+
+ if (mfd->use_mdp_vsync) {
+ uint32 vsync_cnt_cfg, vsync_cnt_cfg_dem;
+ uint32 mdp_vsync_clk_speed_hz;
+
+ mdp_vsync_clk_speed_hz = clk_get_rate(mdp_vsync_clk);
+
+ if (mdp_vsync_clk_speed_hz == 0) {
+ mfd->use_mdp_vsync = 0;
+ } else {
+ /*
+ * Do this calculation in 2 steps for
+ * rounding uint32 properly.
+ */
+ vsync_cnt_cfg_dem =
+ (mfd->panel_info.lcd.refx100 *
+ mfd->total_lcd_lines) / 100;
+ vsync_cnt_cfg =
+ (mdp_vsync_clk_speed_hz) /
+ vsync_cnt_cfg_dem;
+
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON,
+ FALSE);
+ mdp_hw_vsync_clk_enable(mfd);
+
+ mdp_set_sync_cfg_0(mfd, vsync_cnt_cfg);
+
+ /*
+ * load the last line + 1 to be in the
+ * safety zone
+ */
+ vsync_load_cnt = mfd->panel_info.yres;
+
+ /* line counter init value at the next pulse */
+ MDP_OUTP(MDP_BASE + MDP_PRIM_VSYNC_INIT_VAL,
+ vsync_load_cnt);
+
+ /*
+ * external vsync source pulse width and
+ * polarity flip
+ */
+ MDP_OUTP(MDP_BASE + MDP_PRIM_VSYNC_OUT_CTRL,
+ BIT(30) | BIT(0));
+
+
+ /* threshold */
+ MDP_OUTP(MDP_BASE + 0x200,
+ (vsync_above_th << 16) |
+ (vsync_start_th));
+
+ mdp_hw_vsync_clk_disable(mfd);
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK,
+ MDP_BLOCK_POWER_OFF, FALSE);
+ }
+ }
+#else
+ mfd->use_mdp_vsync = 0;
+ hrtimer_init(&mfd->dma_hrtimer, CLOCK_MONOTONIC,
+ HRTIMER_MODE_REL);
+ mfd->dma_hrtimer.function = mdp_dma2_vsync_hrtimer_handler;
+ mfd->vsync_width_boundary = vmalloc(mfd->panel_info.xres * 4);
+#endif
+
+ mfd->channel_irq = 0;
+ if (mfd->panel_info.lcd.hw_vsync_mode) {
+ u32 vsync_gpio = mfd->vsync_gpio;
+ u32 ret;
+
+ if (vsync_gpio == -1) {
+ MSM_FB_INFO("vsync_gpio not defined!\n");
+ goto err_handle;
+ }
+
+ ret = gpio_tlmm_config(GPIO_CFG
+ (vsync_gpio,
+ (mfd->use_mdp_vsync) ? 1 : 0,
+ GPIO_INPUT,
+ GPIO_PULL_DOWN,
+ GPIO_2MA),
+ GPIO_ENABLE);
+ if (ret)
+ goto err_handle;
+
+ if (!mfd->use_mdp_vsync) {
+ mfd->channel_irq = MSM_GPIO_TO_INT(vsync_gpio);
+ if (request_irq
+ (mfd->channel_irq,
+ &mdp_hw_vsync_handler_proxy,
+ IRQF_TRIGGER_FALLING, "VSYNC_GPIO",
+ (void *)mfd)) {
+ MSM_FB_INFO
+ ("irq=%d failed! vsync_gpio=%d\n",
+ mfd->channel_irq,
+ vsync_gpio);
+ goto err_handle;
+ }
+ }
+ }
+
+ mdp_set_vsync((unsigned long)mfd);
+ }
+
+ return;
+
+err_handle:
+ if (mfd->vsync_width_boundary)
+ vfree(mfd->vsync_width_boundary);
+ mfd->panel_info.lcd.vsync_enable = FALSE;
+ printk(KERN_ERR "%s: failed!\n", __func__);
+}
+
+void mdp_vsync_resync_workqueue_handler(struct work_struct *work)
+{
+ struct msm_fb_data_type *mfd = NULL;
+ int vsync_fnc_enabled = FALSE;
+ struct msm_fb_panel_data *pdata = NULL;
+
+ mfd = container_of(work, struct msm_fb_data_type, vsync_resync_worker);
+
+ if (mfd) {
+ if (mfd->panel_power_on) {
+ pdata =
+ (struct msm_fb_panel_data *)mfd->pdev->dev.
+ platform_data;
+
+ /*
+ * we need to turn on MDP power if it uses MDP vsync
+ * HW block in SW mode
+ */
+ if ((!mfd->panel_info.lcd.hw_vsync_mode) &&
+ (mfd->use_mdp_vsync) &&
+ (pdata) && (pdata->set_vsync_notifier != NULL)) {
+ /*
+ * enable pwr here since we can't enable it in
+ * vsync callback in isr mode
+ */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON,
+ FALSE);
+ }
+
+ if (pdata->set_vsync_notifier != NULL) {
+ vsync_fnc_enabled = TRUE;
+ pdata->set_vsync_notifier(mdp_vsync_handler,
+ (void *)mfd);
+ }
+ }
+ }
+
+ if ((mfd) && (!vsync_fnc_enabled))
+ mfd->vsync_handler_pending = FALSE;
+}
+
+boolean mdp_hw_vsync_set_handler(msm_fb_vsync_handler_type handler, void *data)
+{
+ /*
+ * ToDo: tried enabling/disabling GPIO MDP HW VSYNC interrupt
+ * but getting inaccurate timing in mdp_vsync_handler()
+ * enable_irq(MDP_HW_VSYNC_IRQ);
+ */
+
+ return TRUE;
+}
+
+uint32 mdp_get_lcd_line_counter(struct msm_fb_data_type *mfd)
+{
+ uint32 elapsed_usec_time;
+ uint32 lcd_line;
+ ktime_t last_vsync_timetick_local;
+ ktime_t curr_time;
+ unsigned long flag;
+
+ if ((!mfd->panel_info.lcd.vsync_enable) || (!vsync_mode))
+ return 0;
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ last_vsync_timetick_local = mfd->last_vsync_timetick;
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+ curr_time = ktime_get_real();
+ elapsed_usec_time =
+ ((curr_time.tv.sec - last_vsync_timetick_local.tv.sec) * 1000000) +
+ ((curr_time.tv.nsec - last_vsync_timetick_local.tv.nsec) / 1000);
+
+ elapsed_usec_time = elapsed_usec_time % mfd->lcd_ref_usec_time;
+
+ /* lcd line calculation referencing to line counter = 0 */
+ lcd_line =
+ (elapsed_usec_time * mfd->total_lcd_lines) / mfd->lcd_ref_usec_time;
+
+ /* lcd line adjusment referencing to the actual line counter at vsync */
+ lcd_line =
+ (mfd->total_lcd_lines - mfd->panel_info.lcd.v_back_porch +
+ lcd_line) % (mfd->total_lcd_lines + 1);
+
+ if (lcd_line > mfd->total_lcd_lines) {
+ MSM_FB_INFO
+ ("mdp_get_lcd_line_counter: mdp_lcd_rd_cnt >= mfd->total_lcd_lines error!\n");
+ }
+
+ return lcd_line;
+}
diff --git a/drivers/staging/msm/memory.c b/drivers/staging/msm/memory.c
new file mode 100644
index 0000000..cc80fdf
--- /dev/null
+++ b/drivers/staging/msm/memory.c
@@ -0,0 +1,214 @@
+/* arch/arm/mach-msm/memory.c
+ *
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * 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/mm.h>
+#include <linux/mm_types.h>
+#include <linux/bootmem.h>
+#include <linux/module.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+#include <asm/mach/map.h>
+#include "memory_ll.h"
+#include <asm/cacheflush.h>
+#if defined(CONFIG_MSM_NPA_REMOTE)
+#include "npa_remote.h"
+#include <linux/completion.h>
+#include <linux/err.h>
+#endif
+
+int arch_io_remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
+ unsigned long pfn, unsigned long size, pgprot_t prot)
+{
+ unsigned long pfn_addr = pfn << PAGE_SHIFT;
+/*
+ if ((pfn_addr >= 0x88000000) && (pfn_addr < 0xD0000000)) {
+ prot = pgprot_device(prot);
+ printk("remapping device %lx\n", prot);
+ }
+*/
+ panic("Memory remap PFN stuff not done\n");
+ return remap_pfn_range(vma, addr, pfn, size, prot);
+}
+
+void *zero_page_strongly_ordered;
+
+static void map_zero_page_strongly_ordered(void)
+{
+ if (zero_page_strongly_ordered)
+ return;
+/*
+ zero_page_strongly_ordered =
+ ioremap_strongly_ordered(page_to_pfn(empty_zero_page)
+ << PAGE_SHIFT, PAGE_SIZE);
+*/
+ panic("Strongly ordered memory functions not implemented\n");
+}
+
+void write_to_strongly_ordered_memory(void)
+{
+ map_zero_page_strongly_ordered();
+ *(int *)zero_page_strongly_ordered = 0;
+}
+EXPORT_SYMBOL(write_to_strongly_ordered_memory);
+
+void flush_axi_bus_buffer(void)
+{
+ __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
+ : : "r" (0) : "memory");
+ write_to_strongly_ordered_memory();
+}
+
+#define CACHE_LINE_SIZE 32
+
+/* These cache related routines make the assumption that the associated
+ * physical memory is contiguous. They will operate on all (L1
+ * and L2 if present) caches.
+ */
+void clean_and_invalidate_caches(unsigned long vstart,
+ unsigned long length, unsigned long pstart)
+{
+ unsigned long vaddr;
+
+ for (vaddr = vstart; vaddr < vstart + length; vaddr += CACHE_LINE_SIZE)
+ asm ("mcr p15, 0, %0, c7, c14, 1" : : "r" (vaddr));
+#ifdef CONFIG_OUTER_CACHE
+ outer_flush_range(pstart, pstart + length);
+#endif
+ asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
+ asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0));
+
+ flush_axi_bus_buffer();
+}
+
+void clean_caches(unsigned long vstart,
+ unsigned long length, unsigned long pstart)
+{
+ unsigned long vaddr;
+
+ for (vaddr = vstart; vaddr < vstart + length; vaddr += CACHE_LINE_SIZE)
+ asm ("mcr p15, 0, %0, c7, c10, 1" : : "r" (vaddr));
+#ifdef CONFIG_OUTER_CACHE
+ outer_clean_range(pstart, pstart + length);
+#endif
+ asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
+ asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0));
+
+ flush_axi_bus_buffer();
+}
+
+void invalidate_caches(unsigned long vstart,
+ unsigned long length, unsigned long pstart)
+{
+ unsigned long vaddr;
+
+ for (vaddr = vstart; vaddr < vstart + length; vaddr += CACHE_LINE_SIZE)
+ asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (vaddr));
+#ifdef CONFIG_OUTER_CACHE
+ outer_inv_range(pstart, pstart + length);
+#endif
+ asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
+ asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0));
+
+ flush_axi_bus_buffer();
+}
+
+void *alloc_bootmem_aligned(unsigned long size, unsigned long alignment)
+{
+ void *unused_addr = NULL;
+ unsigned long addr, tmp_size, unused_size;
+
+ /* Allocate maximum size needed, see where it ends up.
+ * Then free it -- in this path there are no other allocators
+ * so we can depend on getting the same address back
+ * when we allocate a smaller piece that is aligned
+ * at the end (if necessary) and the piece we really want,
+ * then free the unused first piece.
+ */
+
+ tmp_size = size + alignment - PAGE_SIZE;
+ addr = (unsigned long)alloc_bootmem(tmp_size);
+ free_bootmem(__pa(addr), tmp_size);
+
+ unused_size = alignment - (addr % alignment);
+ if (unused_size)
+ unused_addr = alloc_bootmem(unused_size);
+
+ addr = (unsigned long)alloc_bootmem(size);
+ if (unused_size)
+ free_bootmem(__pa(unused_addr), unused_size);
+
+ return (void *)addr;
+}
+
+#if defined(CONFIG_MSM_NPA_REMOTE)
+struct npa_client *npa_memory_client;
+#endif
+
+static int change_memory_power_state(unsigned long start_pfn,
+ unsigned long nr_pages, int state)
+{
+#if defined(CONFIG_MSM_NPA_REMOTE)
+ static atomic_t node_created_flag = ATOMIC_INIT(1);
+#else
+ unsigned long start;
+ unsigned long size;
+ unsigned long virtual;
+#endif
+ int rc = 0;
+
+#if defined(CONFIG_MSM_NPA_REMOTE)
+ if (atomic_dec_and_test(&node_created_flag)) {
+ /* Create NPA 'required' client. */
+ npa_memory_client = npa_create_sync_client(NPA_MEMORY_NODE_NAME,
+ "memory node", NPA_CLIENT_REQUIRED);
+ if (IS_ERR(npa_memory_client)) {
+ rc = PTR_ERR(npa_memory_client);
+ return rc;
+ }
+ }
+
+ rc = npa_issue_required_request(npa_memory_client, state);
+#else
+ if (state == MEMORY_DEEP_POWERDOWN) {
+ /* simulate turning off memory by writing bit pattern into it */
+ start = start_pfn << PAGE_SHIFT;
+ size = nr_pages << PAGE_SHIFT;
+ virtual = __phys_to_virt(start);
+ memset((void *)virtual, 0x27, size);
+ }
+#endif
+ return rc;
+}
+
+int platform_physical_remove_pages(unsigned long start_pfn,
+ unsigned long nr_pages)
+{
+ return change_memory_power_state(start_pfn, nr_pages,
+ MEMORY_DEEP_POWERDOWN);
+}
+
+int platform_physical_add_pages(unsigned long start_pfn,
+ unsigned long nr_pages)
+{
+ return change_memory_power_state(start_pfn, nr_pages, MEMORY_ACTIVE);
+}
+
+int platform_physical_low_power_pages(unsigned long start_pfn,
+ unsigned long nr_pages)
+{
+ return change_memory_power_state(start_pfn, nr_pages,
+ MEMORY_SELF_REFRESH);
+}
diff --git a/drivers/staging/msm/memory_ll.h b/drivers/staging/msm/memory_ll.h
new file mode 100644
index 0000000..18a239a
--- /dev/null
+++ b/drivers/staging/msm/memory_ll.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * 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 __ASM_ARCH_MEMORY_LL_H
+#define __ASM_ARCH_MEMORY_LL_H
+
+#define MAX_PHYSMEM_BITS 32
+#define SECTION_SIZE_BITS 25
+
+#define HAS_ARCH_IO_REMAP_PFN_RANGE
+
+#ifndef __ASSEMBLY__
+void *alloc_bootmem_aligned(unsigned long size, unsigned long alignment);
+void clean_and_invalidate_caches(unsigned long, unsigned long, unsigned long);
+void clean_caches(unsigned long, unsigned long, unsigned long);
+void invalidate_caches(unsigned long, unsigned long, unsigned long);
+int platform_physical_remove_pages(unsigned long, unsigned long);
+int platform_physical_add_pages(unsigned long, unsigned long);
+int platform_physical_low_power_pages(unsigned long, unsigned long);
+
+#ifdef CONFIG_ARCH_MSM_ARM11
+void write_to_strongly_ordered_memory(void);
+
+#include <asm/mach-types.h>
+
+#define arch_barrier_extra() do \
+ { if (machine_is_msm7x27_surf() || machine_is_msm7x27_ffa()) \
+ write_to_strongly_ordered_memory(); \
+ } while (0)
+#endif
+
+#ifdef CONFIG_CACHE_L2X0
+extern void l2x0_cache_sync(void);
+#define finish_arch_switch(prev) do { l2x0_cache_sync(); } while (0)
+#endif
+
+#endif
+
+#ifdef CONFIG_ARCH_MSM_SCORPION
+#define arch_has_speculative_dfetch() 1
+#endif
+
+#endif
+
+/* these correspond to values known by the modem */
+#define MEMORY_DEEP_POWERDOWN 0
+#define MEMORY_SELF_REFRESH 1
+#define MEMORY_ACTIVE 2
+
+#define NPA_MEMORY_NODE_NAME "/mem/ebi1/cs1"
diff --git a/drivers/staging/msm/msm_fb.c b/drivers/staging/msm/msm_fb.c
new file mode 100644
index 0000000..af5620e
--- /dev/null
+++ b/drivers/staging/msm/msm_fb.c
@@ -0,0 +1,2354 @@
+/*
+ *
+ * Core MSM framebuffer driver.
+ *
+ * Copyright (C) 2007 Google Incorporated
+ * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * 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/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include "msm_mdp.h"
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <mach/board.h>
+#include <linux/uaccess.h>
+
+#include <linux/workqueue.h>
+#include <linux/string.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+#include <linux/vmalloc.h>
+#include <linux/debugfs.h>
+#include <linux/console.h>
+#include <linux/leds.h>
+#include <asm/dma-mapping.h>
+
+
+#define MSM_FB_C
+#include "msm_fb.h"
+#include "mddihosti.h"
+#include "tvenc.h"
+#include "mdp.h"
+#include "mdp4.h"
+
+#ifdef CONFIG_FB_MSM_LOGO
+#define INIT_IMAGE_FILE "/logo.rle"
+extern int load_565rle_image(char *filename);
+#endif
+
+
+#define pgprot_noncached(prot) \
+ __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED)
+#define pgprot_writecombine(prot) \
+ __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE)
+#define pgprot_device(prot) \
+ __pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_DEV_NONSHARED)
+#define pgprot_writethroughcache(prot) \
+ __pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_WRITETHROUGH)
+#define pgprot_writebackcache(prot) \
+ __pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_WRITEBACK)
+#define pgprot_writebackwacache(prot) \
+ __pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_WRITEALLOC)
+
+static unsigned char *fbram;
+static unsigned char *fbram_phys;
+static int fbram_size;
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+
+int vsync_mode = 1;
+
+#define MAX_FBI_LIST 32
+static struct fb_info *fbi_list[MAX_FBI_LIST];
+static int fbi_list_index;
+
+static struct msm_fb_data_type *mfd_list[MAX_FBI_LIST];
+static int mfd_list_index;
+
+static u32 msm_fb_pseudo_palette[16] = {
+ 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
+};
+
+u32 msm_fb_debug_enabled;
+/* Setting msm_fb_msg_level to 8 prints out ALL messages */
+u32 msm_fb_msg_level = 7;
+
+/* Setting mddi_msg_level to 8 prints out ALL messages */
+u32 mddi_msg_level = 5;
+
+extern int32 mdp_block_power_cnt[MDP_MAX_BLOCK];
+extern unsigned long mdp_timer_duration;
+
+static int msm_fb_register(struct msm_fb_data_type *mfd);
+static int msm_fb_open(struct fb_info *info, int user);
+static int msm_fb_release(struct fb_info *info, int user);
+static int msm_fb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info);
+static int msm_fb_stop_sw_refresher(struct msm_fb_data_type *mfd);
+int msm_fb_resume_sw_refresher(struct msm_fb_data_type *mfd);
+static int msm_fb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info);
+static int msm_fb_set_par(struct fb_info *info);
+static int msm_fb_blank_sub(int blank_mode, struct fb_info *info,
+ boolean op_enable);
+static int msm_fb_suspend_sub(struct msm_fb_data_type *mfd);
+static int msm_fb_resume_sub(struct msm_fb_data_type *mfd);
+static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg);
+static int msm_fb_mmap(struct fb_info *info, struct vm_area_struct * vma);
+
+#ifdef MSM_FB_ENABLE_DBGFS
+
+#define MSM_FB_MAX_DBGFS 1024
+#define MAX_BACKLIGHT_BRIGHTNESS 255
+
+int msm_fb_debugfs_file_index;
+struct dentry *msm_fb_debugfs_root;
+struct dentry *msm_fb_debugfs_file[MSM_FB_MAX_DBGFS];
+
+struct dentry *msm_fb_get_debugfs_root(void)
+{
+ if (msm_fb_debugfs_root == NULL)
+ msm_fb_debugfs_root = debugfs_create_dir("msm_fb", NULL);
+
+ return msm_fb_debugfs_root;
+}
+
+void msm_fb_debugfs_file_create(struct dentry *root, const char *name,
+ u32 *var)
+{
+ if (msm_fb_debugfs_file_index >= MSM_FB_MAX_DBGFS)
+ return;
+
+ msm_fb_debugfs_file[msm_fb_debugfs_file_index++] =
+ debugfs_create_u32(name, S_IRUGO | S_IWUSR, root, var);
+}
+#endif
+
+int msm_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ if (!mfd->cursor_update)
+ return -ENODEV;
+
+ return mfd->cursor_update(info, cursor);
+}
+
+static int msm_fb_resource_initialized;
+
+#ifndef CONFIG_FB_BACKLIGHT
+static int lcd_backlight_registered;
+
+static void msm_fb_set_bl_brightness(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct msm_fb_data_type *mfd = dev_get_drvdata(led_cdev->dev->parent);
+ int bl_lvl;
+
+ if (value > MAX_BACKLIGHT_BRIGHTNESS)
+ value = MAX_BACKLIGHT_BRIGHTNESS;
+
+ /* This maps android backlight level 0 to 255 into
+ driver backlight level 0 to bl_max with rounding */
+ bl_lvl = (2 * value * mfd->panel_info.bl_max + MAX_BACKLIGHT_BRIGHTNESS)
+ /(2 * MAX_BACKLIGHT_BRIGHTNESS);
+
+ if (!bl_lvl && value)
+ bl_lvl = 1;
+
+ msm_fb_set_backlight(mfd, bl_lvl, 1);
+}
+
+static struct led_classdev backlight_led = {
+ .name = "lcd-backlight",
+ .brightness = MAX_BACKLIGHT_BRIGHTNESS,
+ .brightness_set = msm_fb_set_bl_brightness,
+};
+#endif
+
+static struct msm_fb_platform_data *msm_fb_pdata;
+
+int msm_fb_detect_client(const char *name)
+{
+ int ret = -EPERM;
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+ u32 id;
+#endif
+
+ if (msm_fb_pdata && msm_fb_pdata->detect_client) {
+ ret = msm_fb_pdata->detect_client(name);
+
+ /* if it's non mddi panel, we need to pre-scan
+ mddi client to see if we can disable mddi host */
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+ if (!ret && msm_fb_pdata->mddi_prescan)
+ id = mddi_get_client_id();
+#endif
+ }
+
+ return ret;
+}
+
+static int msm_fb_probe(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ int rc;
+
+ MSM_FB_DEBUG("msm_fb_probe\n");
+
+ if ((pdev->id == 0) && (pdev->num_resources > 0)) {
+ msm_fb_pdata = pdev->dev.platform_data;
+ fbram_size =
+ pdev->resource[0].end - pdev->resource[0].start + 1;
+ fbram_phys = (char *)pdev->resource[0].start;
+ fbram = ioremap((unsigned long)fbram_phys, fbram_size);
+
+ if (!fbram) {
+ printk(KERN_ERR "fbram ioremap failed!\n");
+ return -ENOMEM;
+ }
+ MSM_FB_INFO("msm_fb_probe: phy_Addr = 0x%x virt = 0x%x\n",
+ (int)fbram_phys, (int)fbram);
+
+ msm_fb_resource_initialized = 1;
+ return 0;
+ }
+
+ if (!msm_fb_resource_initialized)
+ return -EPERM;
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+ return -ENOMEM;
+
+ mfd->panel_info.frame_count = 0;
+ mfd->bl_level = mfd->panel_info.bl_max;
+
+ if (mfd->panel_info.type == LCDC_PANEL)
+ mfd->allow_set_offset =
+ msm_fb_pdata->allow_set_offset != NULL ?
+ msm_fb_pdata->allow_set_offset() : 0;
+ else
+ mfd->allow_set_offset = 0;
+
+ rc = msm_fb_register(mfd);
+ if (rc)
+ return rc;
+
+#ifdef CONFIG_FB_BACKLIGHT
+ msm_fb_config_backlight(mfd);
+#else
+ /* android supports only one lcd-backlight/lcd for now */
+ if (!lcd_backlight_registered) {
+ if (led_classdev_register(&pdev->dev, &backlight_led))
+ printk(KERN_ERR "led_classdev_register failed\n");
+ else
+ lcd_backlight_registered = 1;
+ }
+#endif
+
+ pdev_list[pdev_list_cnt++] = pdev;
+ return 0;
+}
+
+static int msm_fb_remove(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+
+ MSM_FB_DEBUG("msm_fb_remove\n");
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ if (msm_fb_suspend_sub(mfd))
+ printk(KERN_ERR "msm_fb_remove: can't stop the device %d\n", mfd->index);
+
+ if (mfd->channel_irq != 0)
+ free_irq(mfd->channel_irq, (void *)mfd);
+
+ if (mfd->vsync_width_boundary)
+ vfree(mfd->vsync_width_boundary);
+
+ if (mfd->vsync_resync_timer.function)
+ del_timer(&mfd->vsync_resync_timer);
+
+ if (mfd->refresh_timer.function)
+ del_timer(&mfd->refresh_timer);
+
+ if (mfd->dma_hrtimer.function)
+ hrtimer_cancel(&mfd->dma_hrtimer);
+
+ /* remove /dev/fb* */
+ unregister_framebuffer(mfd->fbi);
+
+#ifdef CONFIG_FB_BACKLIGHT
+ /* remove /sys/class/backlight */
+ backlight_device_unregister(mfd->fbi->bl_dev);
+#else
+ if (lcd_backlight_registered) {
+ lcd_backlight_registered = 0;
+ led_classdev_unregister(&backlight_led);
+ }
+#endif
+
+#ifdef MSM_FB_ENABLE_DBGFS
+ if (mfd->sub_dir)
+ debugfs_remove(mfd->sub_dir);
+#endif
+
+ return 0;
+}
+
+#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
+static int msm_fb_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct msm_fb_data_type *mfd;
+ int ret = 0;
+
+ MSM_FB_DEBUG("msm_fb_suspend\n");
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ if ((!mfd) || (mfd->key != MFD_KEY))
+ return 0;
+
+ acquire_console_sem();
+ fb_set_suspend(mfd->fbi, 1);
+
+ ret = msm_fb_suspend_sub(mfd);
+ if (ret != 0) {
+ printk(KERN_ERR "msm_fb: failed to suspend! %d\n", ret);
+ fb_set_suspend(mfd->fbi, 0);
+ } else {
+ pdev->dev.power.power_state = state;
+ }
+
+ release_console_sem();
+ return ret;
+}
+#else
+#define msm_fb_suspend NULL
+#endif
+
+static int msm_fb_suspend_sub(struct msm_fb_data_type *mfd)
+{
+ int ret = 0;
+
+ if ((!mfd) || (mfd->key != MFD_KEY))
+ return 0;
+
+ /*
+ * suspend this channel
+ */
+ mfd->suspend.sw_refreshing_enable = mfd->sw_refreshing_enable;
+ mfd->suspend.op_enable = mfd->op_enable;
+ mfd->suspend.panel_power_on = mfd->panel_power_on;
+
+ if (mfd->op_enable) {
+ ret =
+ msm_fb_blank_sub(FB_BLANK_POWERDOWN, mfd->fbi,
+ mfd->suspend.op_enable);
+ if (ret) {
+ MSM_FB_INFO
+ ("msm_fb_suspend: can't turn off display!\n");
+ return ret;
+ }
+ mfd->op_enable = FALSE;
+ }
+ /*
+ * try to power down
+ */
+ mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ /*
+ * detach display channel irq if there's any
+ * or wait until vsync-resync completes
+ */
+ if ((mfd->dest == DISPLAY_LCD)) {
+ if (mfd->panel_info.lcd.vsync_enable) {
+ if (mfd->panel_info.lcd.hw_vsync_mode) {
+ if (mfd->channel_irq != 0)
+ disable_irq(mfd->channel_irq);
+ } else {
+ volatile boolean vh_pending;
+ do {
+ vh_pending = mfd->vsync_handler_pending;
+ } while (vh_pending);
+ }
+ }
+ }
+
+ return 0;
+}
+
+#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
+static int msm_fb_resume(struct platform_device *pdev)
+{
+ /* This resume function is called when interrupt is enabled.
+ */
+ int ret = 0;
+ struct msm_fb_data_type *mfd;
+
+ MSM_FB_DEBUG("msm_fb_resume\n");
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+ if ((!mfd) || (mfd->key != MFD_KEY))
+ return 0;
+
+ acquire_console_sem();
+ ret = msm_fb_resume_sub(mfd);
+ pdev->dev.power.power_state = PMSG_ON;
+ fb_set_suspend(mfd->fbi, 1);
+ release_console_sem();
+
+ return ret;
+}
+#else
+#define msm_fb_resume NULL
+#endif
+
+static int msm_fb_resume_sub(struct msm_fb_data_type *mfd)
+{
+ int ret = 0;
+
+ if ((!mfd) || (mfd->key != MFD_KEY))
+ return 0;
+
+ /* attach display channel irq if there's any */
+ if (mfd->channel_irq != 0)
+ enable_irq(mfd->channel_irq);
+
+ /* resume state var recover */
+ mfd->sw_refreshing_enable = mfd->suspend.sw_refreshing_enable;
+ mfd->op_enable = mfd->suspend.op_enable;
+
+ if (mfd->suspend.panel_power_on) {
+ ret =
+ msm_fb_blank_sub(FB_BLANK_UNBLANK, mfd->fbi,
+ mfd->op_enable);
+ if (ret)
+ MSM_FB_INFO("msm_fb_resume: can't turn on display!\n");
+ }
+
+ return ret;
+}
+
+static struct platform_driver msm_fb_driver = {
+ .probe = msm_fb_probe,
+ .remove = msm_fb_remove,
+#ifndef CONFIG_HAS_EARLYSUSPEND
+ .suspend = msm_fb_suspend,
+ .resume = msm_fb_resume,
+#endif
+ .shutdown = NULL,
+ .driver = {
+ /* Driver name must match the device name added in platform.c. */
+ .name = "msm_fb",
+ },
+};
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void msmfb_early_suspend(struct early_suspend *h)
+{
+ struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
+ early_suspend);
+ msm_fb_suspend_sub(mfd);
+}
+
+static void msmfb_early_resume(struct early_suspend *h)
+{
+ struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
+ early_suspend);
+ msm_fb_resume_sub(mfd);
+}
+#endif
+
+void msm_fb_set_backlight(struct msm_fb_data_type *mfd, __u32 bkl_lvl, u32 save)
+{
+ struct msm_fb_panel_data *pdata;
+
+ pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+
+ if ((pdata) && (pdata->set_backlight)) {
+ down(&mfd->sem);
+ if ((bkl_lvl != mfd->bl_level) || (!save)) {
+ u32 old_lvl;
+
+ old_lvl = mfd->bl_level;
+ mfd->bl_level = bkl_lvl;
+ pdata->set_backlight(mfd);
+
+ if (!save)
+ mfd->bl_level = old_lvl;
+ }
+ up(&mfd->sem);
+ }
+}
+
+static int msm_fb_blank_sub(int blank_mode, struct fb_info *info,
+ boolean op_enable)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ struct msm_fb_panel_data *pdata = NULL;
+ int ret = 0;
+
+ if (!op_enable)
+ return -EPERM;
+
+ pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+ if ((!pdata) || (!pdata->on) || (!pdata->off)) {
+ printk(KERN_ERR "msm_fb_blank_sub: no panel operation detected!\n");
+ return -ENODEV;
+ }
+
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ if (!mfd->panel_power_on) {
+ mdelay(100);
+ ret = pdata->on(mfd->pdev);
+ if (ret == 0) {
+ mfd->panel_power_on = TRUE;
+
+ msm_fb_set_backlight(mfd,
+ mfd->bl_level, 0);
+
+/* ToDo: possible conflict with android which doesn't expect sw refresher */
+/*
+ if (!mfd->hw_refresh)
+ {
+ if ((ret = msm_fb_resume_sw_refresher(mfd)) != 0)
+ {
+ MSM_FB_INFO("msm_fb_blank_sub: msm_fb_resume_sw_refresher failed = %d!\n",ret);
+ }
+ }
+*/
+ }
+ }
+ break;
+
+ case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_HSYNC_SUSPEND:
+ case FB_BLANK_NORMAL:
+ case FB_BLANK_POWERDOWN:
+ default:
+ if (mfd->panel_power_on) {
+ int curr_pwr_state;
+
+ mfd->op_enable = FALSE;
+ curr_pwr_state = mfd->panel_power_on;
+ mfd->panel_power_on = FALSE;
+
+ mdelay(100);
+ ret = pdata->off(mfd->pdev);
+ if (ret)
+ mfd->panel_power_on = curr_pwr_state;
+
+ msm_fb_set_backlight(mfd, 0, 0);
+ mfd->op_enable = TRUE;
+ }
+ break;
+ }
+
+ return ret;
+}
+
+static void msm_fb_fillrect(struct fb_info *info,
+ const struct fb_fillrect *rect)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ cfb_fillrect(info, rect);
+ if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
+ !mfd->sw_currently_refreshing) {
+ struct fb_var_screeninfo var;
+
+ var = info->var;
+ var.reserved[0] = 0x54445055;
+ var.reserved[1] = (rect->dy << 16) | (rect->dx);
+ var.reserved[2] = ((rect->dy + rect->height) << 16) |
+ (rect->dx + rect->width);
+
+ msm_fb_pan_display(&var, info);
+ }
+}
+
+static void msm_fb_copyarea(struct fb_info *info,
+ const struct fb_copyarea *area)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ cfb_copyarea(info, area);
+ if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
+ !mfd->sw_currently_refreshing) {
+ struct fb_var_screeninfo var;
+
+ var = info->var;
+ var.reserved[0] = 0x54445055;
+ var.reserved[1] = (area->dy << 16) | (area->dx);
+ var.reserved[2] = ((area->dy + area->height) << 16) |
+ (area->dx + area->width);
+
+ msm_fb_pan_display(&var, info);
+ }
+}
+
+static void msm_fb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ cfb_imageblit(info, image);
+ if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
+ !mfd->sw_currently_refreshing) {
+ struct fb_var_screeninfo var;
+
+ var = info->var;
+ var.reserved[0] = 0x54445055;
+ var.reserved[1] = (image->dy << 16) | (image->dx);
+ var.reserved[2] = ((image->dy + image->height) << 16) |
+ (image->dx + image->width);
+
+ msm_fb_pan_display(&var, info);
+ }
+}
+
+static int msm_fb_blank(int blank_mode, struct fb_info *info)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ return msm_fb_blank_sub(blank_mode, info, mfd->op_enable);
+}
+
+static int msm_fb_set_lut(struct fb_cmap *cmap, struct fb_info *info)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ if (!mfd->lut_update)
+ return -ENODEV;
+
+ mfd->lut_update(info, cmap);
+ return 0;
+}
+
+/*
+ * Custom Framebuffer mmap() function for MSM driver.
+ * Differs from standard mmap() function by allowing for customized
+ * page-protection.
+ */
+static int msm_fb_mmap(struct fb_info *info, struct vm_area_struct * vma)
+{
+ /* Get frame buffer memory range. */
+ unsigned long start = info->fix.smem_start;
+ u32 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
+ unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ if (off >= len) {
+ /* memory mapped io */
+ off -= len;
+ if (info->var.accel_flags) {
+ mutex_unlock(&info->lock);
+ return -EINVAL;
+ }
+ start = info->fix.mmio_start;
+ len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
+ }
+
+ /* Set VM flags. */
+ start &= PAGE_MASK;
+ if ((vma->vm_end - vma->vm_start + off) > len)
+ return -EINVAL;
+ off += start;
+ vma->vm_pgoff = off >> PAGE_SHIFT;
+ /* This is an IO map - tell maydump to skip this VMA */
+ vma->vm_flags |= VM_IO | VM_RESERVED;
+
+ /* Set VM page protection */
+ if (mfd->mdp_fb_page_protection == MDP_FB_PAGE_PROTECTION_WRITECOMBINE)
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+ else if (mfd->mdp_fb_page_protection ==
+ MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE)
+ vma->vm_page_prot = pgprot_writethroughcache(vma->vm_page_prot);
+ else if (mfd->mdp_fb_page_protection ==
+ MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE)
+ vma->vm_page_prot = pgprot_writebackcache(vma->vm_page_prot);
+ else if (mfd->mdp_fb_page_protection ==
+ MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE)
+ vma->vm_page_prot = pgprot_writebackwacache(vma->vm_page_prot);
+ else
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ /* Remap the frame buffer I/O range */
+ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot))
+ return -EAGAIN;
+
+ return 0;
+}
+
+static struct fb_ops msm_fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_open = msm_fb_open,
+ .fb_release = msm_fb_release,
+ .fb_read = NULL,
+ .fb_write = NULL,
+ .fb_cursor = NULL,
+ .fb_check_var = msm_fb_check_var, /* vinfo check */
+ .fb_set_par = msm_fb_set_par, /* set the video mode according to info->var */
+ .fb_setcolreg = NULL, /* set color register */
+ .fb_blank = msm_fb_blank, /* blank display */
+ .fb_pan_display = msm_fb_pan_display, /* pan display */
+ .fb_fillrect = msm_fb_fillrect, /* Draws a rectangle */
+ .fb_copyarea = msm_fb_copyarea, /* Copy data from area to another */
+ .fb_imageblit = msm_fb_imageblit, /* Draws a image to the display */
+ .fb_rotate = NULL,
+ .fb_sync = NULL, /* wait for blit idle, optional */
+ .fb_ioctl = msm_fb_ioctl, /* perform fb specific ioctl (optional) */
+ .fb_mmap = msm_fb_mmap,
+};
+
+static int msm_fb_register(struct msm_fb_data_type *mfd)
+{
+ int ret = -ENODEV;
+ int bpp;
+ struct msm_panel_info *panel_info = &mfd->panel_info;
+ struct fb_info *fbi = mfd->fbi;
+ struct fb_fix_screeninfo *fix;
+ struct fb_var_screeninfo *var;
+ int *id;
+ int fbram_offset;
+
+ /*
+ * fb info initialization
+ */
+ fix = &fbi->fix;
+ var = &fbi->var;
+
+ fix->type_aux = 0; /* if type == FB_TYPE_INTERLEAVED_PLANES */
+ fix->visual = FB_VISUAL_TRUECOLOR; /* True Color */
+ fix->ywrapstep = 0; /* No support */
+ fix->mmio_start = 0; /* No MMIO Address */
+ fix->mmio_len = 0; /* No MMIO Address */
+ fix->accel = FB_ACCEL_NONE;/* FB_ACCEL_MSM needes to be added in fb.h */
+
+ var->xoffset = 0, /* Offset from virtual to visible */
+ var->yoffset = 0, /* resolution */
+ var->grayscale = 0, /* No graylevels */
+ var->nonstd = 0, /* standard pixel format */
+ var->activate = FB_ACTIVATE_VBL, /* activate it at vsync */
+ var->height = -1, /* height of picture in mm */
+ var->width = -1, /* width of picture in mm */
+ var->accel_flags = 0, /* acceleration flags */
+ var->sync = 0, /* see FB_SYNC_* */
+ var->rotate = 0, /* angle we rotate counter clockwise */
+ mfd->op_enable = FALSE;
+
+ switch (mfd->fb_imgType) {
+ case MDP_RGB_565:
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->xpanstep = 1;
+ fix->ypanstep = 1;
+ var->vmode = FB_VMODE_NONINTERLACED;
+ var->blue.offset = 0;
+ var->green.offset = 5;
+ var->red.offset = 11;
+ var->blue.length = 5;
+ var->green.length = 6;
+ var->red.length = 5;
+ var->blue.msb_right = 0;
+ var->green.msb_right = 0;
+ var->red.msb_right = 0;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ bpp = 2;
+ break;
+
+ case MDP_RGB_888:
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->xpanstep = 1;
+ fix->ypanstep = 1;
+ var->vmode = FB_VMODE_NONINTERLACED;
+ var->blue.offset = 0;
+ var->green.offset = 8;
+ var->red.offset = 16;
+ var->blue.length = 8;
+ var->green.length = 8;
+ var->red.length = 8;
+ var->blue.msb_right = 0;
+ var->green.msb_right = 0;
+ var->red.msb_right = 0;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ bpp = 3;
+ break;
+
+ case MDP_ARGB_8888:
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->xpanstep = 1;
+ fix->ypanstep = 1;
+ var->vmode = FB_VMODE_NONINTERLACED;
+ var->blue.offset = 0;
+ var->green.offset = 8;
+ var->red.offset = 16;
+ var->blue.length = 8;
+ var->green.length = 8;
+ var->red.length = 8;
+ var->blue.msb_right = 0;
+ var->green.msb_right = 0;
+ var->red.msb_right = 0;
+ var->transp.offset = 24;
+ var->transp.length = 8;
+ bpp = 3;
+ break;
+
+ case MDP_YCRYCB_H2V1:
+ /* ToDo: need to check TV-Out YUV422i framebuffer format */
+ /* we might need to create new type define */
+ fix->type = FB_TYPE_INTERLEAVED_PLANES;
+ fix->xpanstep = 2;
+ fix->ypanstep = 1;
+ var->vmode = FB_VMODE_NONINTERLACED;
+
+ /* how about R/G/B offset? */
+ var->blue.offset = 0;
+ var->green.offset = 5;
+ var->red.offset = 11;
+ var->blue.length = 5;
+ var->green.length = 6;
+ var->red.length = 5;
+ var->blue.msb_right = 0;
+ var->green.msb_right = 0;
+ var->red.msb_right = 0;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ bpp = 2;
+ break;
+
+ default:
+ MSM_FB_ERR("msm_fb_init: fb %d unkown image type!\n",
+ mfd->index);
+ return ret;
+ }
+
+ /* The adreno GPU hardware requires that the pitch be aligned to
+ 32 pixels for color buffers, so for the cases where the GPU
+ is writing directly to fb0, the framebuffer pitch
+ also needs to be 32 pixel aligned */
+
+ if (mfd->index == 0)
+ fix->line_length = ALIGN(panel_info->xres * bpp, 32);
+ else
+ fix->line_length = panel_info->xres * bpp;
+
+ fix->smem_len = fix->line_length * panel_info->yres * mfd->fb_page;
+
+ mfd->var_xres = panel_info->xres;
+ mfd->var_yres = panel_info->yres;
+
+ var->pixclock = mfd->panel_info.clk_rate;
+ mfd->var_pixclock = var->pixclock;
+
+ var->xres = panel_info->xres;
+ var->yres = panel_info->yres;
+ var->xres_virtual = panel_info->xres;
+ var->yres_virtual = panel_info->yres * mfd->fb_page;
+ var->bits_per_pixel = bpp * 8, /* FrameBuffer color depth */
+ /*
+ * id field for fb app
+ */
+ id = (int *)&mfd->panel;
+
+#if defined(CONFIG_FB_MSM_MDP22)
+ snprintf(fix->id, sizeof(fix->id), "msmfb22_%x", (__u32) *id);
+#elif defined(CONFIG_FB_MSM_MDP30)
+ snprintf(fix->id, sizeof(fix->id), "msmfb30_%x", (__u32) *id);
+#elif defined(CONFIG_FB_MSM_MDP31)
+ snprintf(fix->id, sizeof(fix->id), "msmfb31_%x", (__u32) *id);
+#elif defined(CONFIG_FB_MSM_MDP40)
+ snprintf(fix->id, sizeof(fix->id), "msmfb40_%x", (__u32) *id);
+#else
+ error CONFIG_FB_MSM_MDP undefined !
+#endif
+ fbi->fbops = &msm_fb_ops;
+ fbi->flags = FBINFO_FLAG_DEFAULT;
+ fbi->pseudo_palette = msm_fb_pseudo_palette;
+
+ mfd->ref_cnt = 0;
+ mfd->sw_currently_refreshing = FALSE;
+ mfd->sw_refreshing_enable = TRUE;
+ mfd->panel_power_on = FALSE;
+
+ mfd->pan_waiting = FALSE;
+ init_completion(&mfd->pan_comp);
+ init_completion(&mfd->refresher_comp);
+ init_MUTEX(&mfd->sem);
+
+ fbram_offset = PAGE_ALIGN((int)fbram)-(int)fbram;
+ fbram += fbram_offset;
+ fbram_phys += fbram_offset;
+ fbram_size -= fbram_offset;
+
+ if (fbram_size < fix->smem_len) {
+ printk(KERN_ERR "error: no more framebuffer memory!\n");
+ return -ENOMEM;
+ }
+
+ fbi->screen_base = fbram;
+ fbi->fix.smem_start = (unsigned long)fbram_phys;
+
+ memset(fbi->screen_base, 0x0, fix->smem_len);
+
+ mfd->op_enable = TRUE;
+ mfd->panel_power_on = FALSE;
+
+ /* cursor memory allocation */
+ if (mfd->cursor_update) {
+ mfd->cursor_buf = dma_alloc_coherent(NULL,
+ MDP_CURSOR_SIZE,
+ (dma_addr_t *) &mfd->cursor_buf_phys,
+ GFP_KERNEL);
+ if (!mfd->cursor_buf)
+ mfd->cursor_update = 0;
+ }
+
+ if (mfd->lut_update) {
+ ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
+ if (ret)
+ printk(KERN_ERR "%s: fb_alloc_cmap() failed!\n",
+ __func__);
+ }
+
+ if (register_framebuffer(fbi) < 0) {
+ if (mfd->lut_update)
+ fb_dealloc_cmap(&fbi->cmap);
+
+ if (mfd->cursor_buf)
+ dma_free_coherent(NULL,
+ MDP_CURSOR_SIZE,
+ mfd->cursor_buf,
+ (dma_addr_t) mfd->cursor_buf_phys);
+
+ mfd->op_enable = FALSE;
+ return -EPERM;
+ }
+
+ fbram += fix->smem_len;
+ fbram_phys += fix->smem_len;
+ fbram_size -= fix->smem_len;
+
+ MSM_FB_INFO
+ ("FrameBuffer[%d] %dx%d size=%d bytes is registered successfully!\n",
+ mfd->index, fbi->var.xres, fbi->var.yres, fbi->fix.smem_len);
+
+#ifdef CONFIG_FB_MSM_LOGO
+ if (!load_565rle_image(INIT_IMAGE_FILE)) ; /* Flip buffer */
+#endif
+ ret = 0;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ mfd->early_suspend.suspend = msmfb_early_suspend;
+ mfd->early_suspend.resume = msmfb_early_resume;
+ mfd->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 2;
+ register_early_suspend(&mfd->early_suspend);
+#endif
+
+#ifdef MSM_FB_ENABLE_DBGFS
+ {
+ struct dentry *root;
+ struct dentry *sub_dir;
+ char sub_name[2];
+
+ root = msm_fb_get_debugfs_root();
+ if (root != NULL) {
+ sub_name[0] = (char)(mfd->index + 0x30);
+ sub_name[1] = '\0';
+ sub_dir = debugfs_create_dir(sub_name, root);
+ } else {
+ sub_dir = NULL;
+ }
+
+ mfd->sub_dir = sub_dir;
+
+ if (sub_dir) {
+ msm_fb_debugfs_file_create(sub_dir, "op_enable",
+ (u32 *) &mfd->op_enable);
+ msm_fb_debugfs_file_create(sub_dir, "panel_power_on",
+ (u32 *) &mfd->
+ panel_power_on);
+ msm_fb_debugfs_file_create(sub_dir, "ref_cnt",
+ (u32 *) &mfd->ref_cnt);
+ msm_fb_debugfs_file_create(sub_dir, "fb_imgType",
+ (u32 *) &mfd->fb_imgType);
+ msm_fb_debugfs_file_create(sub_dir,
+ "sw_currently_refreshing",
+ (u32 *) &mfd->
+ sw_currently_refreshing);
+ msm_fb_debugfs_file_create(sub_dir,
+ "sw_refreshing_enable",
+ (u32 *) &mfd->
+ sw_refreshing_enable);
+
+ msm_fb_debugfs_file_create(sub_dir, "xres",
+ (u32 *) &mfd->panel_info.
+ xres);
+ msm_fb_debugfs_file_create(sub_dir, "yres",
+ (u32 *) &mfd->panel_info.
+ yres);
+ msm_fb_debugfs_file_create(sub_dir, "bpp",
+ (u32 *) &mfd->panel_info.
+ bpp);
+ msm_fb_debugfs_file_create(sub_dir, "type",
+ (u32 *) &mfd->panel_info.
+ type);
+ msm_fb_debugfs_file_create(sub_dir, "wait_cycle",
+ (u32 *) &mfd->panel_info.
+ wait_cycle);
+ msm_fb_debugfs_file_create(sub_dir, "pdest",
+ (u32 *) &mfd->panel_info.
+ pdest);
+ msm_fb_debugfs_file_create(sub_dir, "backbuff",
+ (u32 *) &mfd->panel_info.
+ fb_num);
+ msm_fb_debugfs_file_create(sub_dir, "clk_rate",
+ (u32 *) &mfd->panel_info.
+ clk_rate);
+ msm_fb_debugfs_file_create(sub_dir, "frame_count",
+ (u32 *) &mfd->panel_info.
+ frame_count);
+
+
+ switch (mfd->dest) {
+ case DISPLAY_LCD:
+ msm_fb_debugfs_file_create(sub_dir,
+ "vsync_enable",
+ (u32 *)&mfd->panel_info.lcd.vsync_enable);
+ msm_fb_debugfs_file_create(sub_dir,
+ "refx100",
+ (u32 *) &mfd->panel_info.lcd. refx100);
+ msm_fb_debugfs_file_create(sub_dir,
+ "v_back_porch",
+ (u32 *) &mfd->panel_info.lcd.v_back_porch);
+ msm_fb_debugfs_file_create(sub_dir,
+ "v_front_porch",
+ (u32 *) &mfd->panel_info.lcd.v_front_porch);
+ msm_fb_debugfs_file_create(sub_dir,
+ "v_pulse_width",
+ (u32 *) &mfd->panel_info.lcd.v_pulse_width);
+ msm_fb_debugfs_file_create(sub_dir,
+ "hw_vsync_mode",
+ (u32 *) &mfd->panel_info.lcd.hw_vsync_mode);
+ msm_fb_debugfs_file_create(sub_dir,
+ "vsync_notifier_period", (u32 *)
+ &mfd->panel_info.lcd.vsync_notifier_period);
+ break;
+
+ case DISPLAY_LCDC:
+ msm_fb_debugfs_file_create(sub_dir,
+ "h_back_porch",
+ (u32 *) &mfd->panel_info.lcdc.h_back_porch);
+ msm_fb_debugfs_file_create(sub_dir,
+ "h_front_porch",
+ (u32 *) &mfd->panel_info.lcdc.h_front_porch);
+ msm_fb_debugfs_file_create(sub_dir,
+ "h_pulse_width",
+ (u32 *) &mfd->panel_info.lcdc.h_pulse_width);
+ msm_fb_debugfs_file_create(sub_dir,
+ "v_back_porch",
+ (u32 *) &mfd->panel_info.lcdc.v_back_porch);
+ msm_fb_debugfs_file_create(sub_dir,
+ "v_front_porch",
+ (u32 *) &mfd->panel_info.lcdc.v_front_porch);
+ msm_fb_debugfs_file_create(sub_dir,
+ "v_pulse_width",
+ (u32 *) &mfd->panel_info.lcdc.v_pulse_width);
+ msm_fb_debugfs_file_create(sub_dir,
+ "border_clr",
+ (u32 *) &mfd->panel_info.lcdc.border_clr);
+ msm_fb_debugfs_file_create(sub_dir,
+ "underflow_clr",
+ (u32 *) &mfd->panel_info.lcdc.underflow_clr);
+ msm_fb_debugfs_file_create(sub_dir,
+ "hsync_skew",
+ (u32 *) &mfd->panel_info.lcdc.hsync_skew);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+#endif /* MSM_FB_ENABLE_DBGFS */
+
+ return ret;
+}
+
+static int msm_fb_open(struct fb_info *info, int user)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ if (!mfd->ref_cnt) {
+ mdp_set_dma_pan_info(info, NULL, TRUE);
+
+ if (msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable)) {
+ printk(KERN_ERR "msm_fb_open: can't turn on display!\n");
+ return -1;
+ }
+ }
+
+ mfd->ref_cnt++;
+ return 0;
+}
+
+static int msm_fb_release(struct fb_info *info, int user)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ int ret = 0;
+
+ if (!mfd->ref_cnt) {
+ MSM_FB_INFO("msm_fb_release: try to close unopened fb %d!\n",
+ mfd->index);
+ return -EINVAL;
+ }
+
+ mfd->ref_cnt--;
+
+ if (!mfd->ref_cnt) {
+ if ((ret =
+ msm_fb_blank_sub(FB_BLANK_POWERDOWN, info,
+ mfd->op_enable)) != 0) {
+ printk(KERN_ERR "msm_fb_release: can't turn off display!\n");
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+DECLARE_MUTEX(msm_fb_pan_sem);
+
+static int msm_fb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct mdp_dirty_region dirty;
+ struct mdp_dirty_region *dirtyPtr = NULL;
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ if ((!mfd->op_enable) || (!mfd->panel_power_on))
+ return -EPERM;
+
+ if (var->xoffset > (info->var.xres_virtual - info->var.xres))
+ return -EINVAL;
+
+ if (var->yoffset > (info->var.yres_virtual - info->var.yres))
+ return -EINVAL;
+
+ if (info->fix.xpanstep)
+ info->var.xoffset =
+ (var->xoffset / info->fix.xpanstep) * info->fix.xpanstep;
+
+ if (info->fix.ypanstep)
+ info->var.yoffset =
+ (var->yoffset / info->fix.ypanstep) * info->fix.ypanstep;
+
+ /* "UPDT" */
+ if (var->reserved[0] == 0x54445055) {
+ dirty.xoffset = var->reserved[1] & 0xffff;
+ dirty.yoffset = (var->reserved[1] >> 16) & 0xffff;
+
+ if ((var->reserved[2] & 0xffff) <= dirty.xoffset)
+ return -EINVAL;
+ if (((var->reserved[2] >> 16) & 0xffff) <= dirty.yoffset)
+ return -EINVAL;
+
+ dirty.width = (var->reserved[2] & 0xffff) - dirty.xoffset;
+ dirty.height =
+ ((var->reserved[2] >> 16) & 0xffff) - dirty.yoffset;
+ info->var.yoffset = var->yoffset;
+
+ if (dirty.xoffset < 0)
+ return -EINVAL;
+
+ if (dirty.yoffset < 0)
+ return -EINVAL;
+
+ if ((dirty.xoffset + dirty.width) > info->var.xres)
+ return -EINVAL;
+
+ if ((dirty.yoffset + dirty.height) > info->var.yres)
+ return -EINVAL;
+
+ if ((dirty.width <= 0) || (dirty.height <= 0))
+ return -EINVAL;
+
+ dirtyPtr = &dirty;
+ }
+
+ /* Flip */
+ /* A constant value is used to indicate that we should change the DMA
+ output buffer instead of just panning */
+
+ if (var->reserved[0] == 0x466c6970) {
+ unsigned long length, address;
+ struct file *p_src_file;
+ struct mdp_img imgdata;
+ int bpp;
+
+ if (mfd->allow_set_offset) {
+ imgdata.memory_id = var->reserved[1];
+ imgdata.priv = var->reserved[2];
+
+ /* If there is no memory ID then we want to reset back
+ to the original fb visibility */
+ if (var->reserved[1]) {
+ if (var->reserved[4] == MDP_BLIT_SRC_GEM) {
+ panic("waaaaaaaaaaaaaah");
+ if ( /*get_gem_img(&imgdata,
+ (unsigned long *) &address,
+ &length)*/ -1 < 0) {
+ return -1;
+ }
+ } else {
+ /*get_img(&imgdata, info, &address,
+ &length, &p_src_file);*/
+ panic("waaaaaah");
+ }
+ mfd->ibuf.visible_swapped = TRUE;
+ } else {
+ /* Flip back to the original address
+ adjusted for xoffset and yoffset */
+
+ bpp = info->var.bits_per_pixel / 8;
+ address = (unsigned long) info->fix.smem_start;
+ address += info->var.xoffset * bpp +
+ info->var.yoffset * info->fix.line_length;
+
+ mfd->ibuf.visible_swapped = FALSE;
+ }
+
+ mdp_set_offset_info(info, address,
+ (var->activate == FB_ACTIVATE_VBL));
+
+ mfd->dma_fnc(mfd);
+ return 0;
+ } else
+ return -EINVAL;
+ }
+
+ down(&msm_fb_pan_sem);
+ mdp_set_dma_pan_info(info, dirtyPtr,
+ (var->activate == FB_ACTIVATE_VBL));
+ mdp_dma_pan_update(info);
+ up(&msm_fb_pan_sem);
+
+ ++mfd->panel_info.frame_count;
+ return 0;
+}
+
+static int msm_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ if (var->rotate != FB_ROTATE_UR)
+ return -EINVAL;
+ if (var->grayscale != info->var.grayscale)
+ return -EINVAL;
+
+ switch (var->bits_per_pixel) {
+ case 16:
+ if ((var->green.offset != 5) ||
+ !((var->blue.offset == 11)
+ || (var->blue.offset == 0)) ||
+ !((var->red.offset == 11)
+ || (var->red.offset == 0)) ||
+ (var->blue.length != 5) ||
+ (var->green.length != 6) ||
+ (var->red.length != 5) ||
+ (var->blue.msb_right != 0) ||
+ (var->green.msb_right != 0) ||
+ (var->red.msb_right != 0) ||
+ (var->transp.offset != 0) ||
+ (var->transp.length != 0))
+ return -EINVAL;
+ break;
+
+ case 24:
+ if ((var->blue.offset != 0) ||
+ (var->green.offset != 8) ||
+ (var->red.offset != 16) ||
+ (var->blue.length != 8) ||
+ (var->green.length != 8) ||
+ (var->red.length != 8) ||
+ (var->blue.msb_right != 0) ||
+ (var->green.msb_right != 0) ||
+ (var->red.msb_right != 0) ||
+ !(((var->transp.offset == 0) &&
+ (var->transp.length == 0)) ||
+ ((var->transp.offset == 24) &&
+ (var->transp.length == 8))))
+ return -EINVAL;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ if ((var->xres_virtual <= 0) || (var->yres_virtual <= 0))
+ return -EINVAL;
+
+ if (info->fix.smem_len <
+ (var->xres_virtual*var->yres_virtual*(var->bits_per_pixel/8)))
+ return -EINVAL;
+
+ if ((var->xres == 0) || (var->yres == 0))
+ return -EINVAL;
+
+ if ((var->xres > mfd->panel_info.xres) ||
+ (var->yres > mfd->panel_info.yres))
+ return -EINVAL;
+
+ if (var->xoffset > (var->xres_virtual - var->xres))
+ return -EINVAL;
+
+ if (var->yoffset > (var->yres_virtual - var->yres))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int msm_fb_set_par(struct fb_info *info)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ struct fb_var_screeninfo *var = &info->var;
+ int old_imgType;
+ int blank = 0;
+
+ old_imgType = mfd->fb_imgType;
+ switch (var->bits_per_pixel) {
+ case 16:
+ if (var->red.offset == 0)
+ mfd->fb_imgType = MDP_BGR_565;
+ else
+ mfd->fb_imgType = MDP_RGB_565;
+ break;
+
+ case 24:
+ if ((var->transp.offset == 0) && (var->transp.length == 0))
+ mfd->fb_imgType = MDP_RGB_888;
+ else if ((var->transp.offset == 24) &&
+ (var->transp.length == 8)) {
+ mfd->fb_imgType = MDP_ARGB_8888;
+ info->var.bits_per_pixel = 32;
+ }
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ if ((mfd->var_pixclock != var->pixclock) ||
+ (mfd->hw_refresh && ((mfd->fb_imgType != old_imgType) ||
+ (mfd->var_pixclock != var->pixclock) ||
+ (mfd->var_xres != var->xres) ||
+ (mfd->var_yres != var->yres)))) {
+ mfd->var_xres = var->xres;
+ mfd->var_yres = var->yres;
+ mfd->var_pixclock = var->pixclock;
+ blank = 1;
+ }
+
+ if (blank) {
+ msm_fb_blank_sub(FB_BLANK_POWERDOWN, info, mfd->op_enable);
+ msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable);
+ }
+
+ return 0;
+}
+
+static int msm_fb_stop_sw_refresher(struct msm_fb_data_type *mfd)
+{
+ if (mfd->hw_refresh)
+ return -EPERM;
+
+ if (mfd->sw_currently_refreshing) {
+ down(&mfd->sem);
+ mfd->sw_currently_refreshing = FALSE;
+ up(&mfd->sem);
+
+ /* wait until the refresher finishes the last job */
+ wait_for_completion_killable(&mfd->refresher_comp);
+ }
+
+ return 0;
+}
+
+int msm_fb_resume_sw_refresher(struct msm_fb_data_type *mfd)
+{
+ boolean do_refresh;
+
+ if (mfd->hw_refresh)
+ return -EPERM;
+
+ down(&mfd->sem);
+ if ((!mfd->sw_currently_refreshing) && (mfd->sw_refreshing_enable)) {
+ do_refresh = TRUE;
+ mfd->sw_currently_refreshing = TRUE;
+ } else {
+ do_refresh = FALSE;
+ }
+ up(&mfd->sem);
+
+ if (do_refresh)
+ mdp_refresh_screen((unsigned long)mfd);
+
+ return 0;
+}
+
+void mdp_ppp_put_img(struct file *p_src_file, struct file *p_dst_file)
+{
+#ifdef CONFIG_ANDROID_PMEM
+ if (p_src_file)
+ put_pmem_file(p_src_file);
+ if (p_dst_file)
+ put_pmem_file(p_dst_file);
+#endif
+}
+
+int mdp_blit(struct fb_info *info, struct mdp_blit_req *req)
+{
+ int ret;
+ struct file *p_src_file = 0, *p_dst_file = 0;
+ if (unlikely(req->src_rect.h == 0 || req->src_rect.w == 0)) {
+ printk(KERN_ERR "mpd_ppp: src img of zero size!\n");
+ return -EINVAL;
+ }
+ if (unlikely(req->dst_rect.h == 0 || req->dst_rect.w == 0))
+ return 0;
+
+ ret = mdp_ppp_blit(info, req, &p_src_file, &p_dst_file);
+ mdp_ppp_put_img(p_src_file, p_dst_file);
+ return ret;
+}
+
+typedef void (*msm_dma_barrier_function_pointer) (void *, size_t);
+
+static inline void msm_fb_dma_barrier_for_rect(struct fb_info *info,
+ struct mdp_img *img, struct mdp_rect *rect,
+ msm_dma_barrier_function_pointer dma_barrier_fp
+ )
+{
+ /*
+ * Compute the start and end addresses of the rectangles.
+ * NOTE: As currently implemented, the data between
+ * the end of one row and the start of the next is
+ * included in the address range rather than
+ * doing multiple calls for each row.
+ */
+
+ char * const pmem_start = info->screen_base;
+/* int bytes_per_pixel = mdp_get_bytes_per_pixel(img->format);
+ unsigned long start = (unsigned long)pmem_start + img->offset +
+ (img->width * rect->y + rect->x) * bytes_per_pixel;
+ size_t size = ((rect->h - 1) * img->width + rect->w) * bytes_per_pixel;
+ (*dma_barrier_fp) ((void *) start, size);
+*/
+ panic("waaaaah");
+}
+
+static inline void msm_dma_nc_pre(void)
+{
+ dmb();
+}
+static inline void msm_dma_wt_pre(void)
+{
+ dmb();
+}
+static inline void msm_dma_todevice_wb_pre(void *start, size_t size)
+{
+ #warning this
+// dma_cache_pre_ops(start, size, DMA_TO_DEVICE);
+}
+
+static inline void msm_dma_fromdevice_wb_pre(void *start, size_t size)
+{
+ #warning this
+// dma_cache_pre_ops(start, size, DMA_FROM_DEVICE);
+}
+
+static inline void msm_dma_nc_post(void)
+{
+ dmb();
+}
+
+static inline void msm_dma_fromdevice_wt_post(void *start, size_t size)
+{
+ #warning this
+// dma_cache_post_ops(start, size, DMA_FROM_DEVICE);
+}
+
+static inline void msm_dma_todevice_wb_post(void *start, size_t size)
+{
+ #warning this
+// dma_cache_post_ops(start, size, DMA_TO_DEVICE);
+}
+
+static inline void msm_dma_fromdevice_wb_post(void *start, size_t size)
+{
+ #warning this
+// dma_cache_post_ops(start, size, DMA_FROM_DEVICE);
+}
+
+/*
+ * Do the write barriers required to guarantee data is committed to RAM
+ * (from CPU cache or internal buffers) before a DMA operation starts.
+ * NOTE: As currently implemented, the data between
+ * the end of one row and the start of the next is
+ * included in the address range rather than
+ * doing multiple calls for each row.
+*/
+static void msm_fb_ensure_memory_coherency_before_dma(struct fb_info *info,
+ struct mdp_blit_req *req_list,
+ int req_list_count)
+{
+#ifdef CONFIG_ARCH_QSD8X50
+ int i;
+
+ /*
+ * Normally, do the requested barriers for each address
+ * range that corresponds to a rectangle.
+ *
+ * But if at least one write barrier is requested for data
+ * going to or from the device but no address range is
+ * needed for that barrier, then do the barrier, but do it
+ * only once, no matter how many requests there are.
+ */
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ switch (mfd->mdp_fb_page_protection) {
+ default:
+ case MDP_FB_PAGE_PROTECTION_NONCACHED:
+ case MDP_FB_PAGE_PROTECTION_WRITECOMBINE:
+ /*
+ * The following barrier is only done at most once,
+ * since further calls would be redundant.
+ */
+ for (i = 0; i < req_list_count; i++) {
+ if (!(req_list[i].flags
+ & MDP_NO_DMA_BARRIER_START)) {
+ msm_dma_nc_pre();
+ break;
+ }
+ }
+ break;
+
+ case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE:
+ /*
+ * The following barrier is only done at most once,
+ * since further calls would be redundant.
+ */
+ for (i = 0; i < req_list_count; i++) {
+ if (!(req_list[i].flags
+ & MDP_NO_DMA_BARRIER_START)) {
+ msm_dma_wt_pre();
+ break;
+ }
+ }
+ break;
+
+ case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE:
+ case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE:
+ for (i = 0; i < req_list_count; i++) {
+ if (!(req_list[i].flags &
+ MDP_NO_DMA_BARRIER_START)) {
+
+ msm_fb_dma_barrier_for_rect(info,
+ &(req_list[i].src),
+ &(req_list[i].src_rect),
+ msm_dma_todevice_wb_pre
+ );
+
+ msm_fb_dma_barrier_for_rect(info,
+ &(req_list[i].dst),
+ &(req_list[i].dst_rect),
+ msm_dma_todevice_wb_pre
+ );
+ }
+ }
+ break;
+ }
+#else
+ dmb();
+#endif
+}
+
+
+/*
+ * Do the write barriers required to guarantee data will be re-read from RAM by
+ * the CPU after a DMA operation ends.
+ * NOTE: As currently implemented, the data between
+ * the end of one row and the start of the next is
+ * included in the address range rather than
+ * doing multiple calls for each row.
+*/
+static void msm_fb_ensure_memory_coherency_after_dma(struct fb_info *info,
+ struct mdp_blit_req *req_list,
+ int req_list_count)
+{
+#ifdef CONFIG_ARCH_QSD8X50
+ int i;
+
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ switch (mfd->mdp_fb_page_protection) {
+ default:
+ case MDP_FB_PAGE_PROTECTION_NONCACHED:
+ case MDP_FB_PAGE_PROTECTION_WRITECOMBINE:
+ /*
+ * The following barrier is only done at most once,
+ * since further calls would be redundant.
+ */
+ for (i = 0; i < req_list_count; i++) {
+ if (!(req_list[i].flags
+ & MDP_NO_DMA_BARRIER_END)) {
+ msm_dma_nc_post();
+ break;
+ }
+ }
+ break;
+
+ case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE:
+ for (i = 0; i < req_list_count; i++) {
+ if (!(req_list[i].flags &
+ MDP_NO_DMA_BARRIER_END)) {
+
+ msm_fb_dma_barrier_for_rect(info,
+ &(req_list[i].dst),
+ &(req_list[i].dst_rect),
+ msm_dma_fromdevice_wt_post
+ );
+ }
+ }
+ break;
+ case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE:
+ case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE:
+ for (i = 0; i < req_list_count; i++) {
+ if (!(req_list[i].flags &
+ MDP_NO_DMA_BARRIER_END)) {
+
+ msm_fb_dma_barrier_for_rect(info,
+ &(req_list[i].dst),
+ &(req_list[i].dst_rect),
+ msm_dma_fromdevice_wb_post
+ );
+ }
+ }
+ break;
+ }
+#else
+ dmb();
+#endif
+}
+
+#ifdef CONFIG_MDP_PPP_ASYNC_OP
+void msm_fb_ensure_mem_coherency_after_dma(struct fb_info *info,
+ struct mdp_blit_req *req_list, int req_list_count)
+{
+ BUG_ON(!info);
+
+ /*
+ * Ensure that CPU cache and other internal CPU state is
+ * updated to reflect any change in memory modified by MDP blit
+ * DMA.
+ */
+ msm_fb_ensure_memory_coherency_after_dma(info,
+ req_list, req_list_count);
+}
+
+static int msmfb_async_blit(struct fb_info *info, void __user *p)
+{
+ /*
+ * CAUTION: The names of the struct types intentionally *DON'T* match
+ * the names of the variables declared -- they appear to be swapped.
+ * Read the code carefully and you should see that the variable names
+ * make sense.
+ */
+ const int MAX_LIST_WINDOW = 16;
+ struct mdp_blit_req req_list[MAX_LIST_WINDOW];
+ struct mdp_blit_req_list req_list_header;
+
+ int count, i, req_list_count;
+
+ /* Get the count size for the total BLIT request. */
+ if (copy_from_user(&req_list_header, p, sizeof(req_list_header)))
+ return -EFAULT;
+ p += sizeof(req_list_header);
+ count = req_list_header.count;
+ while (count > 0) {
+ /*
+ * Access the requests through a narrow window to decrease copy
+ * overhead and make larger requests accessible to the
+ * coherency management code.
+ * NOTE: The window size is intended to be larger than the
+ * typical request size, but not require more than 2
+ * kbytes of stack storage.
+ */
+ req_list_count = count;
+ if (req_list_count > MAX_LIST_WINDOW)
+ req_list_count = MAX_LIST_WINDOW;
+ if (copy_from_user(&req_list, p,
+ sizeof(struct mdp_blit_req)*req_list_count))
+ return -EFAULT;
+
+ /*
+ * Ensure that any data CPU may have previously written to
+ * internal state (but not yet committed to memory) is
+ * guaranteed to be committed to memory now.
+ */
+ msm_fb_ensure_memory_coherency_before_dma(info,
+ req_list, req_list_count);
+
+ /*
+ * Do the blit DMA, if required -- returning early only if
+ * there is a failure.
+ */
+ for (i = 0; i < req_list_count; i++) {
+ if (!(req_list[i].flags & MDP_NO_BLIT)) {
+ int ret = 0;
+ struct mdp_ppp_djob *job = NULL;
+
+ if (unlikely(req_list[i].src_rect.h == 0 ||
+ req_list[i].src_rect.w == 0)) {
+ MSM_FB_ERR("mpd_ppp: "
+ "src img of zero size!\n");
+ return -EINVAL;
+ }
+
+ if (unlikely(req_list[i].dst_rect.h == 0 ||
+ req_list[i].dst_rect.w == 0))
+ continue;
+
+ /* create a new display job */
+ job = mdp_ppp_new_djob();
+ if (unlikely(!job))
+ return -ENOMEM;
+
+ job->info = info;
+ memcpy(&job->req, &req_list[i],
+ sizeof(struct mdp_blit_req));
+
+ /* Do the actual blit. */
+ ret = mdp_ppp_blit(info, &job->req,
+ &job->p_src_file, &job->p_dst_file);
+
+ /*
+ * Note that early returns don't guarantee
+ * memory coherency.
+ */
+ if (ret || mdp_ppp_get_ret_code()) {
+ mdp_ppp_clear_curr_djob();
+ return ret;
+ }
+ }
+ }
+
+ /* Go to next window of requests. */
+ count -= req_list_count;
+ p += sizeof(struct mdp_blit_req)*req_list_count;
+ }
+ return 0;
+}
+#else
+
+/*
+ * NOTE: The userspace issues blit operations in a sequence, the sequence
+ * start with a operation marked START and ends in an operation marked
+ * END. It is guranteed by the userspace that all the blit operations
+ * between START and END are only within the regions of areas designated
+ * by the START and END operations and that the userspace doesnt modify
+ * those areas. Hence it would be enough to perform barrier/cache operations
+ * only on the START and END operations.
+ */
+static int msmfb_blit(struct fb_info *info, void __user *p)
+{
+ /*
+ * CAUTION: The names of the struct types intentionally *DON'T* match
+ * the names of the variables declared -- they appear to be swapped.
+ * Read the code carefully and you should see that the variable names
+ * make sense.
+ */
+ const int MAX_LIST_WINDOW = 16;
+ struct mdp_blit_req req_list[MAX_LIST_WINDOW];
+ struct mdp_blit_req_list req_list_header;
+
+ int count, i, req_list_count;
+
+ /* Get the count size for the total BLIT request. */
+ if (copy_from_user(&req_list_header, p, sizeof(req_list_header)))
+ return -EFAULT;
+ p += sizeof(req_list_header);
+ count = req_list_header.count;
+ while (count > 0) {
+ /*
+ * Access the requests through a narrow window to decrease copy
+ * overhead and make larger requests accessible to the
+ * coherency management code.
+ * NOTE: The window size is intended to be larger than the
+ * typical request size, but not require more than 2
+ * kbytes of stack storage.
+ */
+ req_list_count = count;
+ if (req_list_count > MAX_LIST_WINDOW)
+ req_list_count = MAX_LIST_WINDOW;
+ if (copy_from_user(&req_list, p,
+ sizeof(struct mdp_blit_req)*req_list_count))
+ return -EFAULT;
+
+ /*
+ * Ensure that any data CPU may have previously written to
+ * internal state (but not yet committed to memory) is
+ * guaranteed to be committed to memory now.
+ */
+ msm_fb_ensure_memory_coherency_before_dma(info,
+ req_list, req_list_count);
+
+ /*
+ * Do the blit DMA, if required -- returning early only if
+ * there is a failure.
+ */
+ for (i = 0; i < req_list_count; i++) {
+ if (!(req_list[i].flags & MDP_NO_BLIT)) {
+ /* Do the actual blit. */
+ int ret = mdp_blit(info, &(req_list[i]));
+
+ /*
+ * Note that early returns don't guarantee
+ * memory coherency.
+ */
+ if (ret)
+ return ret;
+ }
+ }
+
+ /*
+ * Ensure that CPU cache and other internal CPU state is
+ * updated to reflect any change in memory modified by MDP blit
+ * DMA.
+ */
+ msm_fb_ensure_memory_coherency_after_dma(info,
+ req_list,
+ req_list_count);
+
+ /* Go to next window of requests. */
+ count -= req_list_count;
+ p += sizeof(struct mdp_blit_req)*req_list_count;
+ }
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_FB_MSM_OVERLAY
+static int msmfb_overlay_get(struct fb_info *info, void __user *p)
+{
+ struct mdp_overlay req;
+ int ret;
+
+ if (copy_from_user(&req, p, sizeof(req)))
+ return -EFAULT;
+
+ ret = mdp4_overlay_get(info, &req);
+ if (ret) {
+ printk(KERN_ERR "%s: ioctl failed \n",
+ __func__);
+ return ret;
+ }
+ if (copy_to_user(p, &req, sizeof(req))) {
+ printk(KERN_ERR "%s: copy2user failed \n",
+ __func__);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int msmfb_overlay_set(struct fb_info *info, void __user *p)
+{
+ struct mdp_overlay req;
+ int ret;
+
+ if (copy_from_user(&req, p, sizeof(req)))
+ return -EFAULT;
+
+ ret = mdp4_overlay_set(info, &req);
+ if (ret) {
+ printk(KERN_ERR "%s:ioctl failed \n",
+ __func__);
+ return ret;
+ }
+
+ if (copy_to_user(p, &req, sizeof(req))) {
+ printk(KERN_ERR "%s: copy2user failed \n",
+ __func__);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int msmfb_overlay_unset(struct fb_info *info, unsigned long *argp)
+{
+ int ret, ndx;
+
+ ret = copy_from_user(&ndx, argp, sizeof(ndx));
+ if (ret) {
+ printk(KERN_ERR "%s:msmfb_overlay_unset ioctl failed \n",
+ __func__);
+ return ret;
+ }
+
+ return mdp4_overlay_unset(info, ndx);
+}
+
+static int msmfb_overlay_play(struct fb_info *info, unsigned long *argp)
+{
+ int ret;
+ struct msmfb_overlay_data req;
+ struct file *p_src_file = 0;
+
+ ret = copy_from_user(&req, argp, sizeof(req));
+ if (ret) {
+ printk(KERN_ERR "%s:msmfb_overlay_play ioctl failed \n",
+ __func__);
+ return ret;
+ }
+
+ ret = mdp4_overlay_play(info, &req, &p_src_file);
+
+ if (p_src_file)
+ put_pmem_file(p_src_file);
+
+ return ret;
+}
+
+#endif
+
+DECLARE_MUTEX(msm_fb_ioctl_ppp_sem);
+DEFINE_MUTEX(msm_fb_ioctl_lut_sem);
+DEFINE_MUTEX(msm_fb_ioctl_hist_sem);
+
+/* Set color conversion matrix from user space */
+
+#ifndef CONFIG_FB_MSM_MDP40
+static void msmfb_set_color_conv(struct mdp_ccs *p)
+{
+ int i;
+
+ if (p->direction == MDP_CCS_RGB2YUV) {
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ /* RGB->YUV primary forward matrix */
+ for (i = 0; i < MDP_CCS_SIZE; i++)
+ writel(p->ccs[i], MDP_CSC_PFMVn(i));
+
+ #ifdef CONFIG_FB_MSM_MDP31
+ for (i = 0; i < MDP_BV_SIZE; i++)
+ writel(p->bv[i], MDP_CSC_POST_BV2n(i));
+ #endif
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ } else {
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ /* YUV->RGB primary reverse matrix */
+ for (i = 0; i < MDP_CCS_SIZE; i++)
+ writel(p->ccs[i], MDP_CSC_PRMVn(i));
+ for (i = 0; i < MDP_BV_SIZE; i++)
+ writel(p->bv[i], MDP_CSC_PRE_BV1n(i));
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ }
+}
+#endif
+
+
+static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ void __user *argp = (void __user *)arg;
+ struct fb_cursor cursor;
+ struct fb_cmap cmap;
+ struct mdp_histogram hist;
+#ifndef CONFIG_FB_MSM_MDP40
+ struct mdp_ccs ccs_matrix;
+#endif
+ struct mdp_page_protection fb_page_protection;
+ int ret = 0;
+
+ if (!mfd->op_enable)
+ return -EPERM;
+
+ switch (cmd) {
+#ifdef CONFIG_FB_MSM_OVERLAY
+ case MSMFB_OVERLAY_GET:
+ down(&msm_fb_ioctl_ppp_sem);
+ ret = msmfb_overlay_get(info, argp);
+ up(&msm_fb_ioctl_ppp_sem);
+ break;
+ case MSMFB_OVERLAY_SET:
+ down(&msm_fb_ioctl_ppp_sem);
+ ret = msmfb_overlay_set(info, argp);
+ up(&msm_fb_ioctl_ppp_sem);
+ break;
+ case MSMFB_OVERLAY_UNSET:
+ down(&msm_fb_ioctl_ppp_sem);
+ ret = msmfb_overlay_unset(info, argp);
+ up(&msm_fb_ioctl_ppp_sem);
+ break;
+ case MSMFB_OVERLAY_PLAY:
+ down(&msm_fb_ioctl_ppp_sem);
+ ret = msmfb_overlay_play(info, argp);
+ up(&msm_fb_ioctl_ppp_sem);
+ break;
+#endif
+ case MSMFB_BLIT:
+ down(&msm_fb_ioctl_ppp_sem);
+#ifdef CONFIG_MDP_PPP_ASYNC_OP
+ ret = msmfb_async_blit(info, argp);
+ mdp_ppp_wait(); /* Wait for all blits to be finished. */
+#else
+ ret = msmfb_blit(info, argp);
+#endif
+ up(&msm_fb_ioctl_ppp_sem);
+
+ break;
+
+ /* Ioctl for setting ccs matrix from user space */
+ case MSMFB_SET_CCS_MATRIX:
+#ifndef CONFIG_FB_MSM_MDP40
+ ret = copy_from_user(&ccs_matrix, argp, sizeof(ccs_matrix));
+ if (ret) {
+ printk(KERN_ERR
+ "%s:MSMFB_SET_CCS_MATRIX ioctl failed \n",
+ __func__);
+ return ret;
+ }
+
+ down(&msm_fb_ioctl_ppp_sem);
+ if (ccs_matrix.direction == MDP_CCS_RGB2YUV)
+ mdp_ccs_rgb2yuv = ccs_matrix;
+ else
+ mdp_ccs_yuv2rgb = ccs_matrix;
+
+ msmfb_set_color_conv(&ccs_matrix) ;
+ up(&msm_fb_ioctl_ppp_sem);
+#else
+ ret = -EINVAL;
+#endif
+
+ break;
+
+ /* Ioctl for getting ccs matrix to user space */
+ case MSMFB_GET_CCS_MATRIX:
+#ifndef CONFIG_FB_MSM_MDP40
+ ret = copy_from_user(&ccs_matrix, argp, sizeof(ccs_matrix)) ;
+ if (ret) {
+ printk(KERN_ERR
+ "%s:MSMFB_GET_CCS_MATRIX ioctl failed \n",
+ __func__);
+ return ret;
+ }
+
+ down(&msm_fb_ioctl_ppp_sem);
+ if (ccs_matrix.direction == MDP_CCS_RGB2YUV)
+ ccs_matrix = mdp_ccs_rgb2yuv;
+ else
+ ccs_matrix = mdp_ccs_yuv2rgb;
+
+ ret = copy_to_user(argp, &ccs_matrix, sizeof(ccs_matrix));
+
+ if (ret) {
+ printk(KERN_ERR
+ "%s:MSMFB_GET_CCS_MATRIX ioctl failed \n",
+ __func__);
+ return ret ;
+ }
+ up(&msm_fb_ioctl_ppp_sem);
+#else
+ ret = -EINVAL;
+#endif
+
+ break;
+
+#ifdef CONFIG_MDP_PPP_ASYNC_OP
+ case MSMFB_ASYNC_BLIT:
+ down(&msm_fb_ioctl_ppp_sem);
+ ret = msmfb_async_blit(info, argp);
+ up(&msm_fb_ioctl_ppp_sem);
+ break;
+
+ case MSMFB_BLIT_FLUSH:
+ down(&msm_fb_ioctl_ppp_sem);
+ mdp_ppp_wait();
+ up(&msm_fb_ioctl_ppp_sem);
+ break;
+#endif
+
+ case MSMFB_GRP_DISP:
+#ifdef CONFIG_FB_MSM_MDP22
+ {
+ unsigned long grp_id;
+
+ ret = copy_from_user(&grp_id, argp, sizeof(grp_id));
+ if (ret)
+ return ret;
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ writel(grp_id, MDP_FULL_BYPASS_WORD43);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF,
+ FALSE);
+ break;
+ }
+#else
+ return -EFAULT;
+#endif
+ case MSMFB_SUSPEND_SW_REFRESHER:
+ if (!mfd->panel_power_on)
+ return -EPERM;
+
+ mfd->sw_refreshing_enable = FALSE;
+ ret = msm_fb_stop_sw_refresher(mfd);
+ break;
+
+ case MSMFB_RESUME_SW_REFRESHER:
+ if (!mfd->panel_power_on)
+ return -EPERM;
+
+ mfd->sw_refreshing_enable = TRUE;
+ ret = msm_fb_resume_sw_refresher(mfd);
+ break;
+
+ case MSMFB_CURSOR:
+ ret = copy_from_user(&cursor, argp, sizeof(cursor));
+ if (ret)
+ return ret;
+
+ ret = msm_fb_cursor(info, &cursor);
+ break;
+
+ case MSMFB_SET_LUT:
+ ret = copy_from_user(&cmap, argp, sizeof(cmap));
+ if (ret)
+ return ret;
+
+ mutex_lock(&msm_fb_ioctl_lut_sem);
+ ret = msm_fb_set_lut(&cmap, info);
+ mutex_unlock(&msm_fb_ioctl_lut_sem);
+ break;
+
+ case MSMFB_HISTOGRAM:
+ if (!mfd->do_histogram)
+ return -ENODEV;
+
+ ret = copy_from_user(&hist, argp, sizeof(hist));
+ if (ret)
+ return ret;
+
+ mutex_lock(&msm_fb_ioctl_hist_sem);
+ ret = mfd->do_histogram(info, &hist);
+ mutex_unlock(&msm_fb_ioctl_hist_sem);
+ break;
+
+ case MSMFB_GET_PAGE_PROTECTION:
+ fb_page_protection.page_protection
+ = mfd->mdp_fb_page_protection;
+ ret = copy_to_user(argp, &fb_page_protection,
+ sizeof(fb_page_protection));
+ if (ret)
+ return ret;
+ break;
+
+ case MSMFB_SET_PAGE_PROTECTION:
+#ifdef CONFIG_ARCH_QSD8X50
+ ret = copy_from_user(&fb_page_protection, argp,
+ sizeof(fb_page_protection));
+ if (ret)
+ return ret;
+
+ /* Validate the proposed page protection settings. */
+ switch (fb_page_protection.page_protection) {
+ case MDP_FB_PAGE_PROTECTION_NONCACHED:
+ case MDP_FB_PAGE_PROTECTION_WRITECOMBINE:
+ case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE:
+ /* Write-back cache (read allocate) */
+ case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE:
+ /* Write-back cache (write allocate) */
+ case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE:
+ mfd->mdp_fb_page_protection =
+ fb_page_protection.page_protection;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+#else
+ /*
+ * Don't allow caching until 7k DMA cache operations are
+ * available.
+ */
+ ret = -EINVAL;
+#endif
+ break;
+
+ default:
+ MSM_FB_INFO("MDP: unknown ioctl (cmd=%d) received!\n", cmd);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int msm_fb_register_driver(void)
+{
+ return platform_driver_register(&msm_fb_driver);
+}
+
+void msm_fb_add_device(struct platform_device *pdev)
+{
+ struct msm_fb_panel_data *pdata;
+ struct platform_device *this_dev = NULL;
+ struct fb_info *fbi;
+ struct msm_fb_data_type *mfd = NULL;
+ u32 type, id, fb_num;
+
+ if (!pdev)
+ return;
+ id = pdev->id;
+
+ pdata = pdev->dev.platform_data;
+ if (!pdata)
+ return;
+ type = pdata->panel_info.type;
+ fb_num = pdata->panel_info.fb_num;
+
+ if (fb_num <= 0)
+ return;
+
+ if (fbi_list_index >= MAX_FBI_LIST) {
+ printk(KERN_ERR "msm_fb: no more framebuffer info list!\n");
+ return;
+ }
+ /*
+ * alloc panel device data
+ */
+ this_dev = msm_fb_device_alloc(pdata, type, id);
+
+ if (!this_dev) {
+ printk(KERN_ERR
+ "%s: msm_fb_device_alloc failed!\n", __func__);
+ return;
+ }
+
+ /*
+ * alloc framebuffer info + par data
+ */
+ fbi = framebuffer_alloc(sizeof(struct msm_fb_data_type), NULL);
+ if (fbi == NULL) {
+ platform_device_put(this_dev);
+ printk(KERN_ERR "msm_fb: can't alloca framebuffer info data!\n");
+ return;
+ }
+
+ mfd = (struct msm_fb_data_type *)fbi->par;
+ mfd->key = MFD_KEY;
+ mfd->fbi = fbi;
+ mfd->panel.type = type;
+ mfd->panel.id = id;
+ mfd->fb_page = fb_num;
+ mfd->index = fbi_list_index;
+ mfd->mdp_fb_page_protection = MDP_FB_PAGE_PROTECTION_WRITECOMBINE;
+
+ /* link to the latest pdev */
+ mfd->pdev = this_dev;
+
+ mfd_list[mfd_list_index++] = mfd;
+ fbi_list[fbi_list_index++] = fbi;
+
+ /*
+ * set driver data
+ */
+ platform_set_drvdata(this_dev, mfd);
+
+ if (platform_device_add(this_dev)) {
+ printk(KERN_ERR "msm_fb: platform_device_add failed!\n");
+ platform_device_put(this_dev);
+ framebuffer_release(fbi);
+ fbi_list_index--;
+ return;
+ }
+}
+EXPORT_SYMBOL(msm_fb_add_device);
+
+int __init msm_fb_init(void)
+{
+ int rc = -ENODEV;
+
+ if (msm_fb_register_driver())
+ return rc;
+
+#ifdef MSM_FB_ENABLE_DBGFS
+ {
+ struct dentry *root;
+
+ if ((root = msm_fb_get_debugfs_root()) != NULL) {
+ msm_fb_debugfs_file_create(root,
+ "msm_fb_msg_printing_level",
+ (u32 *) &msm_fb_msg_level);
+ msm_fb_debugfs_file_create(root,
+ "mddi_msg_printing_level",
+ (u32 *) &mddi_msg_level);
+ msm_fb_debugfs_file_create(root, "msm_fb_debug_enabled",
+ (u32 *) &msm_fb_debug_enabled);
+ }
+ }
+#endif
+
+ return 0;
+}
+
+module_init(msm_fb_init);
diff --git a/drivers/staging/msm/msm_fb.h b/drivers/staging/msm/msm_fb.h
new file mode 100644
index 0000000..f939138
--- /dev/null
+++ b/drivers/staging/msm/msm_fb.h
@@ -0,0 +1,174 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 Code Aurora 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, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT 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 MSM_FB_H
+#define MSM_FB_H
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include "linux/proc_fs.h"
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <mach/board.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <mach/memory.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/hrtimer.h>
+
+#include <linux/fb.h>
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+
+#include "msm_fb_panel.h"
+#include "mdp.h"
+
+#define MSM_FB_DEFAULT_PAGE_SIZE 2
+#define MFD_KEY 0x11161126
+#define MSM_FB_MAX_DEV_LIST 32
+
+struct disp_info_type_suspend {
+ boolean op_enable;
+ boolean sw_refreshing_enable;
+ boolean panel_power_on;
+};
+
+struct msm_fb_data_type {
+ __u32 key;
+ __u32 index;
+ __u32 ref_cnt;
+ __u32 fb_page;
+
+ panel_id_type panel;
+ struct msm_panel_info panel_info;
+
+ DISP_TARGET dest;
+ struct fb_info *fbi;
+
+ boolean op_enable;
+ uint32 fb_imgType;
+ boolean sw_currently_refreshing;
+ boolean sw_refreshing_enable;
+ boolean hw_refresh;
+
+ MDPIBUF ibuf;
+ boolean ibuf_flushed;
+ struct timer_list refresh_timer;
+ struct completion refresher_comp;
+
+ boolean pan_waiting;
+ struct completion pan_comp;
+
+ /* vsync */
+ boolean use_mdp_vsync;
+ __u32 vsync_gpio;
+ __u32 total_lcd_lines;
+ __u32 total_porch_lines;
+ __u32 lcd_ref_usec_time;
+ __u32 refresh_timer_duration;
+
+ struct hrtimer dma_hrtimer;
+
+ boolean panel_power_on;
+ struct work_struct dma_update_worker;
+ struct semaphore sem;
+
+ struct timer_list vsync_resync_timer;
+ boolean vsync_handler_pending;
+ struct work_struct vsync_resync_worker;
+
+ ktime_t last_vsync_timetick;
+
+ __u32 *vsync_width_boundary;
+
+ unsigned int pmem_id;
+ struct disp_info_type_suspend suspend;
+
+ __u32 channel_irq;
+
+ struct mdp_dma_data *dma;
+ void (*dma_fnc) (struct msm_fb_data_type *mfd);
+ int (*cursor_update) (struct fb_info *info,
+ struct fb_cursor *cursor);
+ int (*lut_update) (struct fb_info *info,
+ struct fb_cmap *cmap);
+ int (*do_histogram) (struct fb_info *info,
+ struct mdp_histogram *hist);
+ void *cursor_buf;
+ void *cursor_buf_phys;
+
+ void *cmd_port;
+ void *data_port;
+ void *data_port_phys;
+
+ __u32 bl_level;
+
+ struct platform_device *pdev;
+
+ __u32 var_xres;
+ __u32 var_yres;
+ __u32 var_pixclock;
+
+#ifdef MSM_FB_ENABLE_DBGFS
+ struct dentry *sub_dir;
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+ struct early_suspend mddi_early_suspend;
+ struct early_suspend mddi_ext_early_suspend;
+#endif
+ u32 mdp_fb_page_protection;
+ int allow_set_offset;
+};
+
+struct dentry *msm_fb_get_debugfs_root(void);
+void msm_fb_debugfs_file_create(struct dentry *root, const char *name,
+ u32 *var);
+void msm_fb_set_backlight(struct msm_fb_data_type *mfd, __u32 bkl_lvl,
+ u32 save);
+
+void msm_fb_add_device(struct platform_device *pdev);
+
+int msm_fb_detect_client(const char *name);
+
+#ifdef CONFIG_FB_BACKLIGHT
+void msm_fb_config_backlight(struct msm_fb_data_type *mfd);
+#endif
+
+#endif /* MSM_FB_H */
diff --git a/drivers/staging/msm/msm_fb_bl.c b/drivers/staging/msm/msm_fb_bl.c
new file mode 100644
index 0000000..033fc94
--- /dev/null
+++ b/drivers/staging/msm/msm_fb_bl.c
@@ -0,0 +1,79 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include <linux/string.h>
+#include <linux/version.h>
+#include <linux/backlight.h>
+
+#include "msm_fb.h"
+
+static int msm_fb_bl_get_brightness(struct backlight_device *pbd)
+{
+ return pbd->props.brightness;
+}
+
+static int msm_fb_bl_update_status(struct backlight_device *pbd)
+{
+ struct msm_fb_data_type *mfd = bl_get_data(pbd);
+ __u32 bl_lvl;
+
+ bl_lvl = pbd->props.brightness;
+ bl_lvl = mfd->fbi->bl_curve[bl_lvl];
+ msm_fb_set_backlight(mfd, bl_lvl, 1);
+ return 0;
+}
+
+static struct backlight_ops msm_fb_bl_ops = {
+ .get_brightness = msm_fb_bl_get_brightness,
+ .update_status = msm_fb_bl_update_status,
+};
+
+void msm_fb_config_backlight(struct msm_fb_data_type *mfd)
+{
+ struct msm_fb_panel_data *pdata;
+ struct backlight_device *pbd;
+ struct fb_info *fbi;
+ char name[16];
+
+ fbi = mfd->fbi;
+ pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+
+ if ((pdata) && (pdata->set_backlight)) {
+ snprintf(name, sizeof(name), "msmfb_bl%d", mfd->index);
+ pbd =
+ backlight_device_register(name, fbi->dev, mfd,
+ &msm_fb_bl_ops);
+ if (!IS_ERR(pbd)) {
+ fbi->bl_dev = pbd;
+ fb_bl_default_curve(fbi,
+ 0,
+ mfd->panel_info.bl_min,
+ mfd->panel_info.bl_max);
+ pbd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+ pbd->props.brightness = FB_BACKLIGHT_LEVELS - 1;
+ backlight_update_status(pbd);
+ } else {
+ fbi->bl_dev = NULL;
+ printk(KERN_ERR "msm_fb: backlight_device_register failed!\n");
+ }
+ }
+}
diff --git a/drivers/staging/msm/msm_fb_def.h b/drivers/staging/msm/msm_fb_def.h
new file mode 100644
index 0000000..6de4409
--- /dev/null
+++ b/drivers/staging/msm/msm_fb_def.h
@@ -0,0 +1,201 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 Code Aurora 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, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT 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 MSM_FB_DEF_H
+#define MSM_FB_DEF_H
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include "msm_mdp.h"
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+#include <linux/string.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+#include <linux/vmalloc.h>
+#include <linux/debugfs.h>
+#include <linux/console.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include "linux/proc_fs.h"
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <linux/fb.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/platform_device.h>
+
+typedef s64 int64;
+typedef s32 int32;
+typedef s16 int16;
+typedef s8 int8;
+
+typedef u64 uint64;
+typedef u32 uint32;
+typedef u16 uint16;
+typedef u8 uint8;
+
+typedef s32 int4;
+typedef s16 int2;
+typedef s8 int1;
+
+typedef u32 uint4;
+typedef u16 uint2;
+typedef u8 uint1;
+
+typedef u32 dword;
+typedef u16 word;
+typedef u8 byte;
+
+typedef unsigned int boolean;
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define MSM_FB_ENABLE_DBGFS
+#define FEATURE_MDDI
+
+#define outp32(addr, val) writel(val, addr)
+#define outp16(addr, val) writew(val, addr)
+#define outp8(addr, val) writeb(val, addr)
+#define outp(addr, val) outp32(addr, val)
+
+#ifndef MAX
+#define MAX( x, y ) (((x) > (y)) ? (x) : (y))
+#endif
+
+#ifndef MIN
+#define MIN( x, y ) (((x) < (y)) ? (x) : (y))
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+#define inp32(addr) readl(addr)
+#define inp16(addr) readw(addr)
+#define inp8(addr) readb(addr)
+#define inp(addr) inp32(addr)
+
+#define inpw(port) readw(port)
+#define outpw(port, val) writew(val, port)
+#define inpdw(port) readl(port)
+#define outpdw(port, val) writel(val, port)
+
+
+#define clk_busy_wait(x) msleep_interruptible((x)/1000)
+
+#define memory_barrier()
+
+#define assert(expr) \
+ if(!(expr)) { \
+ printk(KERN_ERR "msm_fb: assertion failed! %s,%s,%s,line=%d\n",\
+ #expr, __FILE__, __func__, __LINE__); \
+ }
+
+#define ASSERT(x) assert(x)
+
+#define DISP_EBI2_LOCAL_DEFINE
+#ifdef DISP_EBI2_LOCAL_DEFINE
+#define LCD_PRIM_BASE_PHYS 0x98000000
+#define LCD_SECD_BASE_PHYS 0x9c000000
+#define EBI2_PRIM_LCD_RS_PIN 0x20000
+#define EBI2_SECD_LCD_RS_PIN 0x20000
+
+#define EBI2_PRIM_LCD_CLR 0xC0
+#define EBI2_PRIM_LCD_SEL 0x40
+
+#define EBI2_SECD_LCD_CLR 0x300
+#define EBI2_SECD_LCD_SEL 0x100
+#endif
+
+extern u32 msm_fb_msg_level;
+
+/*
+ * Message printing priorities:
+ * LEVEL 0 KERN_EMERG (highest priority)
+ * LEVEL 1 KERN_ALERT
+ * LEVEL 2 KERN_CRIT
+ * LEVEL 3 KERN_ERR
+ * LEVEL 4 KERN_WARNING
+ * LEVEL 5 KERN_NOTICE
+ * LEVEL 6 KERN_INFO
+ * LEVEL 7 KERN_DEBUG (Lowest priority)
+ */
+#define MSM_FB_EMERG(msg, ...) \
+ if (msm_fb_msg_level > 0) \
+ printk(KERN_EMERG msg, ## __VA_ARGS__);
+#define MSM_FB_ALERT(msg, ...) \
+ if (msm_fb_msg_level > 1) \
+ printk(KERN_ALERT msg, ## __VA_ARGS__);
+#define MSM_FB_CRIT(msg, ...) \
+ if (msm_fb_msg_level > 2) \
+ printk(KERN_CRIT msg, ## __VA_ARGS__);
+#define MSM_FB_ERR(msg, ...) \
+ if (msm_fb_msg_level > 3) \
+ printk(KERN_ERR msg, ## __VA_ARGS__);
+#define MSM_FB_WARNING(msg, ...) \
+ if (msm_fb_msg_level > 4) \
+ printk(KERN_WARNING msg, ## __VA_ARGS__);
+#define MSM_FB_NOTICE(msg, ...) \
+ if (msm_fb_msg_level > 5) \
+ printk(KERN_NOTICE msg, ## __VA_ARGS__);
+#define MSM_FB_INFO(msg, ...) \
+ if (msm_fb_msg_level > 6) \
+ printk(KERN_INFO msg, ## __VA_ARGS__);
+#define MSM_FB_DEBUG(msg, ...) \
+ if (msm_fb_msg_level > 7) \
+ printk(KERN_DEBUG msg, ## __VA_ARGS__);
+
+#ifdef MSM_FB_C
+unsigned char *msm_mdp_base;
+unsigned char *msm_pmdh_base;
+unsigned char *msm_emdh_base;
+#else
+extern unsigned char *msm_mdp_base;
+extern unsigned char *msm_pmdh_base;
+extern unsigned char *msm_emdh_base;
+#endif
+
+#endif /* MSM_FB_DEF_H */
diff --git a/drivers/staging/msm/msm_fb_panel.c b/drivers/staging/msm/msm_fb_panel.c
new file mode 100644
index 0000000..b17a239
--- /dev/null
+++ b/drivers/staging/msm/msm_fb_panel.c
@@ -0,0 +1,136 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+#include <linux/string.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+#include <linux/vmalloc.h>
+#include <linux/debugfs.h>
+
+#include "msm_fb_panel.h"
+
+int panel_next_on(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct msm_fb_panel_data *pdata;
+ struct msm_fb_panel_data *next_pdata;
+ struct platform_device *next_pdev;
+
+ pdata = (struct msm_fb_panel_data *)pdev->dev.platform_data;
+
+ if (pdata) {
+ next_pdev = pdata->next;
+ if (next_pdev) {
+ next_pdata =
+ (struct msm_fb_panel_data *)next_pdev->dev.
+ platform_data;
+ if ((next_pdata) && (next_pdata->on))
+ ret = next_pdata->on(next_pdev);
+ }
+ }
+
+ return ret;
+}
+
+int panel_next_off(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct msm_fb_panel_data *pdata;
+ struct msm_fb_panel_data *next_pdata;
+ struct platform_device *next_pdev;
+
+ pdata = (struct msm_fb_panel_data *)pdev->dev.platform_data;
+
+ if (pdata) {
+ next_pdev = pdata->next;
+ if (next_pdev) {
+ next_pdata =
+ (struct msm_fb_panel_data *)next_pdev->dev.
+ platform_data;
+ if ((next_pdata) && (next_pdata->on))
+ ret = next_pdata->off(next_pdev);
+ }
+ }
+
+ return ret;
+}
+
+struct platform_device *msm_fb_device_alloc(struct msm_fb_panel_data *pdata,
+ u32 type, u32 id)
+{
+ struct platform_device *this_dev = NULL;
+ char dev_name[16];
+
+ switch (type) {
+ case EBI2_PANEL:
+ snprintf(dev_name, sizeof(dev_name), "ebi2_lcd");
+ break;
+
+ case MDDI_PANEL:
+ snprintf(dev_name, sizeof(dev_name), "mddi");
+ break;
+
+ case EXT_MDDI_PANEL:
+ snprintf(dev_name, sizeof(dev_name), "mddi_ext");
+ break;
+
+ case TV_PANEL:
+ snprintf(dev_name, sizeof(dev_name), "tvenc");
+ break;
+
+ case HDMI_PANEL:
+ case LCDC_PANEL:
+ snprintf(dev_name, sizeof(dev_name), "lcdc");
+ break;
+
+ default:
+ return NULL;
+ }
+
+ if (pdata != NULL)
+ pdata->next = NULL;
+ else
+ return NULL;
+
+ this_dev =
+ platform_device_alloc(dev_name, ((u32) type << 16) | (u32) id);
+
+ if (this_dev) {
+ if (platform_device_add_data
+ (this_dev, pdata, sizeof(struct msm_fb_panel_data))) {
+ printk
+ ("msm_fb_device_alloc: platform_device_add_data failed!\n");
+ platform_device_put(this_dev);
+ return NULL;
+ }
+ }
+
+ return this_dev;
+}
diff --git a/drivers/staging/msm/msm_fb_panel.h b/drivers/staging/msm/msm_fb_panel.h
new file mode 100644
index 0000000..ab45831
--- /dev/null
+++ b/drivers/staging/msm/msm_fb_panel.h
@@ -0,0 +1,145 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 Code Aurora 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, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT 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 MSM_FB_PANEL_H
+#define MSM_FB_PANEL_H
+
+#include "msm_fb_def.h"
+
+struct msm_fb_data_type;
+
+typedef void (*msm_fb_vsync_handler_type) (void *arg);
+
+/* panel id type */
+typedef struct panel_id_s {
+ uint16 id;
+ uint16 type;
+} panel_id_type;
+
+/* panel type list */
+#define NO_PANEL 0xffff /* No Panel */
+#define MDDI_PANEL 1 /* MDDI */
+#define EBI2_PANEL 2 /* EBI2 */
+#define LCDC_PANEL 3 /* internal LCDC type */
+#define EXT_MDDI_PANEL 4 /* Ext.MDDI */
+#define TV_PANEL 5 /* TV */
+#define HDMI_PANEL 6 /* HDMI TV */
+
+/* panel class */
+typedef enum {
+ DISPLAY_LCD = 0, /* lcd = ebi2/mddi */
+ DISPLAY_LCDC, /* lcdc */
+ DISPLAY_TV, /* TV Out */
+ DISPLAY_EXT_MDDI, /* External MDDI */
+} DISP_TARGET;
+
+/* panel device locaiton */
+typedef enum {
+ DISPLAY_1 = 0, /* attached as first device */
+ DISPLAY_2, /* attached on second device */
+ MAX_PHYS_TARGET_NUM,
+} DISP_TARGET_PHYS;
+
+/* panel info type */
+struct lcd_panel_info {
+ __u32 vsync_enable;
+ __u32 refx100;
+ __u32 v_back_porch;
+ __u32 v_front_porch;
+ __u32 v_pulse_width;
+ __u32 hw_vsync_mode;
+ __u32 vsync_notifier_period;
+};
+
+struct lcdc_panel_info {
+ __u32 h_back_porch;
+ __u32 h_front_porch;
+ __u32 h_pulse_width;
+ __u32 v_back_porch;
+ __u32 v_front_porch;
+ __u32 v_pulse_width;
+ __u32 border_clr;
+ __u32 underflow_clr;
+ __u32 hsync_skew;
+};
+
+struct mddi_panel_info {
+ __u32 vdopkt;
+};
+
+struct msm_panel_info {
+ __u32 xres;
+ __u32 yres;
+ __u32 bpp;
+ __u32 type;
+ __u32 wait_cycle;
+ DISP_TARGET_PHYS pdest;
+ __u32 bl_max;
+ __u32 bl_min;
+ __u32 fb_num;
+ __u32 clk_rate;
+ __u32 clk_min;
+ __u32 clk_max;
+ __u32 frame_count;
+
+ union {
+ struct mddi_panel_info mddi;
+ };
+
+ union {
+ struct lcd_panel_info lcd;
+ struct lcdc_panel_info lcdc;
+ };
+};
+
+struct msm_fb_panel_data {
+ struct msm_panel_info panel_info;
+ void (*set_rect) (int x, int y, int xres, int yres);
+ void (*set_vsync_notifier) (msm_fb_vsync_handler_type, void *arg);
+ void (*set_backlight) (struct msm_fb_data_type *);
+
+ /* function entry chain */
+ int (*on) (struct platform_device *pdev);
+ int (*off) (struct platform_device *pdev);
+ struct platform_device *next;
+};
+
+/*===========================================================================
+ FUNCTIONS PROTOTYPES
+============================================================================*/
+struct platform_device *msm_fb_device_alloc(struct msm_fb_panel_data *pdata,
+ u32 type, u32 id);
+int panel_next_on(struct platform_device *pdev);
+int panel_next_off(struct platform_device *pdev);
+
+int lcdc_device_register(struct msm_panel_info *pinfo);
+
+int mddi_toshiba_device_register(struct msm_panel_info *pinfo,
+ u32 channel, u32 panel);
+
+#endif /* MSM_FB_PANEL_H */
diff --git a/drivers/staging/msm/msm_mdp.h b/drivers/staging/msm/msm_mdp.h
new file mode 100644
index 0000000..2d5323f
--- /dev/null
+++ b/drivers/staging/msm/msm_mdp.h
@@ -0,0 +1,245 @@
+/* include/linux/msm_mdp.h
+ *
+ * Copyright (C) 2007 Google Incorporated
+ * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * 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 _MSM_MDP_H_
+#define _MSM_MDP_H_
+
+#include <linux/types.h>
+#include <linux/fb.h>
+
+#define MSMFB_IOCTL_MAGIC 'm'
+#define MSMFB_GRP_DISP _IOW(MSMFB_IOCTL_MAGIC, 1, unsigned int)
+#define MSMFB_BLIT _IOW(MSMFB_IOCTL_MAGIC, 2, unsigned int)
+#define MSMFB_SUSPEND_SW_REFRESHER _IOW(MSMFB_IOCTL_MAGIC, 128, unsigned int)
+#define MSMFB_RESUME_SW_REFRESHER _IOW(MSMFB_IOCTL_MAGIC, 129, unsigned int)
+#define MSMFB_CURSOR _IOW(MSMFB_IOCTL_MAGIC, 130, struct fb_cursor)
+#define MSMFB_SET_LUT _IOW(MSMFB_IOCTL_MAGIC, 131, struct fb_cmap)
+#define MSMFB_HISTOGRAM _IOWR(MSMFB_IOCTL_MAGIC, 132, struct mdp_histogram)
+/* new ioctls's for set/get ccs matrix */
+#define MSMFB_GET_CCS_MATRIX _IOWR(MSMFB_IOCTL_MAGIC, 133, struct mdp_ccs)
+#define MSMFB_SET_CCS_MATRIX _IOW(MSMFB_IOCTL_MAGIC, 134, struct mdp_ccs)
+#define MSMFB_OVERLAY_SET _IOWR(MSMFB_IOCTL_MAGIC, 135, \
+ struct mdp_overlay)
+#define MSMFB_OVERLAY_UNSET _IOW(MSMFB_IOCTL_MAGIC, 136, unsigned int)
+#define MSMFB_OVERLAY_PLAY _IOW(MSMFB_IOCTL_MAGIC, 137, \
+ struct msmfb_overlay_data)
+#define MSMFB_GET_PAGE_PROTECTION _IOR(MSMFB_IOCTL_MAGIC, 138, \
+ struct mdp_page_protection)
+#define MSMFB_SET_PAGE_PROTECTION _IOW(MSMFB_IOCTL_MAGIC, 139, \
+ struct mdp_page_protection)
+#define MSMFB_OVERLAY_GET _IOR(MSMFB_IOCTL_MAGIC, 140, \
+ struct mdp_overlay)
+
+/* new ioctls for async MDP ops */
+#define MSMFB_ASYNC_BLIT _IOW(MSMFB_IOCTL_MAGIC, 141, unsigned int)
+#define MSMFB_BLIT_FLUSH _IOR(MSMFB_IOCTL_MAGIC, 142, unsigned int)
+
+#define MDP_IMGTYPE2_START 0x10000
+
+enum {
+ MDP_RGB_565, /* RGB 565 planer */
+ MDP_XRGB_8888, /* RGB 888 padded */
+ MDP_Y_CBCR_H2V2, /* Y and CbCr, pseudo planer w/ Cb is in MSB */
+ MDP_ARGB_8888, /* ARGB 888 */
+ MDP_RGB_888, /* RGB 888 planer */
+ MDP_Y_CRCB_H2V2, /* Y and CrCb, pseudo planer w/ Cr is in MSB */
+ MDP_YCRYCB_H2V1, /* YCrYCb interleave */
+ MDP_Y_CRCB_H2V1, /* Y and CrCb, pseduo planer w/ Cr is in MSB */
+ MDP_Y_CBCR_H2V1, /* Y and CrCb, pseduo planer w/ Cr is in MSB */
+ MDP_RGBA_8888, /* ARGB 888 */
+ MDP_BGRA_8888, /* ABGR 888 */
+ MDP_Y_CRCB_H2V2_TILE, /* Y and CrCb, pseudo planer tile */
+ MDP_Y_CBCR_H2V2_TILE, /* Y and CbCr, pseudo planer tile */
+ MDP_IMGTYPE_LIMIT,
+ MDP_BGR_565 = MDP_IMGTYPE2_START, /* BGR 565 planer */
+ MDP_FB_FORMAT, /* framebuffer format */
+ MDP_IMGTYPE_LIMIT2 /* Non valid image type after this enum */
+};
+
+enum {
+ PMEM_IMG,
+ FB_IMG,
+};
+
+/* mdp_blit_req flag values */
+#define MDP_ROT_NOP 0
+#define MDP_FLIP_LR 0x1
+#define MDP_FLIP_UD 0x2
+#define MDP_ROT_90 0x4
+#define MDP_ROT_180 (MDP_FLIP_UD|MDP_FLIP_LR)
+#define MDP_ROT_270 (MDP_ROT_90|MDP_FLIP_UD|MDP_FLIP_LR)
+#define MDP_DITHER 0x8
+#define MDP_BLUR 0x10
+#define MDP_BLEND_FG_PREMULT 0x20000
+
+#define MDP_DEINTERLACE 0x80000000
+#define MDP_SHARPENING 0x40000000
+
+#define MDP_NO_DMA_BARRIER_START 0x20000000
+#define MDP_NO_DMA_BARRIER_END 0x10000000
+#define MDP_NO_BLIT 0x08000000
+#define MDP_BLIT_WITH_DMA_BARRIERS 0x000
+#define MDP_BLIT_WITH_NO_DMA_BARRIERS \
+ (MDP_NO_DMA_BARRIER_START | MDP_NO_DMA_BARRIER_END)
+#define MDP_TRANSP_NOP 0xffffffff
+#define MDP_ALPHA_NOP 0xff
+
+#define MDP_BLIT_SRC_GEM 0x02000000 /* set for GEM, clear for PMEM */
+#define MDP_BLIT_DST_GEM 0x01000000 /* set for GEM, clear for PMEM */
+
+#define MDP_FB_PAGE_PROTECTION_NONCACHED (0)
+#define MDP_FB_PAGE_PROTECTION_WRITECOMBINE (1)
+#define MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE (2)
+#define MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE (3)
+#define MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE (4)
+/* Sentinel: Don't use! */
+#define MDP_FB_PAGE_PROTECTION_INVALID (5)
+/* Count of the number of MDP_FB_PAGE_PROTECTION_... values. */
+#define MDP_NUM_FB_PAGE_PROTECTION_VALUES (5)
+
+struct mdp_rect {
+ uint32_t x;
+ uint32_t y;
+ uint32_t w;
+ uint32_t h;
+};
+
+struct mdp_img {
+ uint32_t width;
+ uint32_t height;
+ uint32_t format;
+ uint32_t offset;
+ int memory_id; /* the file descriptor */
+ uint32_t priv;
+};
+
+/*
+ * {3x3} + {3} ccs matrix
+ */
+
+#define MDP_CCS_RGB2YUV 0
+#define MDP_CCS_YUV2RGB 1
+
+#define MDP_CCS_SIZE 9
+#define MDP_BV_SIZE 3
+
+struct mdp_ccs {
+ int direction; /* MDP_CCS_RGB2YUV or YUV2RGB */
+ uint16_t ccs[MDP_CCS_SIZE]; /* 3x3 color coefficients */
+ uint16_t bv[MDP_BV_SIZE]; /* 1x3 bias vector */
+};
+
+/* The version of the mdp_blit_req structure so that
+ * user applications can selectively decide which functionality
+ * to include
+ */
+
+#define MDP_BLIT_REQ_VERSION 2
+
+struct mdp_blit_req {
+ struct mdp_img src;
+ struct mdp_img dst;
+ struct mdp_rect src_rect;
+ struct mdp_rect dst_rect;
+ uint32_t alpha;
+ uint32_t transp_mask;
+ uint32_t flags;
+ int sharpening_strength; /* -127 <--> 127, default 64 */
+};
+
+struct mdp_blit_req_list {
+ uint32_t count;
+ struct mdp_blit_req req[];
+};
+
+struct msmfb_data {
+ uint32_t offset;
+ int memory_id;
+ int id;
+};
+
+#define MSMFB_NEW_REQUEST -1
+
+struct msmfb_overlay_data {
+ uint32_t id;
+ struct msmfb_data data;
+};
+
+struct msmfb_img {
+ uint32_t width;
+ uint32_t height;
+ uint32_t format;
+};
+
+struct mdp_overlay {
+ struct msmfb_img src;
+ struct mdp_rect src_rect;
+ struct mdp_rect dst_rect;
+ uint32_t z_order; /* stage number */
+ uint32_t is_fg; /* control alpha & transp */
+ uint32_t alpha;
+ uint32_t transp_mask;
+ uint32_t flags;
+ uint32_t id;
+ uint32_t user_data[8];
+};
+
+struct mdp_histogram {
+ uint32_t frame_cnt;
+ uint32_t bin_cnt;
+ uint32_t *r;
+ uint32_t *g;
+ uint32_t *b;
+};
+
+struct mdp_page_protection {
+ uint32_t page_protection;
+};
+
+
+struct msm_panel_common_pdata {
+ int gpio;
+ int (*backlight_level)(int level, int max, int min);
+ int (*pmic_backlight)(int level);
+ int (*panel_num)(void);
+ void (*panel_config_gpio)(int);
+ int *gpio_num;
+};
+
+struct lcdc_platform_data {
+ int (*lcdc_gpio_config)(int on);
+ void (*lcdc_power_save)(int);
+};
+
+struct tvenc_platform_data {
+ int (*pm_vid_en)(int on);
+};
+
+struct mddi_platform_data {
+ void (*mddi_power_save)(int on);
+ int (*mddi_sel_clk)(u32 *clk_rate);
+};
+
+struct msm_fb_platform_data {
+ int (*detect_client)(const char *name);
+ int mddi_prescan;
+ int (*allow_set_offset)(void);
+};
+
+struct msm_hdmi_platform_data {
+ int irq;
+ int (*cable_detect)(int insert);
+};
+
+#endif /*_MSM_MDP_H_*/
diff --git a/drivers/staging/msm/staging-devices.c b/drivers/staging/msm/staging-devices.c
new file mode 100644
index 0000000..0f8ec3e
--- /dev/null
+++ b/drivers/staging/msm/staging-devices.c
@@ -0,0 +1,323 @@
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/bootmem.h>
+#include <linux/delay.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+
+#include <mach/board.h>
+#include <mach/irqs.h>
+#include <mach/sirc.h>
+#include <mach/gpio.h>
+
+#include "msm_mdp.h"
+#include "memory_ll.h"
+//#include "android_pmem.h"
+#include <mach/board.h>
+
+#ifdef CONFIG_MSM_SOC_REV_A
+#define MSM_SMI_BASE 0xE0000000
+#else
+#define MSM_SMI_BASE 0x00000000
+#endif
+
+
+#define TOUCHPAD_SUSPEND 34
+#define TOUCHPAD_IRQ 38
+
+#define MSM_PMEM_MDP_SIZE 0x1591000
+
+#ifdef CONFIG_MSM_SOC_REV_A
+#define SMEM_SPINLOCK_I2C "D:I2C02000021"
+#else
+#define SMEM_SPINLOCK_I2C "S:6"
+#endif
+
+#define MSM_PMEM_ADSP_SIZE 0x1C00000
+
+#define MSM_FB_SIZE 0x500000
+#define MSM_FB_SIZE_ST15 0x800000
+#define MSM_AUDIO_SIZE 0x80000
+#define MSM_GPU_PHYS_SIZE SZ_2M
+
+#ifdef CONFIG_MSM_SOC_REV_A
+#define MSM_SMI_BASE 0xE0000000
+#else
+#define MSM_SMI_BASE 0x00000000
+#endif
+
+#define MSM_SHARED_RAM_PHYS (MSM_SMI_BASE + 0x00100000)
+
+#define MSM_PMEM_SMI_BASE (MSM_SMI_BASE + 0x02B00000)
+#define MSM_PMEM_SMI_SIZE 0x01500000
+
+#define MSM_FB_BASE MSM_PMEM_SMI_BASE
+#define MSM_GPU_PHYS_BASE (MSM_FB_BASE + MSM_FB_SIZE)
+#define MSM_PMEM_SMIPOOL_BASE (MSM_GPU_PHYS_BASE + MSM_GPU_PHYS_SIZE)
+#define MSM_PMEM_SMIPOOL_SIZE (MSM_PMEM_SMI_SIZE - MSM_FB_SIZE \
+ - MSM_GPU_PHYS_SIZE)
+
+#if defined(CONFIG_FB_MSM_MDP40)
+#define MDP_BASE 0xA3F00000
+#define PMDH_BASE 0xAD600000
+#define EMDH_BASE 0xAD700000
+#define TVENC_BASE 0xAD400000
+#else
+#define MDP_BASE 0xAA200000
+#define PMDH_BASE 0xAA600000
+#define EMDH_BASE 0xAA700000
+#define TVENC_BASE 0xAA400000
+#endif
+
+#define PMEM_KERNEL_EBI1_SIZE (CONFIG_PMEM_KERNEL_SIZE * 1024 * 1024)
+
+static struct resource msm_fb_resources[] = {
+ {
+ .flags = IORESOURCE_DMA,
+ }
+};
+
+static struct resource msm_mdp_resources[] = {
+ {
+ .name = "mdp",
+ .start = MDP_BASE,
+ .end = MDP_BASE + 0x000F0000 - 1,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device msm_mdp_device = {
+ .name = "mdp",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(msm_mdp_resources),
+ .resource = msm_mdp_resources,
+};
+
+static struct platform_device msm_lcdc_device = {
+ .name = "lcdc",
+ .id = 0,
+};
+
+static int msm_fb_detect_panel(const char *name)
+{
+ int ret = -EPERM;
+
+ if (machine_is_qsd8x50_ffa() || machine_is_qsd8x50a_ffa()) {
+ if (!strncmp(name, "mddi_toshiba_wvga_pt", 20))
+ ret = 0;
+ else
+ ret = -ENODEV;
+ } else if ((machine_is_qsd8x50_surf() || machine_is_qsd8x50a_surf())
+ && !strcmp(name, "lcdc_external"))
+ ret = 0;
+ else if (0 /*machine_is_qsd8x50_grapefruit() */) {
+ if (!strcmp(name, "lcdc_grapefruit_vga"))
+ ret = 0;
+ else
+ ret = -ENODEV;
+ } else if (machine_is_qsd8x50_st1()) {
+ if (!strcmp(name, "lcdc_st1_wxga"))
+ ret = 0;
+ else
+ ret = -ENODEV;
+ } else if (machine_is_qsd8x50a_st1_5()) {
+ if (!strcmp(name, "lcdc_st15") ||
+ !strcmp(name, "hdmi_sii9022"))
+ ret = 0;
+ else
+ ret = -ENODEV;
+ }
+
+ return ret;
+}
+
+/* Only allow a small subset of machines to set the offset via
+ FB PAN_DISPLAY */
+
+static int msm_fb_allow_set_offset(void)
+{
+ return (machine_is_qsd8x50_st1() ||
+ machine_is_qsd8x50a_st1_5()) ? 1 : 0;
+}
+
+
+static struct msm_fb_platform_data msm_fb_pdata = {
+ .detect_client = msm_fb_detect_panel,
+ .allow_set_offset = msm_fb_allow_set_offset,
+};
+
+static struct platform_device msm_fb_device = {
+ .name = "msm_fb",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(msm_fb_resources),
+ .resource = msm_fb_resources,
+ .dev = {
+ .platform_data = &msm_fb_pdata,
+ }
+};
+
+static void __init qsd8x50_allocate_memory_regions(void)
+{
+ void *addr;
+ unsigned long size;
+ if (machine_is_qsd8x50a_st1_5())
+ size = MSM_FB_SIZE_ST15;
+ else
+ size = MSM_FB_SIZE;
+
+ addr = alloc_bootmem(size); // (void *)MSM_FB_BASE;
+ if (!addr)
+ printk("Failed to allocate bootmem for framebuffer\n");
+
+
+ msm_fb_resources[0].start = __pa(addr);
+ msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1;
+ pr_info(KERN_ERR "using %lu bytes of SMI at %lx physical for fb\n",
+ size, (unsigned long)addr);
+}
+
+static int msm_fb_lcdc_gpio_config(int on)
+{
+// return 0;
+ if (machine_is_qsd8x50_st1()) {
+ if (on) {
+ gpio_set_value(32, 1);
+ mdelay(100);
+ gpio_set_value(20, 1);
+ gpio_set_value(17, 1);
+ gpio_set_value(19, 1);
+ } else {
+ gpio_set_value(17, 0);
+ gpio_set_value(19, 0);
+ gpio_set_value(20, 0);
+ mdelay(100);
+ gpio_set_value(32, 0);
+ }
+ } else if (machine_is_qsd8x50a_st1_5()) {
+ if (on) {
+ gpio_set_value(17, 1);
+ gpio_set_value(19, 1);
+ gpio_set_value(20, 1);
+ gpio_set_value(22, 0);
+ gpio_set_value(32, 1);
+ gpio_set_value(155, 1);
+ //st15_hdmi_power(1);
+ gpio_set_value(22, 1);
+
+ } else {
+ gpio_set_value(17, 0);
+ gpio_set_value(19, 0);
+ gpio_set_value(22, 0);
+ gpio_set_value(32, 0);
+ gpio_set_value(155, 0);
+ // st15_hdmi_power(0);
+ }
+ }
+ return 0;
+}
+
+
+static struct lcdc_platform_data lcdc_pdata = {
+ .lcdc_gpio_config = msm_fb_lcdc_gpio_config,
+};
+
+static struct msm_gpio msm_fb_st15_gpio_config_data[] = {
+ { GPIO_CFG(17, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "lcdc_en0" },
+ { GPIO_CFG(19, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "dat_pwr_sv" },
+ { GPIO_CFG(20, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "lvds_pwr_dn" },
+ { GPIO_CFG(22, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "lcdc_en1" },
+ { GPIO_CFG(32, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "lcdc_en2" },
+ { GPIO_CFG(103, 0, GPIO_INPUT, GPIO_NO_PULL, GPIO_2MA), "hdmi_irq" },
+ { GPIO_CFG(155, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "hdmi_3v3" },
+};
+
+static struct msm_panel_common_pdata mdp_pdata = {
+ .gpio = 98,
+};
+
+static struct platform_device *devices[] __initdata = {
+ &msm_fb_device,
+};
+
+
+static void __init msm_register_device(struct platform_device *pdev, void *data)
+{
+ int ret;
+
+ pdev->dev.platform_data = data;
+
+ ret = platform_device_register(pdev);
+ if (ret)
+ dev_err(&pdev->dev,
+ "%s: platform_device_register() failed = %d\n",
+ __func__, ret);
+}
+
+void __init msm_fb_register_device(char *name, void *data)
+{
+ if (!strncmp(name, "mdp", 3))
+ msm_register_device(&msm_mdp_device, data);
+/*
+ else if (!strncmp(name, "pmdh", 4))
+ msm_register_device(&msm_mddi_device, data);
+ else if (!strncmp(name, "emdh", 4))
+ msm_register_device(&msm_mddi_ext_device, data);
+ else if (!strncmp(name, "ebi2", 4))
+ msm_register_device(&msm_ebi2_lcd_device, data);
+ else if (!strncmp(name, "tvenc", 5))
+ msm_register_device(&msm_tvenc_device, data);
+ else */
+
+ if (!strncmp(name, "lcdc", 4))
+ msm_register_device(&msm_lcdc_device, data);
+ /*else
+ printk(KERN_ERR "%s: unknown device! %s\n", __func__, name);
+*/
+}
+
+static void __init msm_fb_add_devices(void)
+{
+ int rc;
+ msm_fb_register_device("mdp", &mdp_pdata);
+// msm_fb_register_device("pmdh", &mddi_pdata);
+// msm_fb_register_device("emdh", &mddi_pdata);
+// msm_fb_register_device("tvenc", 0);
+
+ if (machine_is_qsd8x50a_st1_5()) {
+/* rc = st15_hdmi_vreg_init();
+ if (rc)
+ return;
+*/
+ rc = msm_gpios_request_enable(
+ msm_fb_st15_gpio_config_data,
+ ARRAY_SIZE(msm_fb_st15_gpio_config_data));
+ if (rc) {
+ printk(KERN_ERR "%s: unable to init lcdc gpios\n",
+ __func__);
+ return;
+ }
+ msm_fb_register_device("lcdc", &lcdc_pdata);
+ } else
+ msm_fb_register_device("lcdc", 0);
+}
+
+int __init staging_init_pmem(void)
+{
+ qsd8x50_allocate_memory_regions();
+ return 0;
+}
+
+int __init staging_init_devices(void)
+{
+ platform_add_devices(devices, ARRAY_SIZE(devices));
+ msm_fb_add_devices();
+ return 0;
+}
+
+arch_initcall(staging_init_pmem);
+arch_initcall(staging_init_devices);
diff --git a/drivers/staging/msm/tv_ntsc.c b/drivers/staging/msm/tv_ntsc.c
new file mode 100644
index 0000000..5eb6761
--- /dev/null
+++ b/drivers/staging/msm/tv_ntsc.c
@@ -0,0 +1,163 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+
+#include "msm_fb.h"
+#include "tvenc.h"
+
+#define NTSC_TV_DIMENSION_WIDTH 720
+#define NTSC_TV_DIMENSION_HEIGHT 480
+
+static int ntsc_off(struct platform_device *pdev);
+static int ntsc_on(struct platform_device *pdev);
+
+static int ntsc_on(struct platform_device *pdev)
+{
+ uint32 reg = 0;
+ int ret = 0;
+ struct msm_fb_data_type *mfd;
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */
+
+ if (mfd->panel.id == NTSC_M) {
+ /* Cr gain 11, Cb gain C6, y_gain 97 */
+ TV_OUT(TV_GAIN, 0x0081B697);
+ } else {
+ /* Cr gain 11, Cb gain C6, y_gain 97 */
+ TV_OUT(TV_GAIN, 0x008bc4a3);
+ reg |= TVENC_CTL_NTSCJ_MODE;
+ }
+
+ TV_OUT(TV_CGMS, 0x0);
+ /* NTSC Timing */
+ TV_OUT(TV_SYNC_1, 0x0020009e);
+ TV_OUT(TV_SYNC_2, 0x011306B4);
+ TV_OUT(TV_SYNC_3, 0x0006000C);
+ TV_OUT(TV_SYNC_4, 0x0028020D);
+ TV_OUT(TV_SYNC_5, 0x005E02FB);
+ TV_OUT(TV_SYNC_6, 0x0006000C);
+ TV_OUT(TV_SYNC_7, 0x00000012);
+ TV_OUT(TV_BURST_V1, 0x0013020D);
+ TV_OUT(TV_BURST_V2, 0x0014020C);
+ TV_OUT(TV_BURST_V3, 0x0013020D);
+ TV_OUT(TV_BURST_V4, 0x0014020C);
+ TV_OUT(TV_BURST_H, 0x00AE00F2);
+ TV_OUT(TV_SOL_REQ_ODD, 0x00280208);
+ TV_OUT(TV_SOL_REQ_EVEN, 0x00290209);
+
+ reg |= TVENC_CTL_TV_MODE_NTSC_M_PAL60;
+
+ reg |= TVENC_CTL_Y_FILTER_EN |
+ TVENC_CTL_CR_FILTER_EN |
+ TVENC_CTL_CB_FILTER_EN | TVENC_CTL_SINX_FILTER_EN;
+#ifdef CONFIG_FB_MSM_TVOUT_SVIDEO
+ reg |= TVENC_CTL_S_VIDEO_EN;
+#endif
+
+ TV_OUT(TV_LEVEL, 0x00000000); /* DC offset to 0. */
+ TV_OUT(TV_OFFSET, 0x008080f0);
+
+#ifdef CONFIG_FB_MSM_MDP31
+ TV_OUT(TV_DAC_INTF, 0x29);
+#endif
+ TV_OUT(TV_ENC_CTL, reg);
+
+ reg |= TVENC_CTL_ENC_EN;
+ TV_OUT(TV_ENC_CTL, reg);
+
+ return ret;
+}
+
+static int ntsc_off(struct platform_device *pdev)
+{
+ TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */
+ return 0;
+}
+
+static int __init ntsc_probe(struct platform_device *pdev)
+{
+ msm_fb_add_device(pdev);
+
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = ntsc_probe,
+ .driver = {
+ .name = "tv_ntsc",
+ },
+};
+
+static struct msm_fb_panel_data ntsc_panel_data = {
+ .panel_info.xres = NTSC_TV_DIMENSION_WIDTH,
+ .panel_info.yres = NTSC_TV_DIMENSION_HEIGHT,
+ .panel_info.type = TV_PANEL,
+ .panel_info.pdest = DISPLAY_1,
+ .panel_info.wait_cycle = 0,
+ .panel_info.bpp = 16,
+ .panel_info.fb_num = 2,
+ .on = ntsc_on,
+ .off = ntsc_off,
+};
+
+static struct platform_device this_device = {
+ .name = "tv_ntsc",
+ .id = 0,
+ .dev = {
+ .platform_data = &ntsc_panel_data,
+ }
+};
+
+static int __init ntsc_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&this_driver);
+ if (!ret) {
+ ret = platform_device_register(&this_device);
+ if (ret)
+ platform_driver_unregister(&this_driver);
+ }
+
+ return ret;
+}
+
+module_init(ntsc_init);
\ No newline at end of file
diff --git a/drivers/staging/msm/tv_pal.c b/drivers/staging/msm/tv_pal.c
new file mode 100644
index 0000000..204da51
--- /dev/null
+++ b/drivers/staging/msm/tv_pal.c
@@ -0,0 +1,213 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+
+#include "msm_fb.h"
+#include "tvenc.h"
+
+#ifdef CONFIG_FB_MSM_TVOUT_PAL_M
+#define PAL_TV_DIMENSION_WIDTH 720
+#define PAL_TV_DIMENSION_HEIGHT 480
+#else
+#define PAL_TV_DIMENSION_WIDTH 720
+#define PAL_TV_DIMENSION_HEIGHT 576
+#endif
+
+static int pal_on(struct platform_device *pdev)
+{
+ uint32 reg = 0;
+ int ret = 0;
+ struct msm_fb_data_type *mfd;
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */
+
+ switch (mfd->panel.id) {
+ case PAL_BDGHIN:
+ /* Cr gain 11, Cb gain C6, y_gain 97 */
+ TV_OUT(TV_GAIN, 0x0088c1a0);
+ TV_OUT(TV_CGMS, 0x00012345);
+ TV_OUT(TV_TEST_MUX, 0x0);
+ /* PAL Timing */
+ TV_OUT(TV_SYNC_1, 0x00180097);
+ TV_OUT(TV_SYNC_2, 0x011f06c0);
+ TV_OUT(TV_SYNC_3, 0x0005000a);
+ TV_OUT(TV_SYNC_4, 0x00320271);
+ TV_OUT(TV_SYNC_5, 0x005602f9);
+ TV_OUT(TV_SYNC_6, 0x0005000a);
+ TV_OUT(TV_SYNC_7, 0x0000000f);
+ TV_OUT(TV_BURST_V1, 0x0012026e);
+ TV_OUT(TV_BURST_V2, 0x0011026d);
+ TV_OUT(TV_BURST_V3, 0x00100270);
+ TV_OUT(TV_BURST_V4, 0x0013026f);
+ TV_OUT(TV_BURST_H, 0x00af00ea);
+ TV_OUT(TV_SOL_REQ_ODD, 0x0030026e);
+ TV_OUT(TV_SOL_REQ_EVEN, 0x0031026f);
+
+ reg |= TVENC_CTL_TV_MODE_PAL_BDGHIN;
+ break;
+ case PAL_M:
+ /* Cr gain 11, Cb gain C6, y_gain 97 */
+ TV_OUT(TV_GAIN, 0x0081b697);
+ TV_OUT(TV_CGMS, 0x000af317);
+ TV_OUT(TV_TEST_MUX, 0x000001c3);
+ TV_OUT(TV_TEST_MODE, 0x00000002);
+ /* PAL Timing */
+ TV_OUT(TV_SYNC_1, 0x0020009e);
+ TV_OUT(TV_SYNC_2, 0x011306b4);
+ TV_OUT(TV_SYNC_3, 0x0006000c);
+ TV_OUT(TV_SYNC_4, 0x0028020D);
+ TV_OUT(TV_SYNC_5, 0x005e02fb);
+ TV_OUT(TV_SYNC_6, 0x0006000c);
+ TV_OUT(TV_SYNC_7, 0x00000012);
+ TV_OUT(TV_BURST_V1, 0x0012020b);
+ TV_OUT(TV_BURST_V2, 0x0016020c);
+ TV_OUT(TV_BURST_V3, 0x00150209);
+ TV_OUT(TV_BURST_V4, 0x0013020c);
+ TV_OUT(TV_BURST_H, 0x00bf010b);
+ TV_OUT(TV_SOL_REQ_ODD, 0x00280208);
+ TV_OUT(TV_SOL_REQ_EVEN, 0x00290209);
+
+ reg |= TVENC_CTL_TV_MODE_PAL_M;
+ break;
+ case PAL_N:
+ /* Cr gain 11, Cb gain C6, y_gain 97 */
+ TV_OUT(TV_GAIN, 0x0081b697);
+ TV_OUT(TV_CGMS, 0x000af317);
+ TV_OUT(TV_TEST_MUX, 0x000001c3);
+ TV_OUT(TV_TEST_MODE, 0x00000002);
+ /* PAL Timing */
+ TV_OUT(TV_SYNC_1, 0x00180097);
+ TV_OUT(TV_SYNC_2, 0x12006c0);
+ TV_OUT(TV_SYNC_3, 0x0005000a);
+ TV_OUT(TV_SYNC_4, 0x00320271);
+ TV_OUT(TV_SYNC_5, 0x005602f9);
+ TV_OUT(TV_SYNC_6, 0x0005000a);
+ TV_OUT(TV_SYNC_7, 0x0000000f);
+ TV_OUT(TV_BURST_V1, 0x0012026e);
+ TV_OUT(TV_BURST_V2, 0x0011026d);
+ TV_OUT(TV_BURST_V3, 0x00100270);
+ TV_OUT(TV_BURST_V4, 0x0013026f);
+ TV_OUT(TV_BURST_H, 0x00af00fa);
+ TV_OUT(TV_SOL_REQ_ODD, 0x0030026e);
+ TV_OUT(TV_SOL_REQ_EVEN, 0x0031026f);
+
+ reg |= TVENC_CTL_TV_MODE_PAL_N;
+ break;
+
+ default:
+ return -ENODEV;
+ }
+
+ reg |= TVENC_CTL_Y_FILTER_EN |
+ TVENC_CTL_CR_FILTER_EN |
+ TVENC_CTL_CB_FILTER_EN | TVENC_CTL_SINX_FILTER_EN;
+#ifdef CONFIG_FB_MSM_TVOUT_SVIDEO
+ reg |= TVENC_CTL_S_VIDEO_EN;
+#endif
+
+ TV_OUT(TV_LEVEL, 0x00000000); /* DC offset to 0. */
+ TV_OUT(TV_OFFSET, 0x008080f0);
+
+#ifdef CONFIG_FB_MSM_MDP31
+ TV_OUT(TV_DAC_INTF, 0x29);
+#endif
+ TV_OUT(TV_ENC_CTL, reg);
+
+ reg |= TVENC_CTL_ENC_EN;
+ TV_OUT(TV_ENC_CTL, reg);
+
+ return ret;
+}
+
+static int pal_off(struct platform_device *pdev)
+{
+ TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */
+ return 0;
+}
+
+static int __init pal_probe(struct platform_device *pdev)
+{
+ msm_fb_add_device(pdev);
+
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = pal_probe,
+ .driver = {
+ .name = "tv_pal",
+ },
+};
+
+static struct msm_fb_panel_data pal_panel_data = {
+ .panel_info.xres = PAL_TV_DIMENSION_WIDTH,
+ .panel_info.yres = PAL_TV_DIMENSION_HEIGHT,
+ .panel_info.type = TV_PANEL,
+ .panel_info.pdest = DISPLAY_1,
+ .panel_info.wait_cycle = 0,
+ .panel_info.bpp = 16,
+ .panel_info.fb_num = 2,
+ .on = pal_on,
+ .off = pal_off,
+};
+
+static struct platform_device this_device = {
+ .name = "tv_pal",
+ .id = 0,
+ .dev = {
+ .platform_data = &pal_panel_data,
+ }
+};
+
+static int __init pal_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&this_driver);
+ if (!ret) {
+ ret = platform_device_register(&this_device);
+ if (ret)
+ platform_driver_unregister(&this_driver);
+ }
+
+ return ret;
+}
+
+module_init(pal_init);
diff --git a/drivers/staging/msm/tvenc.c b/drivers/staging/msm/tvenc.c
new file mode 100644
index 0000000..f41c5ac
--- /dev/null
+++ b/drivers/staging/msm/tvenc.c
@@ -0,0 +1,295 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/pm_qos_params.h>
+
+#define TVENC_C
+#include "tvenc.h"
+#include "msm_fb.h"
+
+static int tvenc_probe(struct platform_device *pdev);
+static int tvenc_remove(struct platform_device *pdev);
+
+static int tvenc_off(struct platform_device *pdev);
+static int tvenc_on(struct platform_device *pdev);
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+
+static struct clk *tvenc_clk;
+static struct clk *tvdac_clk;
+
+static struct platform_driver tvenc_driver = {
+ .probe = tvenc_probe,
+ .remove = tvenc_remove,
+ .suspend = NULL,
+// .suspend_late = NULL,
+// .resume_early = NULL,
+ .resume = NULL,
+ .shutdown = NULL,
+ .driver = {
+ .name = "tvenc",
+ },
+};
+
+static struct tvenc_platform_data *tvenc_pdata;
+
+static int tvenc_off(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ ret = panel_next_off(pdev);
+
+ clk_disable(tvenc_clk);
+ clk_disable(tvdac_clk);
+
+ if (tvenc_pdata && tvenc_pdata->pm_vid_en)
+ ret = tvenc_pdata->pm_vid_en(0);
+
+ //pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "tvenc",
+ // PM_QOS_DEFAULT_VALUE);
+
+ if (ret)
+ printk(KERN_ERR "%s: pm_vid_en(off) failed! %d\n",
+ __func__, ret);
+
+ return ret;
+}
+
+static int tvenc_on(struct platform_device *pdev)
+{
+ int ret = 0;
+
+// pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "tvenc",
+// 128000);
+ if (tvenc_pdata && tvenc_pdata->pm_vid_en)
+ ret = tvenc_pdata->pm_vid_en(1);
+
+ if (ret) {
+ printk(KERN_ERR "%s: pm_vid_en(on) failed! %d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ clk_enable(tvenc_clk);
+ clk_enable(tvdac_clk);
+
+ ret = panel_next_on(pdev);
+
+ return ret;
+}
+
+void tvenc_gen_test_pattern(struct msm_fb_data_type *mfd)
+{
+ uint32 reg = 0, i;
+
+ reg = readl(MSM_TV_ENC_CTL);
+ reg |= TVENC_CTL_TEST_PATT_EN;
+
+ for (i = 0; i < 3; i++) {
+ TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */
+
+ switch (i) {
+ /*
+ * TV Encoder - Color Bar Test Pattern
+ */
+ case 0:
+ reg |= TVENC_CTL_TPG_CLRBAR;
+ break;
+ /*
+ * TV Encoder - Red Frame Test Pattern
+ */
+ case 1:
+ reg |= TVENC_CTL_TPG_REDCLR;
+ break;
+ /*
+ * TV Encoder - Modulated Ramp Test Pattern
+ */
+ default:
+ reg |= TVENC_CTL_TPG_MODRAMP;
+ break;
+ }
+
+ TV_OUT(TV_ENC_CTL, reg);
+ mdelay(5000);
+
+ switch (i) {
+ /*
+ * TV Encoder - Color Bar Test Pattern
+ */
+ case 0:
+ reg &= ~TVENC_CTL_TPG_CLRBAR;
+ break;
+ /*
+ * TV Encoder - Red Frame Test Pattern
+ */
+ case 1:
+ reg &= ~TVENC_CTL_TPG_REDCLR;
+ break;
+ /*
+ * TV Encoder - Modulated Ramp Test Pattern
+ */
+ default:
+ reg &= ~TVENC_CTL_TPG_MODRAMP;
+ break;
+ }
+ }
+}
+
+static int tvenc_resource_initialized;
+
+static int tvenc_probe(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ struct platform_device *mdp_dev = NULL;
+ struct msm_fb_panel_data *pdata = NULL;
+ int rc;
+
+ if (pdev->id == 0) {
+ tvenc_base = ioremap(pdev->resource[0].start,
+ pdev->resource[0].end -
+ pdev->resource[0].start + 1);
+ if (!tvenc_base) {
+ printk(KERN_ERR
+ "tvenc_base ioremap failed!\n");
+ return -ENOMEM;
+ }
+ tvenc_pdata = pdev->dev.platform_data;
+ tvenc_resource_initialized = 1;
+ return 0;
+ }
+
+ if (!tvenc_resource_initialized)
+ return -EPERM;
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+ return -ENOMEM;
+
+ if (tvenc_base == NULL)
+ return -ENOMEM;
+
+ mdp_dev = platform_device_alloc("mdp", pdev->id);
+ if (!mdp_dev)
+ return -ENOMEM;
+
+ /*
+ * link to the latest pdev
+ */
+ mfd->pdev = mdp_dev;
+ mfd->dest = DISPLAY_TV;
+
+ /*
+ * alloc panel device data
+ */
+ if (platform_device_add_data
+ (mdp_dev, pdev->dev.platform_data,
+ sizeof(struct msm_fb_panel_data))) {
+ printk(KERN_ERR "tvenc_probe: platform_device_add_data failed!\n");
+ platform_device_put(mdp_dev);
+ return -ENOMEM;
+ }
+ /*
+ * data chain
+ */
+ pdata = mdp_dev->dev.platform_data;
+ pdata->on = tvenc_on;
+ pdata->off = tvenc_off;
+ pdata->next = pdev;
+
+ /*
+ * get/set panel specific fb info
+ */
+ mfd->panel_info = pdata->panel_info;
+ mfd->fb_imgType = MDP_YCRYCB_H2V1;
+
+ /*
+ * set driver data
+ */
+ platform_set_drvdata(mdp_dev, mfd);
+
+ /*
+ * register in mdp driver
+ */
+ rc = platform_device_add(mdp_dev);
+ if (rc)
+ goto tvenc_probe_err;
+
+ pdev_list[pdev_list_cnt++] = pdev;
+ return 0;
+
+tvenc_probe_err:
+ platform_device_put(mdp_dev);
+ return rc;
+}
+
+static int tvenc_remove(struct platform_device *pdev)
+{
+// pm_qos_remove_requirement(PM_QOS_SYSTEM_BUS_FREQ , "tvenc");
+ return 0;
+}
+
+static int tvenc_register_driver(void)
+{
+ return platform_driver_register(&tvenc_driver);
+}
+
+static int __init tvenc_driver_init(void)
+{
+ tvenc_clk = clk_get(NULL, "tv_enc_clk");
+ tvdac_clk = clk_get(NULL, "tv_dac_clk");
+
+ if (IS_ERR(tvenc_clk)) {
+ printk(KERN_ERR "error: can't get tvenc_clk!\n");
+ return IS_ERR(tvenc_clk);
+ }
+
+ if (IS_ERR(tvdac_clk)) {
+ printk(KERN_ERR "error: can't get tvdac_clk!\n");
+ return IS_ERR(tvdac_clk);
+ }
+
+// pm_qos_add_requirement(PM_QOS_SYSTEM_BUS_FREQ , "tvenc",
+// PM_QOS_DEFAULT_VALUE);
+ return tvenc_register_driver();
+}
+
+module_init(tvenc_driver_init);
diff --git a/drivers/staging/msm/tvenc.h b/drivers/staging/msm/tvenc.h
new file mode 100644
index 0000000..a682dbe
--- /dev/null
+++ b/drivers/staging/msm/tvenc.h
@@ -0,0 +1,117 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. 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 Code Aurora 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, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT 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 TVENC_H
+#define TVENC_H
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+#include "msm_fb_panel.h"
+
+#define NTSC_M 0 /* North America, Korea */
+#define NTSC_J 1 /* Japan */
+#define PAL_BDGHIN 2 /* Non-argentina PAL-N */
+#define PAL_M 3 /* PAL-M */
+#define PAL_N 4 /* Argentina PAL-N */
+
+/* 3.57954545 Mhz */
+#define TVENC_CTL_TV_MODE_NTSC_M_PAL60 0
+/* 3.57961149 Mhz */
+#define TVENC_CTL_TV_MODE_PAL_M BIT(0)
+/*non-Argintina = 4.3361875 Mhz */
+#define TVENC_CTL_TV_MODE_PAL_BDGHIN BIT(1)
+/*Argentina = 3.582055625 Mhz */
+#define TVENC_CTL_TV_MODE_PAL_N (BIT(1)|BIT(0))
+
+#define TVENC_CTL_ENC_EN BIT(2)
+#define TVENC_CTL_CC_EN BIT(3)
+#define TVENC_CTL_CGMS_EN BIT(4)
+#define TVENC_CTL_MACRO_EN BIT(5)
+#define TVENC_CTL_Y_FILTER_W_NOTCH BIT(6)
+#define TVENC_CTL_Y_FILTER_WO_NOTCH 0
+#define TVENC_CTL_Y_FILTER_EN BIT(7)
+#define TVENC_CTL_CR_FILTER_EN BIT(8)
+#define TVENC_CTL_CB_FILTER_EN BIT(9)
+#define TVENC_CTL_SINX_FILTER_EN BIT(10)
+#define TVENC_CTL_TEST_PATT_EN BIT(11)
+#define TVENC_CTL_OUTPUT_INV BIT(12)
+#define TVENC_CTL_PAL60_MODE BIT(13)
+#define TVENC_CTL_NTSCJ_MODE BIT(14)
+#define TVENC_CTL_TPG_CLRBAR 0
+#define TVENC_CTL_TPG_MODRAMP BIT(15)
+#define TVENC_CTL_TPG_REDCLR BIT(16)
+#define TVENC_CTL_S_VIDEO_EN BIT(19)
+
+#ifdef TVENC_C
+void *tvenc_base;
+#else
+extern void *tvenc_base;
+#endif
+
+#define TV_OUT(reg, v) writel(v, tvenc_base + MSM_##reg)
+
+#define MSM_TV_ENC_CTL 0x00
+#define MSM_TV_LEVEL 0x04
+#define MSM_TV_GAIN 0x08
+#define MSM_TV_OFFSET 0x0c
+#define MSM_TV_CGMS 0x10
+#define MSM_TV_SYNC_1 0x14
+#define MSM_TV_SYNC_2 0x18
+#define MSM_TV_SYNC_3 0x1c
+#define MSM_TV_SYNC_4 0x20
+#define MSM_TV_SYNC_5 0x24
+#define MSM_TV_SYNC_6 0x28
+#define MSM_TV_SYNC_7 0x2c
+#define MSM_TV_BURST_V1 0x30
+#define MSM_TV_BURST_V2 0x34
+#define MSM_TV_BURST_V3 0x38
+#define MSM_TV_BURST_V4 0x3c
+#define MSM_TV_BURST_H 0x40
+#define MSM_TV_SOL_REQ_ODD 0x44
+#define MSM_TV_SOL_REQ_EVEN 0x48
+#define MSM_TV_DAC_CTL 0x4c
+#define MSM_TV_TEST_MUX 0x50
+#define MSM_TV_TEST_MODE 0x54
+#define MSM_TV_TEST_MISR_RESET 0x58
+#define MSM_TV_TEST_EXPORT_MISR 0x5c
+#define MSM_TV_TEST_MISR_CURR_VAL 0x60
+#define MSM_TV_TEST_SOF_CFG 0x64
+#define MSM_TV_DAC_INTF 0x100
+
+#endif /* TVENC_H */
diff --git a/drivers/staging/phison/Kconfig b/drivers/staging/phison/Kconfig
index d3c65d3..1b56119 100644
--- a/drivers/staging/phison/Kconfig
+++ b/drivers/staging/phison/Kconfig
@@ -1,5 +1,5 @@
config IDE_PHISON
tristate "PCIE ATA PS5000 IDE support"
- depends on PCI && ATA && ATA_SFF
+ depends on PCI && ATA && ATA_SFF && ATA_BMDMA
---help---
This is an experimental driver for PS5000 IDE driver.
diff --git a/drivers/staging/rt2860/sta_ioctl.c b/drivers/staging/rt2860/sta_ioctl.c
index 112da7a..6b8268d 100644
--- a/drivers/staging/rt2860/sta_ioctl.c
+++ b/drivers/staging/rt2860/sta_ioctl.c
@@ -2522,6 +2522,8 @@
Status =
copy_to_user(erq->pointer, pAd->nickname,
erq->length);
+ if (Status)
+ Status = -EFAULT;
break;
}
case SIOCGIWRATE: /*get default bit rate (bps) */
diff --git a/drivers/staging/rt2860/usb_main_dev.c b/drivers/staging/rt2860/usb_main_dev.c
index b740662..674769d 100644
--- a/drivers/staging/rt2860/usb_main_dev.c
+++ b/drivers/staging/rt2860/usb_main_dev.c
@@ -77,6 +77,7 @@
{USB_DEVICE(0x083A, 0x7522)}, /* Arcadyan */
{USB_DEVICE(0x0CDE, 0x0022)}, /* ZCOM */
{USB_DEVICE(0x0586, 0x3416)}, /* Zyxel */
+ {USB_DEVICE(0x0586, 0x341a)}, /* Zyxel NWD-270N */
{USB_DEVICE(0x0CDE, 0x0025)}, /* Zyxel */
{USB_DEVICE(0x1740, 0x9701)}, /* EnGenius */
{USB_DEVICE(0x1740, 0x9702)}, /* EnGenius */
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c
index dacefea..49ab9fa 100644
--- a/drivers/staging/rtl8187se/r8180_core.c
+++ b/drivers/staging/rtl8187se/r8180_core.c
@@ -66,8 +66,6 @@
static int hwwep = 0;
static int channels = 0x3fff;
-#define eqMacAddr(a, b) (((a)[0] == (b)[0] && (a)[1] == (b)[1] && (a)[2] == (b)[2] && (a)[3] == (b)[3] && (a)[4] == (b)[4] && (a)[5] == (b)[5]) ? 1 : 0)
-#define cpMacAddr(des, src) ((des)[0] = (src)[0], (des)[1] = (src)[1], (des)[2] = (src)[2], (des)[3] = (src)[3], (des)[4] = (src)[4], (des)[5] = (src)[5])
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, rtl8180_pci_id_tbl);
MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
diff --git a/drivers/staging/rtl8192su/r8192U_core.c b/drivers/staging/rtl8192su/r8192U_core.c
index 447d647..1b68906 100644
--- a/drivers/staging/rtl8192su/r8192U_core.c
+++ b/drivers/staging/rtl8192su/r8192U_core.c
@@ -112,28 +112,29 @@
#define CAM_CONTENT_COUNT 8
static const struct usb_device_id rtl8192_usb_id_tbl[] = {
- /* Realtek */
- {USB_DEVICE(0x0bda, 0x8171)},
- {USB_DEVICE(0x0bda, 0x8192)},
- {USB_DEVICE(0x0bda, 0x8709)},
- /* Corega */
- {USB_DEVICE(0x07aa, 0x0043)},
- /* Belkin */
- {USB_DEVICE(0x050d, 0x805E)},
- {USB_DEVICE(0x050d, 0x815F)}, /* Belkin F5D8053 v6 */
- /* Sitecom */
- {USB_DEVICE(0x0df6, 0x0031)},
- {USB_DEVICE(0x0df6, 0x004b)}, /* WL-349 */
- /* EnGenius */
- {USB_DEVICE(0x1740, 0x9201)},
- /* Dlink */
- {USB_DEVICE(0x2001, 0x3301)},
- /* Zinwell */
- {USB_DEVICE(0x5a57, 0x0290)},
- /* Guillemot */
- {USB_DEVICE(0x06f8, 0xe031)},
- //92SU
+ {USB_DEVICE(0x0bda, 0x8171)}, /* Realtek */
{USB_DEVICE(0x0bda, 0x8172)},
+ {USB_DEVICE(0x0bda, 0x8173)},
+ {USB_DEVICE(0x0bda, 0x8174)},
+ {USB_DEVICE(0x0bda, 0x8712)},
+ {USB_DEVICE(0x0bda, 0x8713)},
+ {USB_DEVICE(0x07aa, 0x0047)},
+ {USB_DEVICE(0x07d1, 0x3303)},
+ {USB_DEVICE(0x07d1, 0x3302)},
+ {USB_DEVICE(0x07d1, 0x3300)},
+ {USB_DEVICE(0x1740, 0x9603)},
+ {USB_DEVICE(0x1740, 0x9605)},
+ {USB_DEVICE(0x050d, 0x815F)},
+ {USB_DEVICE(0x06f8, 0xe031)},
+ {USB_DEVICE(0x7392, 0x7611)},
+ {USB_DEVICE(0x7392, 0x7612)},
+ {USB_DEVICE(0x7392, 0x7622)},
+ {USB_DEVICE(0x0DF6, 0x0045)},
+ {USB_DEVICE(0x0E66, 0x0015)},
+ {USB_DEVICE(0x0E66, 0x0016)},
+ {USB_DEVICE(0x0b05, 0x1786)},
+ /* these are not in the official list */
+ {USB_DEVICE(0x0df6, 0x004b)}, /* WL-349 */
{}
};
diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
index 2bede27..f38472c 100644
--- a/drivers/staging/rtl8192u/r8192U_core.c
+++ b/drivers/staging/rtl8192u/r8192U_core.c
@@ -121,6 +121,8 @@
{USB_DEVICE(0x2001, 0x3301)},
/* Zinwell */
{USB_DEVICE(0x5a57, 0x0290)},
+ /* LG */
+ {USB_DEVICE(0x043e, 0x7a01)},
{}
};
diff --git a/drivers/staging/sep/sep_driver.c b/drivers/staging/sep/sep_driver.c
index 0332c37..ecbde34 100644
--- a/drivers/staging/sep/sep_driver.c
+++ b/drivers/staging/sep/sep_driver.c
@@ -594,8 +594,10 @@
dbg("SEP Driver:--------> sep_allocate_data_pool_memory_handler start\n");
error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_alloc_t));
- if (error)
+ if (error) {
+ error = -EFAULT;
goto end_function;
+ }
/* allocate memory */
if ((sep->data_pool_bytes_allocated + command_args.num_bytes) > SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES) {
@@ -609,8 +611,10 @@
/* write the memory back to the user space */
error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_alloc_t));
- if (error)
+ if (error) {
+ error = -EFAULT;
goto end_function;
+ }
/* set the allocation */
sep->data_pool_bytes_allocated += command_args.num_bytes;
@@ -661,6 +665,8 @@
}
/* copy the application data */
error = copy_from_user(virt_address, (void *) app_in_address, num_bytes);
+ if (error)
+ error = -EFAULT;
end_function:
dbg("SEP Driver:<-------- sep_write_into_data_pool_handler end\n");
return error;
@@ -711,6 +717,8 @@
/* copy the application data */
error = copy_to_user((void *) app_out_address, virt_address, num_bytes);
+ if (error)
+ error = -EFAULT;
end_function:
dbg("SEP Driver:<-------- sep_read_from_data_pool_handler end\n");
return error;
@@ -1448,8 +1456,10 @@
dbg("SEP Driver:--------> sep_create_sync_dma_tables_handler start\n");
error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_build_sync_table_t));
- if (error)
+ if (error) {
+ error = -EFAULT;
goto end_function;
+ }
edbg("app_in_address is %08lx\n", command_args.app_in_address);
edbg("app_out_address is %08lx\n", command_args.app_out_address);
@@ -1799,8 +1809,10 @@
goto end_function;
error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_build_flow_table_t));
- if (error)
+ if (error) {
+ error = -EFAULT;
goto end_function;
+ }
/* create flow tables */
error = sep_prepare_flow_dma_tables(sep, command_args.num_virtual_buffers, command_args.virt_buff_data_addr, flow_context_ptr, &first_table_data, &last_table_data, command_args.isKernelVirtualAddress);
@@ -1819,8 +1831,10 @@
/* send the parameters to user application */
error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_build_flow_table_t));
- if (error)
+ if (error) {
+ error = -EFAULT;
goto end_function_with_error;
+ }
/* all the flow created - update the flow entry with temp id */
flow_context_ptr->flow_id = SEP_TEMP_FLOW_ID;
@@ -1861,8 +1875,10 @@
/* get input parameters */
error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_add_flow_table_t));
- if (error)
+ if (error) {
+ error = -EFAULT;
goto end_function;
+ }
/* find the flow structure for the flow id */
flow_context_ptr = sep_find_flow_context(sep, command_args.flow_id);
@@ -1933,6 +1949,8 @@
/* send the parameters to user application */
error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_add_flow_table_t));
+ if (error)
+ error = -EFAULT;
end_function_with_error:
/* free the allocated tables */
sep_deallocated_flow_tables(&first_table_data);
@@ -1953,8 +1971,10 @@
dbg("SEP Driver:--------> sep_add_flow_tables_message_handler start\n");
error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_add_message_t));
- if (error)
+ if (error) {
+ error = -EFAULT;
goto end_function;
+ }
/* check input */
if (command_args.message_size_in_bytes > SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES) {
@@ -1970,6 +1990,8 @@
/* copy the message into context */
flow_context_ptr->message_size_in_bytes = command_args.message_size_in_bytes;
error = copy_from_user(flow_context_ptr->message, (void *) command_args.message_address, command_args.message_size_in_bytes);
+ if (error)
+ error = -EFAULT;
end_function:
dbg("SEP Driver:<-------- sep_add_flow_tables_message_handler end\n");
return error;
@@ -1994,6 +2016,8 @@
/* send the parameters to user application */
error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_static_pool_addr_t));
+ if (error)
+ error = -EFAULT;
dbg("SEP Driver:<-------- sep_get_static_pool_addr_handler end\n");
return error;
}
@@ -2010,8 +2034,10 @@
dbg("SEP Driver:--------> sep_get_physical_mapped_offset_handler start\n");
error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_get_mapped_offset_t));
- if (error)
+ if (error) {
+ error = -EFAULT;
goto end_function;
+ }
if (command_args.physical_address < sep->shared_bus) {
error = -EINVAL;
@@ -2025,6 +2051,8 @@
/* send the parameters to user application */
error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_get_mapped_offset_t));
+ if (error)
+ error = -EFAULT;
end_function:
dbg("SEP Driver:<-------- sep_get_physical_mapped_offset_handler end\n");
return error;
@@ -2070,11 +2098,11 @@
error = 0;
error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_init_t));
-
- dbg("SEP Driver:--------> sep_init_handler - finished copy_from_user \n");
-
- if (error)
+ if (error) {
+ error = -EFAULT;
goto end_function;
+ }
+ dbg("SEP Driver:--------> sep_init_handler - finished copy_from_user\n");
/* PATCH - configure the DMA to single -burst instead of multi-burst */
/*sep_configure_dma_burst(); */
diff --git a/drivers/staging/tm6000/Kconfig b/drivers/staging/tm6000/Kconfig
index 5fe759c..3657e33 100644
--- a/drivers/staging/tm6000/Kconfig
+++ b/drivers/staging/tm6000/Kconfig
@@ -2,7 +2,8 @@
tristate "TV Master TM5600/6000/6010 driver"
depends on VIDEO_DEV && I2C && INPUT && USB && EXPERIMENTAL
select VIDEO_TUNER
- select TUNER_XC2028
+ select MEDIA_TUNER_XC2028
+ select MEDIA_TUNER_XC5000
select VIDEOBUF_VMALLOC
help
Support for TM5600/TM6000/TM6010 USB Device
diff --git a/drivers/staging/tm6000/tm6000-alsa.c b/drivers/staging/tm6000/tm6000-alsa.c
index bc89f9d..273e26e 100644
--- a/drivers/staging/tm6000/tm6000-alsa.c
+++ b/drivers/staging/tm6000/tm6000-alsa.c
@@ -15,6 +15,7 @@
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/usb.h>
+#include <linux/slab.h>
#include <asm/delay.h>
#include <sound/core.h>
@@ -410,5 +411,28 @@
snd_card_free(card);
return rc;
}
-EXPORT_SYMBOL_GPL(tm6000_audio_init);
+static int tm6000_audio_fini(struct tm6000_core *dev)
+{
+ return 0;
+}
+
+struct tm6000_ops audio_ops = {
+ .id = TM6000_AUDIO,
+ .name = "TM6000 Audio Extension",
+ .init = tm6000_audio_init,
+ .fini = tm6000_audio_fini,
+};
+
+static int __init tm6000_alsa_register(void)
+{
+ return tm6000_register_extension(&audio_ops);
+}
+
+static void __exit tm6000_alsa_unregister(void)
+{
+ tm6000_unregister_extension(&audio_ops);
+}
+
+module_init(tm6000_alsa_register);
+module_exit(tm6000_alsa_unregister);
diff --git a/drivers/staging/tm6000/tm6000-cards.c b/drivers/staging/tm6000/tm6000-cards.c
index 6143e20..6a9ae40 100644
--- a/drivers/staging/tm6000/tm6000-cards.c
+++ b/drivers/staging/tm6000/tm6000-cards.c
@@ -24,6 +24,7 @@
#include <linux/i2c.h>
#include <linux/usb.h>
#include <linux/version.h>
+#include <linux/slab.h>
#include <media/v4l2-common.h>
#include <media/tuner.h>
#include <media/tvaudio.h>
@@ -363,13 +364,7 @@
tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT,
0x02, arg);
msleep(10);
- rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
- TM6000_GPIO_CLK, 0);
- if (rc < 0)
- return rc;
- msleep(10);
- rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
- TM6000_GPIO_CLK, 1);
+ rc = tm6000_i2c_reset(dev, 10);
break;
case XC2028_TUNER_RESET:
/* Reset codes during load firmware */
@@ -423,14 +418,7 @@
break;
case 2:
- rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
- TM6000_GPIO_CLK, 0);
- if (rc < 0)
- return rc;
- msleep(100);
- rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
- TM6000_GPIO_CLK, 1);
- msleep(100);
+ rc = tm6000_i2c_reset(dev, 100);
break;
}
}
@@ -563,7 +551,7 @@
switch (dev->tuner_type) {
case TUNER_XC2028:
- tun_setup.tuner_callback = tm6000_tuner_callback;;
+ tun_setup.tuner_callback = tm6000_tuner_callback;
break;
case TUNER_XC5000:
tun_setup.tuner_callback = tm6000_xc5000_callback;
@@ -692,6 +680,10 @@
if (rc < 0)
goto err;
+ tm6000_add_into_devlist(dev);
+
+ tm6000_init_extension(dev);
+
if (dev->caps.has_dvb) {
dev->dvb = kzalloc(sizeof(*(dev->dvb)), GFP_KERNEL);
if (!dev->dvb) {
@@ -921,6 +913,25 @@
}
#endif
+ if (dev->gpio.power_led) {
+ switch (dev->model) {
+ case TM6010_BOARD_HAUPPAUGE_900H:
+ case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+ case TM6010_BOARD_TWINHAN_TU501:
+ /* Power led off */
+ tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+ dev->gpio.power_led, 0x01);
+ msleep(15);
+ break;
+ case TM6010_BOARD_BEHOLD_WANDER:
+ case TM6010_BOARD_BEHOLD_VOYAGER:
+ /* Power led off */
+ tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+ dev->gpio.power_led, 0x00);
+ msleep(15);
+ break;
+ }
+ }
tm6000_v4l2_unregister(dev);
tm6000_i2c_unregister(dev);
@@ -931,6 +942,9 @@
usb_put_dev(dev->udev);
+ tm6000_remove_from_devlist(dev);
+ tm6000_close_extension(dev);
+
mutex_unlock(&dev->lock);
kfree(dev);
}
diff --git a/drivers/staging/tm6000/tm6000-core.c b/drivers/staging/tm6000/tm6000-core.c
index bfbc53b..c3690e3 100644
--- a/drivers/staging/tm6000/tm6000-core.c
+++ b/drivers/staging/tm6000/tm6000-core.c
@@ -22,6 +22,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/i2c.h>
#include "tm6000.h"
@@ -153,6 +154,22 @@
return buf[3] | buf[2] << 8 | buf[1] << 16 | buf[0] << 24;
}
+int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep)
+{
+ int rc;
+
+ rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 0);
+ if (rc < 0)
+ return rc;
+
+ msleep(tsleep);
+
+ rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 1);
+ msleep(tsleep);
+
+ return rc;
+}
+
void tm6000_set_fourcc_format(struct tm6000_core *dev)
{
if (dev->dev_type == TM6010) {
@@ -323,6 +340,12 @@
tm6000_set_standard (dev, &dev->norm);
tm6000_set_audio_bitrate (dev,48000);
+ /* switch dvb led off */
+ if (dev->gpio.dvb_led) {
+ tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+ dev->gpio.dvb_led, 0x01);
+ }
+
return 0;
}
@@ -375,6 +398,13 @@
tm6000_set_reg (dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00);
msleep(100);
}
+
+ /* switch dvb led on */
+ if (dev->gpio.dvb_led) {
+ tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+ dev->gpio.dvb_led, 0x00);
+ }
+
return 0;
}
@@ -600,3 +630,95 @@
return val;
}
EXPORT_SYMBOL_GPL(tm6000_set_audio_bitrate);
+
+static LIST_HEAD(tm6000_devlist);
+static DEFINE_MUTEX(tm6000_devlist_mutex);
+
+/*
+ * tm6000_realease_resource()
+ */
+
+void tm6000_remove_from_devlist(struct tm6000_core *dev)
+{
+ mutex_lock(&tm6000_devlist_mutex);
+ list_del(&dev->devlist);
+ mutex_unlock(&tm6000_devlist_mutex);
+};
+
+void tm6000_add_into_devlist(struct tm6000_core *dev)
+{
+ mutex_lock(&tm6000_devlist_mutex);
+ list_add_tail(&dev->devlist, &tm6000_devlist);
+ mutex_unlock(&tm6000_devlist_mutex);
+};
+
+/*
+ * Extension interface
+ */
+
+static LIST_HEAD(tm6000_extension_devlist);
+static DEFINE_MUTEX(tm6000_extension_devlist_lock);
+
+int tm6000_register_extension(struct tm6000_ops *ops)
+{
+ struct tm6000_core *dev = NULL;
+
+ mutex_lock(&tm6000_devlist_mutex);
+ mutex_lock(&tm6000_extension_devlist_lock);
+ list_add_tail(&ops->next, &tm6000_extension_devlist);
+ list_for_each_entry(dev, &tm6000_devlist, devlist) {
+ if (dev)
+ ops->init(dev);
+ }
+ printk(KERN_INFO "tm6000: Initialized (%s) extension\n", ops->name);
+ mutex_unlock(&tm6000_extension_devlist_lock);
+ mutex_unlock(&tm6000_devlist_mutex);
+ return 0;
+}
+EXPORT_SYMBOL(tm6000_register_extension);
+
+void tm6000_unregister_extension(struct tm6000_ops *ops)
+{
+ struct tm6000_core *dev = NULL;
+
+ mutex_lock(&tm6000_devlist_mutex);
+ list_for_each_entry(dev, &tm6000_devlist, devlist) {
+ if (dev)
+ ops->fini(dev);
+ }
+
+ mutex_lock(&tm6000_extension_devlist_lock);
+ printk(KERN_INFO "tm6000: Remove (%s) extension\n", ops->name);
+ list_del(&ops->next);
+ mutex_unlock(&tm6000_extension_devlist_lock);
+ mutex_unlock(&tm6000_devlist_mutex);
+}
+EXPORT_SYMBOL(tm6000_unregister_extension);
+
+void tm6000_init_extension(struct tm6000_core *dev)
+{
+ struct tm6000_ops *ops = NULL;
+
+ mutex_lock(&tm6000_extension_devlist_lock);
+ if (!list_empty(&tm6000_extension_devlist)) {
+ list_for_each_entry(ops, &tm6000_extension_devlist, next) {
+ if (ops->init)
+ ops->init(dev);
+ }
+ }
+ mutex_unlock(&tm6000_extension_devlist_lock);
+}
+
+void tm6000_close_extension(struct tm6000_core *dev)
+{
+ struct tm6000_ops *ops = NULL;
+
+ mutex_lock(&tm6000_extension_devlist_lock);
+ if (!list_empty(&tm6000_extension_devlist)) {
+ list_for_each_entry(ops, &tm6000_extension_devlist, next) {
+ if (ops->fini)
+ ops->fini(dev);
+ }
+ }
+ mutex_unlock(&tm6000_extension_devlist_lock);
+}
diff --git a/drivers/staging/tm6000/tm6000-dvb.c b/drivers/staging/tm6000/tm6000-dvb.c
index eafc89c..86c1c8b 100644
--- a/drivers/staging/tm6000/tm6000-dvb.c
+++ b/drivers/staging/tm6000/tm6000-dvb.c
@@ -18,6 +18,7 @@
*/
#include <linux/kernel.h>
+#include <linux/slab.h>
#include <linux/usb.h>
#include "tm6000.h"
@@ -28,6 +29,7 @@
#include <media/tuner.h>
#include "tuner-xc2028.h"
+#include "xc5000.h"
static void inline print_err_status (struct tm6000_core *dev,
int packet, int status)
@@ -100,7 +102,10 @@
printk(KERN_INFO "tm6000: got start stream request %s\n",__FUNCTION__);
- tm6000_init_digital_mode(dev);
+ if (dev->mode != TM6000_MODE_DIGITAL) {
+ tm6000_init_digital_mode(dev);
+ dev->mode = TM6000_MODE_DIGITAL;
+ }
dvb->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
if(dvb->bulk_urb == NULL) {
@@ -254,27 +259,55 @@
dvb->adapter.priv = dev;
if (dvb->frontend) {
- struct xc2028_config cfg = {
- .i2c_adap = &dev->i2c_adap,
- .i2c_addr = dev->tuner_addr,
- };
+ switch (dev->tuner_type) {
+ case TUNER_XC2028: {
+ struct xc2028_config cfg = {
+ .i2c_adap = &dev->i2c_adap,
+ .i2c_addr = dev->tuner_addr,
+ };
- dvb->frontend->callback = tm6000_tuner_callback;
- ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
- if (ret < 0) {
- printk(KERN_ERR
- "tm6000: couldn't register frontend\n");
- goto adapter_err;
- }
+ dvb->frontend->callback = tm6000_tuner_callback;
+ ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
+ if (ret < 0) {
+ printk(KERN_ERR
+ "tm6000: couldn't register frontend\n");
+ goto adapter_err;
+ }
- if (!dvb_attach(xc2028_attach, dvb->frontend, &cfg)) {
- printk(KERN_ERR "tm6000: couldn't register "
- "frontend (xc3028)\n");
- ret = -EINVAL;
- goto frontend_err;
+ if (!dvb_attach(xc2028_attach, dvb->frontend, &cfg)) {
+ printk(KERN_ERR "tm6000: couldn't register "
+ "frontend (xc3028)\n");
+ ret = -EINVAL;
+ goto frontend_err;
+ }
+ printk(KERN_INFO "tm6000: XC2028/3028 asked to be "
+ "attached to frontend!\n");
+ break;
+ }
+ case TUNER_XC5000: {
+ struct xc5000_config cfg = {
+ .i2c_address = dev->tuner_addr,
+ };
+
+ dvb->frontend->callback = tm6000_xc5000_callback;
+ ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
+ if (ret < 0) {
+ printk(KERN_ERR
+ "tm6000: couldn't register frontend\n");
+ goto adapter_err;
+ }
+
+ if (!dvb_attach(xc5000_attach, dvb->frontend, &dev->i2c_adap, &cfg)) {
+ printk(KERN_ERR "tm6000: couldn't register "
+ "frontend (xc5000)\n");
+ ret = -EINVAL;
+ goto frontend_err;
+ }
+ printk(KERN_INFO "tm6000: XC5000 asked to be "
+ "attached to frontend!\n");
+ break;
+ }
}
- printk(KERN_INFO "tm6000: XC2028/3028 asked to be "
- "attached to frontend!\n");
} else {
printk(KERN_ERR "tm6000: no frontend found\n");
}
diff --git a/drivers/staging/tm6000/tm6000-video.c b/drivers/staging/tm6000/tm6000-video.c
index f2b7fe4..56fa371 100644
--- a/drivers/staging/tm6000/tm6000-video.c
+++ b/drivers/staging/tm6000/tm6000-video.c
@@ -48,7 +48,7 @@
#define TM6000_MIN_BUF 4
#define TM6000_DEF_BUF 8
-#define TM6000_MAX_ISO_PACKETS 40 /* Max number of ISO packets */
+#define TM6000_MAX_ISO_PACKETS 46 /* Max number of ISO packets */
/* Declare static vars that will be used as parameters */
static unsigned int vid_limit = 16; /* Video memory limit, in Mb */
@@ -205,7 +205,11 @@
c = (header >> 24) & 0xff;
/* split the header fields */
- size = (((header & 0x7e) << 1) -1) *4;
+ size = ((header & 0x7e) << 1);
+
+ if (size > 0)
+ size -= 4;
+
block = (header >> 7) & 0xf;
field = (header >> 11) & 0x1;
line = (header >> 12) & 0x1ff;
@@ -307,10 +311,12 @@
case TM6000_URB_MSG_PTS:
break;
case TM6000_URB_MSG_AUDIO:
-/* Need some code to process audio */
-printk ("%ld: cmd=%s, size=%d\n", jiffies,
+ /* Need some code to process audio */
+ printk ("%ld: cmd=%s, size=%d\n", jiffies,
tm6000_msg_type[cmd],size);
break;
+ case TM6000_URB_MSG_VBI:
+ break;
default:
dprintk (dev, V4L2_DEBUG_ISOC, "cmd=%s, size=%d\n",
tm6000_msg_type[cmd],size);
@@ -333,14 +339,23 @@
return rc;
}
-static int copy_streams(u8 *data, u8 *out_p, unsigned long len,
- struct urb *urb, struct tm6000_buffer **buf)
+static int copy_streams(u8 *data, unsigned long len,
+ struct urb *urb)
{
struct tm6000_dmaqueue *dma_q = urb->context;
struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq);
u8 *ptr=data, *endp=data+len;
unsigned long header=0;
int rc=0;
+ struct tm6000_buffer *buf;
+ char *outp = NULL;
+
+ get_next_buf(dma_q, &buf);
+ if (buf)
+ outp = videobuf_to_vmalloc(&buf->vb);
+
+ if (!outp)
+ return 0;
for (ptr=data; ptr<endp;) {
if (!dev->isoc_ctl.cmd) {
@@ -388,14 +403,14 @@
}
HEADER:
/* Copy or continue last copy */
- rc=copy_packet(urb,header,&ptr,endp,out_p,buf);
+ rc=copy_packet(urb,header,&ptr,endp,outp,&buf);
if (rc<0) {
buf=NULL;
printk(KERN_ERR "tm6000: buffer underrun at %ld\n",
jiffies);
return rc;
}
- if (!*buf)
+ if (!buf)
return 0;
}
@@ -404,31 +419,40 @@
/*
* Identify the tm5600/6000 buffer header type and properly handles
*/
-static int copy_multiplexed(u8 *ptr, u8 *out_p, unsigned long len,
- struct urb *urb, struct tm6000_buffer **buf)
+static int copy_multiplexed(u8 *ptr, unsigned long len,
+ struct urb *urb)
{
struct tm6000_dmaqueue *dma_q = urb->context;
struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq);
unsigned int pos=dev->isoc_ctl.pos,cpysize;
int rc=1;
+ struct tm6000_buffer *buf;
+ char *outp = NULL;
+
+ get_next_buf(dma_q, &buf);
+ if (buf)
+ outp = videobuf_to_vmalloc(&buf->vb);
+
+ if (!outp)
+ return 0;
while (len>0) {
- cpysize=min(len,(*buf)->vb.size-pos);
-//printk("Copying %d bytes (max=%lu) from %p to %p[%u]\n",cpysize,(*buf)->vb.size,ptr,out_p,pos);
- memcpy(&out_p[pos], ptr, cpysize);
+ cpysize=min(len,buf->vb.size-pos);
+ //printk("Copying %d bytes (max=%lu) from %p to %p[%u]\n",cpysize,(*buf)->vb.size,ptr,out_p,pos);
+ memcpy(&outp[pos], ptr, cpysize);
pos+=cpysize;
ptr+=cpysize;
len-=cpysize;
- if (pos >= (*buf)->vb.size) {
+ if (pos >= buf->vb.size) {
pos=0;
/* Announces that a new buffer were filled */
- buffer_filled (dev, dma_q, *buf);
+ buffer_filled (dev, dma_q, buf);
dprintk(dev, V4L2_DEBUG_ISOC, "new buffer filled\n");
- get_next_buf (dma_q, buf);
- if (!*buf)
+ get_next_buf (dma_q, &buf);
+ if (!buf)
break;
- out_p = videobuf_to_vmalloc(&((*buf)->vb));
- if (!out_p)
+ outp = videobuf_to_vmalloc(&(buf->vb));
+ if (!outp)
return rc;
pos = 0;
}
@@ -487,52 +511,36 @@
struct tm6000_dmaqueue *dma_q = urb->context;
struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq);
struct tm6000_buffer *buf;
- int i, len=0, rc=1;
- int size;
- char *outp = NULL, *p;
- unsigned long copied;
+ int i, len=0, rc=1, status;
+ char *p;
- get_next_buf(dma_q, &buf);
- if (buf)
- outp = videobuf_to_vmalloc(&buf->vb);
-
- if (!outp)
- return 0;
-
- size = buf->vb.size;
-
- copied=0;
-
- if (urb->status<0) {
- print_err_status (dev,-1,urb->status);
+ if (urb->status < 0) {
+ print_err_status (dev, -1, urb->status);
return 0;
}
for (i = 0; i < urb->number_of_packets; i++) {
- int status = urb->iso_frame_desc[i].status;
+ status = urb->iso_frame_desc[i].status;
if (status<0) {
print_err_status (dev,i,status);
continue;
}
- len=urb->iso_frame_desc[i].actual_length;
+ len = urb->iso_frame_desc[i].actual_length;
-// if (len>=TM6000_URB_MSG_LEN) {
- p=urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+ if (len > 0) {
+ p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
if (!urb->iso_frame_desc[i].status) {
- if ((buf->fmt->fourcc)==V4L2_PIX_FMT_TM6000) {
- rc=copy_multiplexed(p, outp, len, urb, &buf);
+ if ((dev->fourcc)==V4L2_PIX_FMT_TM6000) {
+ rc=copy_multiplexed(p, len, urb);
if (rc<=0)
return rc;
} else {
- copy_streams(p, outp, len, urb, &buf);
+ copy_streams(p, len, urb);
}
}
- copied += len;
- if (copied >= size || !buf)
- break;
-// }
+ }
}
return rc;
}
@@ -612,7 +620,7 @@
static int tm6000_prepare_isoc(struct tm6000_core *dev, unsigned int framesize)
{
struct tm6000_dmaqueue *dma_q = &dev->vidq;
- int i, j, sb_size, pipe, size, max_packets, num_bufs = 5;
+ int i, j, sb_size, pipe, size, max_packets, num_bufs = 8;
struct urb *urb;
/* De-allocates all pending stuff */
diff --git a/drivers/staging/tm6000/tm6000.h b/drivers/staging/tm6000/tm6000.h
index 6812d68..7bbaf26 100644
--- a/drivers/staging/tm6000/tm6000.h
+++ b/drivers/staging/tm6000/tm6000.h
@@ -168,6 +168,10 @@
struct i2c_adapter i2c_adap;
struct i2c_client i2c_client;
+
+ /* extension */
+ struct list_head devlist;
+
/* video for linux */
int users;
@@ -203,6 +207,16 @@
spinlock_t slock;
};
+#define TM6000_AUDIO 0x10
+
+struct tm6000_ops {
+ struct list_head next;
+ char *name;
+ int id;
+ int (*init)(struct tm6000_core *);
+ int (*fini)(struct tm6000_core *);
+};
+
struct tm6000_fh {
struct tm6000_core *dev;
@@ -232,6 +246,8 @@
int tm6000_get_reg16(struct tm6000_core *dev, u8 req, u16 value, u16 index);
int tm6000_get_reg32(struct tm6000_core *dev, u8 req, u16 value, u16 index);
int tm6000_set_reg (struct tm6000_core *dev, u8 req, u16 value, u16 index);
+int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep);
+
int tm6000_init (struct tm6000_core *dev);
int tm6000_init_analog_mode (struct tm6000_core *dev);
@@ -246,6 +262,13 @@
int tm6000_v4l2_exit(void);
void tm6000_set_fourcc_format(struct tm6000_core *dev);
+void tm6000_remove_from_devlist(struct tm6000_core *dev);
+void tm6000_add_into_devlist(struct tm6000_core *dev);
+int tm6000_register_extension(struct tm6000_ops *ops);
+void tm6000_unregister_extension(struct tm6000_ops *ops);
+void tm6000_init_extension(struct tm6000_core *dev);
+void tm6000_close_extension(struct tm6000_core *dev);
+
/* In tm6000-stds.c */
void tm6000_get_std_res(struct tm6000_core *dev);
int tm6000_set_standard (struct tm6000_core *dev, v4l2_std_id *norm);
@@ -275,7 +298,7 @@
int tm6000_queue_init(struct tm6000_core *dev);
/* In tm6000-alsa.c */
-int tm6000_audio_init(struct tm6000_core *dev, int idx);
+/*int tm6000_audio_init(struct tm6000_core *dev, int idx);*/
/* Debug stuff */
diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c
index 5240816..6a499f0 100644
--- a/drivers/staging/usbip/usbip_common.c
+++ b/drivers/staging/usbip/usbip_common.c
@@ -378,47 +378,67 @@
complete_and_exit(&ut->thread_done, 0);
}
+static void stop_rx_thread(struct usbip_device *ud)
+{
+ if (ud->tcp_rx.thread != NULL) {
+ send_sig(SIGKILL, ud->tcp_rx.thread, 1);
+ wait_for_completion(&ud->tcp_rx.thread_done);
+ usbip_udbg("rx_thread for ud %p has finished\n", ud);
+ }
+}
+
+static void stop_tx_thread(struct usbip_device *ud)
+{
+ if (ud->tcp_tx.thread != NULL) {
+ send_sig(SIGKILL, ud->tcp_tx.thread, 1);
+ wait_for_completion(&ud->tcp_tx.thread_done);
+ usbip_udbg("tx_thread for ud %p has finished\n", ud);
+ }
+}
+
int usbip_start_threads(struct usbip_device *ud)
{
/*
* threads are invoked per one device (per one connection).
*/
struct task_struct *th;
+ int err = 0;
th = kthread_run(usbip_thread, (void *)&ud->tcp_rx, "usbip");
if (IS_ERR(th)) {
printk(KERN_WARNING
"Unable to start control thread\n");
- return PTR_ERR(th);
+ err = PTR_ERR(th);
+ goto ust_exit;
}
+
th = kthread_run(usbip_thread, (void *)&ud->tcp_tx, "usbip");
if (IS_ERR(th)) {
printk(KERN_WARNING
"Unable to start control thread\n");
- return PTR_ERR(th);
+ err = PTR_ERR(th);
+ goto tx_thread_err;
}
/* confirm threads are starting */
wait_for_completion(&ud->tcp_rx.thread_done);
wait_for_completion(&ud->tcp_tx.thread_done);
+
return 0;
+
+tx_thread_err:
+ stop_rx_thread(ud);
+
+ust_exit:
+ return err;
}
EXPORT_SYMBOL_GPL(usbip_start_threads);
void usbip_stop_threads(struct usbip_device *ud)
{
/* kill threads related to this sdev, if v.c. exists */
- if (ud->tcp_rx.thread != NULL) {
- send_sig(SIGKILL, ud->tcp_rx.thread, 1);
- wait_for_completion(&ud->tcp_rx.thread_done);
- usbip_udbg("rx_thread for ud %p has finished\n", ud);
- }
-
- if (ud->tcp_tx.thread != NULL) {
- send_sig(SIGKILL, ud->tcp_tx.thread, 1);
- wait_for_completion(&ud->tcp_tx.thread_done);
- usbip_udbg("tx_thread for ud %p has finished\n", ud);
- }
+ stop_rx_thread(ud);
+ stop_tx_thread(ud);
}
EXPORT_SYMBOL_GPL(usbip_stop_threads);
diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.c b/drivers/staging/vme/bridges/vme_ca91cx42.c
index 0c82eb4..0f9ea58 100644
--- a/drivers/staging/vme/bridges/vme_ca91cx42.c
+++ b/drivers/staging/vme/bridges/vme_ca91cx42.c
@@ -523,7 +523,7 @@
}
if (image->bus_resource.name == NULL) {
- image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_KERNEL);
+ image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_ATOMIC);
if (image->bus_resource.name == NULL) {
dev_err(ca91cx42_bridge->parent, "Unable to allocate "
"memory for resource name\n");
diff --git a/drivers/staging/vme/bridges/vme_tsi148.c b/drivers/staging/vme/bridges/vme_tsi148.c
index abe88a3..f09cac1 100644
--- a/drivers/staging/vme/bridges/vme_tsi148.c
+++ b/drivers/staging/vme/bridges/vme_tsi148.c
@@ -828,7 +828,7 @@
return 0;
if (image->bus_resource.name == NULL) {
- image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_KERNEL);
+ image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_ATOMIC);
if (image->bus_resource.name == NULL) {
dev_err(tsi148_bridge->parent, "Unable to allocate "
"memory for resource name\n");
diff --git a/drivers/staging/wlags49_h2/Kconfig b/drivers/staging/wlags49_h2/Kconfig
index b6fc2ca..3efcbf8 100644
--- a/drivers/staging/wlags49_h2/Kconfig
+++ b/drivers/staging/wlags49_h2/Kconfig
@@ -1,9 +1,11 @@
config WLAGS49_H2
tristate "Agere Systems HERMES II Wireless PC Card Model 0110"
- depends on WLAN && WIRELESS_EXT && PCMCIA
+ depends on WLAN && PCMCIA
+ select WIRELESS_EXT
select WEXT_SPY
+ select WEXT_PRIV
---help---
- Driver for wireless cards using Agere's HERMES II chipset
- which are identified with Manufacture ID: 0156,0003
- The software is a modified version of wl_lkm_722_abg.tar.gz
- from the Agere Systems website, addapted for Ubuntu 9.04.
+ Driver for wireless cards using Agere's HERMES II chipset
+ which are identified with Manufacture ID: 0156,0003
+ The software is a modified version of wl_lkm_722_abg.tar.gz
+ from the Agere Systems website, addapted for Ubuntu 9.04.
diff --git a/drivers/staging/wlags49_h2/wl_enc.c b/drivers/staging/wlags49_h2/wl_enc.c
index 48c44c8..26cf548 100644
--- a/drivers/staging/wlags49_h2/wl_enc.c
+++ b/drivers/staging/wlags49_h2/wl_enc.c
@@ -62,6 +62,7 @@
/*******************************************************************************
* include files
******************************************************************************/
+#include <linux/string.h>
#include <wl_version.h>
#include <debug.h>
diff --git a/drivers/staging/wlags49_h2/wl_sysfs.h b/drivers/staging/wlags49_h2/wl_sysfs.h
index 6d96d03..fa658c3 100644
--- a/drivers/staging/wlags49_h2/wl_sysfs.h
+++ b/drivers/staging/wlags49_h2/wl_sysfs.h
@@ -2,6 +2,6 @@
extern void register_wlags_sysfs(struct net_device *);
extern void unregister_wlags_sysfs(struct net_device *);
#else
-static void register_wlags_sysfs(struct net_device *) { return; };
-static void unregister_wlags_sysfs(struct net_device *) { return; };
+static inline void register_wlags_sysfs(struct net_device *net) { }
+static inline void unregister_wlags_sysfs(struct net_device *net) { }
#endif
diff --git a/drivers/staging/wlags49_h25/Kconfig b/drivers/staging/wlags49_h25/Kconfig
index dcc1709..bf5664a 100644
--- a/drivers/staging/wlags49_h25/Kconfig
+++ b/drivers/staging/wlags49_h25/Kconfig
@@ -1,9 +1,11 @@
config WLAGS49_H25
tristate "Linksys HERMES II.5 WCF54G_Wireless-G_CompactFlash_Card"
- depends on WLAN && WIRELESS_EXT && PCMCIA
+ depends on WLAN && PCMCIA
+ select WIRELESS_EXT
select WEXT_SPY
+ select WEXT_PRIV
---help---
- Driver for wireless cards using Agere's HERMES II.5 chipset
- which are identified with Manufacture ID: 0156,0004
- The software is a modified version of wl_lkm_722_abg.tar.gz
- from the Agere Systems website, addapted for Ubuntu 9.04.
+ Driver for wireless cards using Agere's HERMES II.5 chipset
+ which are identified with Manufacture ID: 0156,0004
+ The software is a modified version of wl_lkm_722_abg.tar.gz
+ from the Agere Systems website, addapted for Ubuntu 9.04.
diff --git a/drivers/staging/xgifb/Kconfig b/drivers/staging/xgifb/Kconfig
new file mode 100644
index 0000000..bb0ca59
--- /dev/null
+++ b/drivers/staging/xgifb/Kconfig
@@ -0,0 +1,11 @@
+config FB_XGI
+ tristate "XGI display support"
+ depends on FB && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This driver supports notebooks with XGI Z7,Z9,Z11 PCI chips.
+ Say Y if you have such a graphics card.
+ To compile this driver as a module, choose M here: the
+ module will be called xgifb.ko
diff --git a/drivers/staging/xgifb/Makefile b/drivers/staging/xgifb/Makefile
new file mode 100644
index 0000000..2a31770
--- /dev/null
+++ b/drivers/staging/xgifb/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_FB_XGI) += xgifb.o
+
+xgifb-objs := XGI_main_26.o XGI_accel.o vb_init.o vb_setmode.o vb_util.o vb_ext.o
+
diff --git a/drivers/staging/xgifb/TODO b/drivers/staging/xgifb/TODO
new file mode 100644
index 0000000..7d71019
--- /dev/null
+++ b/drivers/staging/xgifb/TODO
@@ -0,0 +1,15 @@
+This drivers still need a lot of work. I can list all cleanups to do but it's
+going to be long. So, I'm writing "cleanups" and not the list.
+
+Arnaud
+
+TODO:
+- clean ups
+- fix build warnings when module
+- sort out dup ids with SiS driver
+- remove useless/wrong/unused #ifdef/code/...
+- fix printk usages
+- get rid of non-linux related stuff
+
+Please send patches to:
+Arnaud Patard <apatard@mandriva.com>
diff --git a/drivers/staging/xgifb/XGI.h b/drivers/staging/xgifb/XGI.h
new file mode 100644
index 0000000..87803dd
--- /dev/null
+++ b/drivers/staging/xgifb/XGI.h
@@ -0,0 +1,10 @@
+#ifndef _XGI_H
+#define _XGI_H
+
+#if 1
+#define TWDEBUG(x)
+#else
+#define TWDEBUG(x) printk(KERN_INFO x "\n");
+#endif
+
+#endif
diff --git a/drivers/staging/xgifb/XGI_accel.c b/drivers/staging/xgifb/XGI_accel.c
new file mode 100644
index 0000000..86ec342
--- /dev/null
+++ b/drivers/staging/xgifb/XGI_accel.c
@@ -0,0 +1,596 @@
+/*
+ * XGI 300/630/730/540/315/550/650/740 frame buffer driver
+ * for Linux kernels 2.4.x and 2.5.x
+ *
+ * 2D acceleration part
+ *
+ * Based on the X driver's XGI300_accel.c which is
+ * Copyright Xavier Ducoin <x.ducoin@lectra.com>
+ * Copyright 2002 by Thomas Winischhofer, Vienna, Austria
+ * and XGI310_accel.c which is
+ * Copyright 2002 by Thomas Winischhofer, Vienna, Austria
+ *
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ * (see http://www.winischhofer.net/
+ * for more information and updates)
+ */
+
+//#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/console.h>
+#include <linux/selection.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/vt_kern.h>
+#include <linux/capability.h>
+#include <linux/fs.h>
+#include <linux/agp_backend.h>
+
+#include <linux/types.h>
+/*
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#include <linux/XGIfb.h>
+#else
+#include <video/XGIfb.h>
+#endif
+*/
+#include <asm/io.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb24.h>
+#include <video/fbcon-cfb32.h>
+#endif
+
+#include "osdef.h"
+#include "vgatypes.h"
+#include "vb_struct.h"
+#include "XGIfb.h"
+#include "XGI_accel.h"
+
+
+extern struct video_info xgi_video_info;
+extern int XGIfb_accel;
+
+static const int XGIALUConv[] =
+{
+ 0x00, /* dest = 0; 0, GXclear, 0 */
+ 0x88, /* dest &= src; DSa, GXand, 0x1 */
+ 0x44, /* dest = src & ~dest; SDna, GXandReverse, 0x2 */
+ 0xCC, /* dest = src; S, GXcopy, 0x3 */
+ 0x22, /* dest &= ~src; DSna, GXandInverted, 0x4 */
+ 0xAA, /* dest = dest; D, GXnoop, 0x5 */
+ 0x66, /* dest = ^src; DSx, GXxor, 0x6 */
+ 0xEE, /* dest |= src; DSo, GXor, 0x7 */
+ 0x11, /* dest = ~src & ~dest; DSon, GXnor, 0x8 */
+ 0x99, /* dest ^= ~src ; DSxn, GXequiv, 0x9 */
+ 0x55, /* dest = ~dest; Dn, GXInvert, 0xA */
+ 0xDD, /* dest = src|~dest ; SDno, GXorReverse, 0xB */
+ 0x33, /* dest = ~src; Sn, GXcopyInverted, 0xC */
+ 0xBB, /* dest |= ~src; DSno, GXorInverted, 0xD */
+ 0x77, /* dest = ~src|~dest; DSan, GXnand, 0xE */
+ 0xFF, /* dest = 0xFF; 1, GXset, 0xF */
+};
+/* same ROP but with Pattern as Source */
+static const int XGIPatALUConv[] =
+{
+ 0x00, /* dest = 0; 0, GXclear, 0 */
+ 0xA0, /* dest &= src; DPa, GXand, 0x1 */
+ 0x50, /* dest = src & ~dest; PDna, GXandReverse, 0x2 */
+ 0xF0, /* dest = src; P, GXcopy, 0x3 */
+ 0x0A, /* dest &= ~src; DPna, GXandInverted, 0x4 */
+ 0xAA, /* dest = dest; D, GXnoop, 0x5 */
+ 0x5A, /* dest = ^src; DPx, GXxor, 0x6 */
+ 0xFA, /* dest |= src; DPo, GXor, 0x7 */
+ 0x05, /* dest = ~src & ~dest; DPon, GXnor, 0x8 */
+ 0xA5, /* dest ^= ~src ; DPxn, GXequiv, 0x9 */
+ 0x55, /* dest = ~dest; Dn, GXInvert, 0xA */
+ 0xF5, /* dest = src|~dest ; PDno, GXorReverse, 0xB */
+ 0x0F, /* dest = ~src; Pn, GXcopyInverted, 0xC */
+ 0xAF, /* dest |= ~src; DPno, GXorInverted, 0xD */
+ 0x5F, /* dest = ~src|~dest; DPan, GXnand, 0xE */
+ 0xFF, /* dest = 0xFF; 1, GXset, 0xF */
+};
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)
+static const unsigned char myrops[] = {
+ 3, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
+ };
+#endif
+
+/* 300 series */
+#if 0
+static void
+XGI300Sync(void)
+{
+ XGI300Idle
+}
+#endif
+static void
+XGI310Sync(void)
+{
+ XGI310Idle
+}
+#if 0
+static void
+XGI300SetupForScreenToScreenCopy(int xdir, int ydir, int rop,
+ unsigned int planemask, int trans_color)
+{
+ XGI300SetupDSTColorDepth(xgi_video_info.DstColor);
+ XGI300SetupSRCPitch(xgi_video_info.video_linelength)
+ XGI300SetupDSTRect(xgi_video_info.video_linelength, 0xFFF)
+
+ if(trans_color != -1) {
+ XGI300SetupROP(0x0A)
+ XGI300SetupSRCTrans(trans_color)
+ XGI300SetupCMDFlag(TRANSPARENT_BITBLT)
+ } else {
+ XGI300SetupROP(XGIALUConv[rop])
+ }
+ if(xdir > 0) {
+ XGI300SetupCMDFlag(X_INC)
+ }
+ if(ydir > 0) {
+ XGI300SetupCMDFlag(Y_INC)
+ }
+}
+
+static void
+XGI300SubsequentScreenToScreenCopy(int src_x, int src_y, int dst_x, int dst_y,
+ int width, int height)
+{
+ long srcbase, dstbase;
+
+ srcbase = dstbase = 0;
+ if (src_y >= 2048) {
+ srcbase = xgi_video_info.video_linelength * src_y;
+ src_y = 0;
+ }
+ if (dst_y >= 2048) {
+ dstbase = xgi_video_info.video_linelength * dst_y;
+ dst_y = 0;
+ }
+
+ XGI300SetupSRCBase(srcbase);
+ XGI300SetupDSTBase(dstbase);
+
+ if(!(xgi_video_info.CommandReg & X_INC)) {
+ src_x += width-1;
+ dst_x += width-1;
+ }
+ if(!(xgi_video_info.CommandReg & Y_INC)) {
+ src_y += height-1;
+ dst_y += height-1;
+ }
+ XGI300SetupRect(width, height)
+ XGI300SetupSRCXY(src_x, src_y)
+ XGI300SetupDSTXY(dst_x, dst_y)
+ XGI300DoCMD
+}
+
+static void
+XGI300SetupForSolidFill(int color, int rop, unsigned int planemask)
+{
+ XGI300SetupPATFG(color)
+ XGI300SetupDSTRect(xgi_video_info.video_linelength, 0xFFF)
+ XGI300SetupDSTColorDepth(xgi_video_info.DstColor);
+ XGI300SetupROP(XGIPatALUConv[rop])
+ XGI300SetupCMDFlag(PATFG)
+}
+
+static void
+XGI300SubsequentSolidFillRect(int x, int y, int w, int h)
+{
+ long dstbase;
+
+ dstbase = 0;
+ if(y >= 2048) {
+ dstbase = xgi_video_info.video_linelength * y;
+ y = 0;
+ }
+ XGI300SetupDSTBase(dstbase)
+ XGI300SetupDSTXY(x,y)
+ XGI300SetupRect(w,h)
+ XGI300SetupCMDFlag(X_INC | Y_INC | BITBLT)
+ XGI300DoCMD
+}
+#endif
+/* 310/325 series ------------------------------------------------ */
+
+static void
+XGI310SetupForScreenToScreenCopy(int xdir, int ydir, int rop,
+ unsigned int planemask, int trans_color)
+{
+ XGI310SetupDSTColorDepth(xgi_video_info.DstColor);
+ XGI310SetupSRCPitch(xgi_video_info.video_linelength)
+ XGI310SetupDSTRect(xgi_video_info.video_linelength, 0xFFF)
+ if (trans_color != -1) {
+ XGI310SetupROP(0x0A)
+ XGI310SetupSRCTrans(trans_color)
+ XGI310SetupCMDFlag(TRANSPARENT_BITBLT)
+ } else {
+ XGI310SetupROP(XGIALUConv[rop])
+ /* Set command - not needed, both 0 */
+ /* XGISetupCMDFlag(BITBLT | SRCVIDEO) */
+ }
+ XGI310SetupCMDFlag(xgi_video_info.XGI310_AccelDepth)
+ /* TW: The 310/325 series is smart enough to know the direction */
+}
+
+static void
+XGI310SubsequentScreenToScreenCopy(int src_x, int src_y, int dst_x, int dst_y,
+ int width, int height)
+{
+ long srcbase, dstbase;
+ int mymin, mymax;
+
+ srcbase = dstbase = 0;
+ mymin = min(src_y, dst_y);
+ mymax = max(src_y, dst_y);
+
+ /* Although the chip knows the direction to use
+ * if the source and destination areas overlap,
+ * that logic fails if we fiddle with the bitmap
+ * addresses. Therefore, we check if the source
+ * and destination blitting areas overlap and
+ * adapt the bitmap addresses synchronously
+ * if the coordinates exceed the valid range.
+ * The the areas do not overlap, we do our
+ * normal check.
+ */
+ if((mymax - mymin) < height) {
+ if((src_y >= 2048) || (dst_y >= 2048)) {
+ srcbase = xgi_video_info.video_linelength * mymin;
+ dstbase = xgi_video_info.video_linelength * mymin;
+ src_y -= mymin;
+ dst_y -= mymin;
+ }
+ } else {
+ if(src_y >= 2048) {
+ srcbase = xgi_video_info.video_linelength * src_y;
+ src_y = 0;
+ }
+ if(dst_y >= 2048) {
+ dstbase = xgi_video_info.video_linelength * dst_y;
+ dst_y = 0;
+ }
+ }
+
+ XGI310SetupSRCBase(srcbase);
+ XGI310SetupDSTBase(dstbase);
+ XGI310SetupRect(width, height)
+ XGI310SetupSRCXY(src_x, src_y)
+ XGI310SetupDSTXY(dst_x, dst_y)
+ XGI310DoCMD
+}
+
+static void
+XGI310SetupForSolidFill(int color, int rop, unsigned int planemask)
+{
+ XGI310SetupPATFG(color)
+ XGI310SetupDSTRect(xgi_video_info.video_linelength, 0xFFF)
+ XGI310SetupDSTColorDepth(xgi_video_info.DstColor);
+ XGI310SetupROP(XGIPatALUConv[rop])
+ XGI310SetupCMDFlag(PATFG | xgi_video_info.XGI310_AccelDepth)
+}
+
+static void
+XGI310SubsequentSolidFillRect(int x, int y, int w, int h)
+{
+ long dstbase;
+
+ dstbase = 0;
+ if(y >= 2048) {
+ dstbase = xgi_video_info.video_linelength * y;
+ y = 0;
+ }
+ XGI310SetupDSTBase(dstbase)
+ XGI310SetupDSTXY(x,y)
+ XGI310SetupRect(w,h)
+ XGI310SetupCMDFlag(BITBLT)
+ XGI310DoCMD
+}
+
+/* --------------------------------------------------------------------- */
+
+/* The exported routines */
+
+int XGIfb_initaccel(void)
+{
+#ifdef XGIFB_USE_SPINLOCKS
+ spin_lock_init(&xgi_video_info.lockaccel);
+#endif
+ return(0);
+}
+
+void XGIfb_syncaccel(void)
+{
+
+ XGI310Sync();
+
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34) /* --- KERNEL 2.5.34 and later --- */
+
+int fbcon_XGI_sync(struct fb_info *info)
+{
+ if(!XGIfb_accel) return 0;
+ CRITFLAGS
+
+ XGI310Sync();
+
+ CRITEND
+ return 0;
+}
+
+void fbcon_XGI_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+ int col=0;
+ CRITFLAGS
+
+
+ if(!rect->width || !rect->height)
+ return;
+
+ if(!XGIfb_accel) {
+ cfb_fillrect(info, rect);
+ return;
+ }
+
+ switch(info->var.bits_per_pixel) {
+ case 8: col = rect->color;
+ break;
+ case 16: col = ((u32 *)(info->pseudo_palette))[rect->color];
+ break;
+ case 32: col = ((u32 *)(info->pseudo_palette))[rect->color];
+ break;
+ }
+
+
+ CRITBEGIN
+ XGI310SetupForSolidFill(col, myrops[rect->rop], 0);
+ XGI310SubsequentSolidFillRect(rect->dx, rect->dy, rect->width, rect->height);
+ CRITEND
+ XGI310Sync();
+
+
+}
+
+void fbcon_XGI_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+ int xdir, ydir;
+ CRITFLAGS
+
+
+ if(!XGIfb_accel) {
+ cfb_copyarea(info, area);
+ return;
+ }
+
+ if(!area->width || !area->height)
+ return;
+
+ if(area->sx < area->dx) xdir = 0;
+ else xdir = 1;
+ if(area->sy < area->dy) ydir = 0;
+ else ydir = 1;
+
+ CRITBEGIN
+ XGI310SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
+ XGI310SubsequentScreenToScreenCopy(area->sx, area->sy, area->dx, area->dy, area->width, area->height);
+ CRITEND
+ XGI310Sync();
+
+}
+
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33) /* ------ KERNEL <2.5.34 ------ */
+
+void fbcon_XGI_bmove(struct display *p, int srcy, int srcx,
+ int dsty, int dstx, int height, int width)
+{
+ int xdir, ydir;
+ CRITFLAGS
+
+ if(!xgi_video_info.accel) {
+ switch(xgi_video_info.video_bpp) {
+ case 8:
+#ifdef FBCON_HAS_CFB8
+ fbcon_cfb8_bmove(p, srcy, srcx, dsty, dstx, height, width);
+#endif
+ break;
+ case 16:
+#ifdef FBCON_HAS_CFB16
+ fbcon_cfb16_bmove(p, srcy, srcx, dsty, dstx, height, width);
+#endif
+ break;
+ case 32:
+#ifdef FBCON_HAS_CFB32
+ fbcon_cfb32_bmove(p, srcy, srcx, dsty, dstx, height, width);
+#endif
+ break;
+ }
+ return;
+ }
+
+ srcx *= fontwidth(p);
+ srcy *= fontheight(p);
+ dstx *= fontwidth(p);
+ dsty *= fontheight(p);
+ width *= fontwidth(p);
+ height *= fontheight(p);
+
+ if(srcx < dstx) xdir = 0;
+ else xdir = 1;
+ if(srcy < dsty) ydir = 0;
+ else ydir = 1;
+
+
+ CRITBEGIN
+ XGI310SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
+ XGI310SubsequentScreenToScreenCopy(srcx, srcy, dstx, dsty, width, height);
+ CRITEND
+ XGI310Sync();
+#if 0
+ printk(KERN_INFO "XGI_bmove sx %d sy %d dx %d dy %d w %d h %d\n",
+ srcx, srcy, dstx, dsty, width, height);
+#endif
+
+}
+
+
+static void fbcon_XGI_clear(struct vc_data *conp, struct display *p,
+ int srcy, int srcx, int height, int width, int color)
+{
+ CRITFLAGS
+
+ srcx *= fontwidth(p);
+ srcy *= fontheight(p);
+ width *= fontwidth(p);
+ height *= fontheight(p);
+
+
+ CRITBEGIN
+ XGI310SetupForSolidFill(color, 3, 0);
+ XGI310SubsequentSolidFillRect(srcx, srcy, width, height);
+ CRITEND
+ XGI310Sync();
+
+}
+
+void fbcon_XGI_clear8(struct vc_data *conp, struct display *p,
+ int srcy, int srcx, int height, int width)
+{
+ u32 bgx;
+
+ if(!xgi_video_info.accel) {
+#ifdef FBCON_HAS_CFB8
+ fbcon_cfb8_clear(conp, p, srcy, srcx, height, width);
+#endif
+ return;
+ }
+
+ bgx = attr_bgcol_ec(p, conp);
+ fbcon_XGI_clear(conp, p, srcy, srcx, height, width, bgx);
+}
+
+void fbcon_XGI_clear16(struct vc_data *conp, struct display *p,
+ int srcy, int srcx, int height, int width)
+{
+ u32 bgx;
+ if(!xgi_video_info.accel) {
+#ifdef FBCON_HAS_CFB16
+ fbcon_cfb16_clear(conp, p, srcy, srcx, height, width);
+#endif
+ return;
+ }
+
+ bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
+ fbcon_XGI_clear(conp, p, srcy, srcx, height, width, bgx);
+}
+
+void fbcon_XGI_clear32(struct vc_data *conp, struct display *p,
+ int srcy, int srcx, int height, int width)
+{
+ u32 bgx;
+
+ if(!xgi_video_info.accel) {
+#ifdef FBCON_HAS_CFB32
+ fbcon_cfb32_clear(conp, p, srcy, srcx, height, width);
+#endif
+ return;
+ }
+
+ bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
+ fbcon_XGI_clear(conp, p, srcy, srcx, height, width, bgx);
+}
+
+void fbcon_XGI_revc(struct display *p, int srcx, int srcy)
+{
+ CRITFLAGS
+
+ if(!xgi_video_info.accel) {
+ switch(xgi_video_info.video_bpp) {
+ case 16:
+#ifdef FBCON_HAS_CFB16
+ fbcon_cfb16_revc(p, srcx, srcy);
+#endif
+ break;
+ case 32:
+#ifdef FBCON_HAS_CFB32
+ fbcon_cfb32_revc(p, srcx, srcy);
+#endif
+ break;
+ }
+ return;
+ }
+
+ srcx *= fontwidth(p);
+ srcy *= fontheight(p);
+
+
+ CRITBEGIN
+ XGI310SetupForSolidFill(0, 0x0a, 0);
+ XGI310SubsequentSolidFillRect(srcx, srcy, fontwidth(p), fontheight(p));
+ CRITEND
+ XGI310Sync();
+
+}
+
+#ifdef FBCON_HAS_CFB8
+struct display_switch fbcon_XGI8 = {
+ setup: fbcon_cfb8_setup,
+ bmove: fbcon_XGI_bmove,
+ clear: fbcon_XGI_clear8,
+ putc: fbcon_cfb8_putc,
+ putcs: fbcon_cfb8_putcs,
+ revc: fbcon_cfb8_revc,
+ clear_margins: fbcon_cfb8_clear_margins,
+ fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+#endif
+#ifdef FBCON_HAS_CFB16
+struct display_switch fbcon_XGI16 = {
+ setup: fbcon_cfb16_setup,
+ bmove: fbcon_XGI_bmove,
+ clear: fbcon_XGI_clear16,
+ putc: fbcon_cfb16_putc,
+ putcs: fbcon_cfb16_putcs,
+ revc: fbcon_XGI_revc,
+ clear_margins: fbcon_cfb16_clear_margins,
+ fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+#endif
+#ifdef FBCON_HAS_CFB32
+struct display_switch fbcon_XGI32 = {
+ setup: fbcon_cfb32_setup,
+ bmove: fbcon_XGI_bmove,
+ clear: fbcon_XGI_clear32,
+ putc: fbcon_cfb32_putc,
+ putcs: fbcon_cfb32_putcs,
+ revc: fbcon_XGI_revc,
+ clear_margins: fbcon_cfb32_clear_margins,
+ fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+#endif
+
+#endif /* KERNEL VERSION */
+
+
diff --git a/drivers/staging/xgifb/XGI_accel.h b/drivers/staging/xgifb/XGI_accel.h
new file mode 100644
index 0000000..04e1267
--- /dev/null
+++ b/drivers/staging/xgifb/XGI_accel.h
@@ -0,0 +1,511 @@
+/*
+ * XGI 300/630/730/540/315/550/650/740 frame buffer driver
+ * for Linux kernels 2.4.x and 2.5.x
+ *
+ * 2D acceleration part
+ *
+ * Based on the X driver's XGI300_accel.h which is
+ * Copyright Xavier Ducoin <x.ducoin@lectra.com>
+ * Copyright 2002 by Thomas Winischhofer, Vienna, Austria
+ * and XGI310_accel.h which is
+ * Copyright 2002 by Thomas Winischhofer, Vienna, Austria
+ *
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>:
+ * (see http://www.winischhofer.net/
+ * for more information and updates)
+ */
+
+#ifndef _XGIFB_ACCEL_H
+#define _XGIFB_ACCEL_H
+
+/* Guard accelerator accesses with spin_lock_irqsave? Works well without. */
+#undef XGIFB_USE_SPINLOCKS
+
+#ifdef XGIFB_USE_SPINLOCKS
+#include <linux/spinlock.h>
+#define CRITBEGIN spin_lock_irqsave(&xgi_video_info.lockaccel), critflags);
+#define CRITEND spin_unlock_irqrestore(&xgi_video_info.lockaccel), critflags);
+#define CRITFLAGS unsigned long critflags;
+#else
+#define CRITBEGIN
+#define CRITEND
+#define CRITFLAGS
+#endif
+
+/* Definitions for the XGI engine communication. */
+
+#define PATREGSIZE 384 /* Pattern register size. 384 bytes @ 0x8300 */
+#define BR(x) (0x8200 | (x) << 2)
+#define PBR(x) (0x8300 | (x) << 2)
+
+/* XGI300 engine commands */
+#define BITBLT 0x00000000 /* Blit */
+#define COLOREXP 0x00000001 /* Color expand */
+#define ENCOLOREXP 0x00000002 /* Enhanced color expand */
+#define MULTIPLE_SCANLINE 0x00000003 /* ? */
+#define LINE 0x00000004 /* Draw line */
+#define TRAPAZOID_FILL 0x00000005 /* Fill trapezoid */
+#define TRANSPARENT_BITBLT 0x00000006 /* Transparent Blit */
+
+/* Additional engine commands for 310/325 */
+#define ALPHA_BLEND 0x00000007 /* Alpha blend ? */
+#define A3D_FUNCTION 0x00000008 /* 3D command ? */
+#define CLEAR_Z_BUFFER 0x00000009 /* ? */
+#define GRADIENT_FILL 0x0000000A /* Gradient fill */
+#define STRETCH_BITBLT 0x0000000B /* Stretched Blit */
+
+/* source select */
+#define SRCVIDEO 0x00000000 /* source is video RAM */
+#define SRCSYSTEM 0x00000010 /* source is system memory */
+#define SRCCPUBLITBUF SRCSYSTEM /* source is CPU-driven BitBuffer (for color expand) */
+#define SRCAGP 0x00000020 /* source is AGP memory (?) */
+
+/* Pattern flags */
+#define PATFG 0x00000000 /* foreground color */
+#define PATPATREG 0x00000040 /* pattern in pattern buffer (0x8300) */
+#define PATMONO 0x00000080 /* mono pattern */
+
+/* blitting direction (300 series only) */
+#define X_INC 0x00010000
+#define X_DEC 0x00000000
+#define Y_INC 0x00020000
+#define Y_DEC 0x00000000
+
+/* Clipping flags */
+#define NOCLIP 0x00000000
+#define NOMERGECLIP 0x04000000
+#define CLIPENABLE 0x00040000
+#define CLIPWITHOUTMERGE 0x04040000
+
+/* Transparency */
+#define OPAQUE 0x00000000
+#define TRANSPARENT 0x00100000
+
+/* ? */
+#define DSTAGP 0x02000000
+#define DSTVIDEO 0x02000000
+
+/* Line */
+#define LINE_STYLE 0x00800000
+#define NO_RESET_COUNTER 0x00400000
+#define NO_LAST_PIXEL 0x00200000
+
+/* Subfunctions for Color/Enhanced Color Expansion (310/325 only) */
+#define COLOR_TO_MONO 0x00100000
+#define AA_TEXT 0x00200000
+
+/* Some general registers for 310/325 series */
+#define SRC_ADDR 0x8200
+#define SRC_PITCH 0x8204
+#define AGP_BASE 0x8206 /* color-depth dependent value */
+#define SRC_Y 0x8208
+#define SRC_X 0x820A
+#define DST_Y 0x820C
+#define DST_X 0x820E
+#define DST_ADDR 0x8210
+#define DST_PITCH 0x8214
+#define DST_HEIGHT 0x8216
+#define RECT_WIDTH 0x8218
+#define RECT_HEIGHT 0x821A
+#define PAT_FGCOLOR 0x821C
+#define PAT_BGCOLOR 0x8220
+#define SRC_FGCOLOR 0x8224
+#define SRC_BGCOLOR 0x8228
+#define MONO_MASK 0x822C
+#define LEFT_CLIP 0x8234
+#define TOP_CLIP 0x8236
+#define RIGHT_CLIP 0x8238
+#define BOTTOM_CLIP 0x823A
+#define COMMAND_READY 0x823C
+#define FIRE_TRIGGER 0x8240
+
+#define PATTERN_REG 0x8300 /* 384 bytes pattern buffer */
+
+/* Line registers */
+#define LINE_X0 SRC_Y
+#define LINE_X1 DST_Y
+#define LINE_Y0 SRC_X
+#define LINE_Y1 DST_X
+#define LINE_COUNT RECT_WIDTH
+#define LINE_STYLE_PERIOD RECT_HEIGHT
+#define LINE_STYLE_0 MONO_MASK
+#define LINE_STYLE_1 0x8230
+#define LINE_XN PATTERN_REG
+#define LINE_YN PATTERN_REG+2
+
+/* Transparent bitblit registers */
+#define TRANS_DST_KEY_HIGH PAT_FGCOLOR
+#define TRANS_DST_KEY_LOW PAT_BGCOLOR
+#define TRANS_SRC_KEY_HIGH SRC_FGCOLOR
+#define TRANS_SRC_KEY_LOW SRC_BGCOLOR
+
+/* Queue */
+#define Q_BASE_ADDR 0x85C0 /* Base address of software queue (?) */
+#define Q_WRITE_PTR 0x85C4 /* Current write pointer (?) */
+#define Q_READ_PTR 0x85C8 /* Current read pointer (?) */
+#define Q_STATUS 0x85CC /* queue status */
+
+
+#define MMIO_IN8(base, offset) \
+ *(volatile u8 *)(((u8*)(base)) + (offset))
+#define MMIO_IN16(base, offset) \
+ *(volatile u16 *)(void *)(((u8*)(base)) + (offset))
+#define MMIO_IN32(base, offset) \
+ *(volatile u32 *)(void *)(((u8*)(base)) + (offset))
+#define MMIO_OUT8(base, offset, val) \
+ *(volatile u8 *)(((u8*)(base)) + (offset)) = (val)
+#define MMIO_OUT16(base, offset, val) \
+ *(volatile u16 *)(void *)(((u8*)(base)) + (offset)) = (val)
+#define MMIO_OUT32(base, offset, val) \
+ *(volatile u32 *)(void *)(((u8*)(base)) + (offset)) = (val)
+
+
+
+/* ------------- XGI 300 series -------------- */
+
+/* Macros to do useful things with the XGI BitBLT engine */
+
+/* BR(16) (0x8420):
+
+ bit 31 2D engine: 1 is idle,
+ bit 30 3D engine: 1 is idle,
+ bit 29 Command queue: 1 is empty
+
+ bits 28:24: Current CPU driven BitBlt buffer stage bit[4:0]
+
+ bits 15:0: Current command queue length
+
+*/
+
+/* TW: BR(16)+2 = 0x8242 */
+
+int xgiCmdQueLen;
+
+#define XGI300Idle \
+ { \
+ while( (MMIO_IN16(xgi_video_info.mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
+ while( (MMIO_IN16(xgi_video_info.mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
+ while( (MMIO_IN16(xgi_video_info.mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
+ xgiCmdQueLen=MMIO_IN16(xgi_video_info.mmio_vbase, 0x8240); \
+ }
+/* TW: (do three times, because 2D engine seems quite unsure about whether or not it's idle) */
+
+#define XGI300SetupSRCBase(base) \
+ if (xgiCmdQueLen <= 0) XGI300Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, BR(0), base);\
+ xgiCmdQueLen --;
+
+#define XGI300SetupSRCPitch(pitch) \
+ if (xgiCmdQueLen <= 0) XGI300Idle;\
+ MMIO_OUT16(xgi_video_info.mmio_vbase, BR(1), pitch);\
+ xgiCmdQueLen --;
+
+#define XGI300SetupSRCXY(x,y) \
+ if (xgiCmdQueLen <= 0) XGI300Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, BR(2), (x)<<16 | (y) );\
+ xgiCmdQueLen --;
+
+#define XGI300SetupDSTBase(base) \
+ if (xgiCmdQueLen <= 0) XGI300Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, BR(4), base);\
+ xgiCmdQueLen --;
+
+#define XGI300SetupDSTXY(x,y) \
+ if (xgiCmdQueLen <= 0) XGI300Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, BR(3), (x)<<16 | (y) );\
+ xgiCmdQueLen --;
+
+#define XGI300SetupDSTRect(x,y) \
+ if (xgiCmdQueLen <= 0) XGI300Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, BR(5), (y)<<16 | (x) );\
+ xgiCmdQueLen --;
+
+#define XGI300SetupDSTColorDepth(bpp) \
+ if (xgiCmdQueLen <= 0) XGI300Idle;\
+ MMIO_OUT16(xgi_video_info.mmio_vbase, BR(1)+2, bpp);\
+ xgiCmdQueLen --;
+
+#define XGI300SetupRect(w,h) \
+ if (xgiCmdQueLen <= 0) XGI300Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, BR(6), (h)<<16 | (w) );\
+ xgiCmdQueLen --;
+
+#define XGI300SetupPATFG(color) \
+ if (xgiCmdQueLen <= 0) XGI300Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, BR(7), color);\
+ xgiCmdQueLen --;
+
+#define XGI300SetupPATBG(color) \
+ if (xgiCmdQueLen <= 0) XGI300Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, BR(8), color);\
+ xgiCmdQueLen --;
+
+#define XGI300SetupSRCFG(color) \
+ if (xgiCmdQueLen <= 0) XGI300Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, BR(9), color);\
+ xgiCmdQueLen --;
+
+#define XGI300SetupSRCBG(color) \
+ if (xgiCmdQueLen <= 0) XGI300Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, BR(10), color);\
+ xgiCmdQueLen --;
+
+/* 0x8224 src colorkey high */
+/* 0x8228 src colorkey low */
+/* 0x821c dest colorkey high */
+/* 0x8220 dest colorkey low */
+#define XGI300SetupSRCTrans(color) \
+ if (xgiCmdQueLen <= 1) XGI300Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, 0x8224, color);\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, 0x8228, color);\
+ xgiCmdQueLen -= 2;
+
+#define XGI300SetupDSTTrans(color) \
+ if (xgiCmdQueLen <= 1) XGI300Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, 0x821C, color); \
+ MMIO_OUT32(xgi_video_info.mmio_vbase, 0x8220, color); \
+ xgiCmdQueLen -= 2;
+
+#define XGI300SetupMONOPAT(p0,p1) \
+ if (xgiCmdQueLen <= 1) XGI300Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, BR(11), p0);\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, BR(12), p1);\
+ xgiCmdQueLen -= 2;
+
+#define XGI300SetupClipLT(left,top) \
+ if (xgiCmdQueLen <= 0) XGI300Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, BR(13), ((left) & 0xFFFF) | (top)<<16 );\
+ xgiCmdQueLen--;
+
+#define XGI300SetupClipRB(right,bottom) \
+ if (xgiCmdQueLen <= 0) XGI300Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, BR(14), ((right) & 0xFFFF) | (bottom)<<16 );\
+ xgiCmdQueLen--;
+
+/* General */
+#define XGI300SetupROP(rop) \
+ xgi_video_info.CommandReg = (rop) << 8;
+
+#define XGI300SetupCMDFlag(flags) \
+ xgi_video_info.CommandReg |= (flags);
+
+#define XGI300DoCMD \
+ if (xgiCmdQueLen <= 1) XGI300Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, BR(15), xgi_video_info.CommandReg); \
+ MMIO_OUT32(xgi_video_info.mmio_vbase, BR(16), 0);\
+ xgiCmdQueLen -= 2;
+
+/* Line */
+#define XGI300SetupX0Y0(x,y) \
+ if (xgiCmdQueLen <= 0) XGI300Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, BR(2), (y)<<16 | (x) );\
+ xgiCmdQueLen--;
+
+#define XGI300SetupX1Y1(x,y) \
+ if (xgiCmdQueLen <= 0) XGI300Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, BR(3), (y)<<16 | (x) );\
+ xgiCmdQueLen--;
+
+#define XGI300SetupLineCount(c) \
+ if (xgiCmdQueLen <= 0) XGI300Idle;\
+ MMIO_OUT16(xgi_video_info.mmio_vbase, BR(6), c);\
+ xgiCmdQueLen--;
+
+#define XGI300SetupStylePeriod(p) \
+ if (xgiCmdQueLen <= 0) XGI300Idle;\
+ MMIO_OUT16(xgi_video_info.mmio_vbase, BR(6)+2, p);\
+ xgiCmdQueLen--;
+
+#define XGI300SetupStyleLow(ls) \
+ if (xgiCmdQueLen <= 0) XGI300Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, BR(11), ls);\
+ xgiCmdQueLen--;
+
+#define XGI300SetupStyleHigh(ls) \
+ if (xgiCmdQueLen <= 0) XGI300Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, BR(12), ls);\
+ xgiCmdQueLen--;
+
+
+
+/* ----------- XGI 310/325 series --------------- */
+
+/* Q_STATUS:
+ bit 31 = 1: All engines idle and all queues empty
+ bit 30 = 1: Hardware Queue (=HW CQ, 2D queue, 3D queue) empty
+ bit 29 = 1: 2D engine is idle
+ bit 28 = 1: 3D engine is idle
+ bit 27 = 1: HW command queue empty
+ bit 26 = 1: 2D queue empty
+ bit 25 = 1: 3D queue empty
+ bit 24 = 1: SW command queue empty
+ bits 23:16: 2D counter 3
+ bits 15:8: 2D counter 2
+ bits 7:0: 2D counter 1
+
+ Where is the command queue length (current amount of commands the queue
+ can accept) on the 310/325 series? (The current implementation is taken
+ from 300 series and certainly wrong...)
+*/
+
+/* TW: FIXME: xgiCmdQueLen is... where....? */
+#define XGI310Idle \
+ { \
+ while( (MMIO_IN16(xgi_video_info.mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
+ while( (MMIO_IN16(xgi_video_info.mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
+ xgiCmdQueLen=MMIO_IN16(xgi_video_info.mmio_vbase, Q_STATUS); \
+ }
+
+#define XGI310SetupSRCBase(base) \
+ if (xgiCmdQueLen <= 0) XGI310Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, SRC_ADDR, base);\
+ xgiCmdQueLen--;
+
+#define XGI310SetupSRCPitch(pitch) \
+ if (xgiCmdQueLen <= 0) XGI310Idle;\
+ MMIO_OUT16(xgi_video_info.mmio_vbase, SRC_PITCH, pitch);\
+ xgiCmdQueLen--;
+
+#define XGI310SetupSRCXY(x,y) \
+ if (xgiCmdQueLen <= 0) XGI310Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, SRC_Y, (x)<<16 | (y) );\
+ xgiCmdQueLen--;
+
+#define XGI310SetupDSTBase(base) \
+ if (xgiCmdQueLen <= 0) XGI310Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, DST_ADDR, base);\
+ xgiCmdQueLen--;
+
+#define XGI310SetupDSTXY(x,y) \
+ if (xgiCmdQueLen <= 0) XGI310Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, DST_Y, (x)<<16 | (y) );\
+ xgiCmdQueLen--;
+
+#define XGI310SetupDSTRect(x,y) \
+ if (xgiCmdQueLen <= 0) XGI310Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, DST_PITCH, (y)<<16 | (x) );\
+ xgiCmdQueLen--;
+
+#define XGI310SetupDSTColorDepth(bpp) \
+ if (xgiCmdQueLen <= 0) XGI310Idle;\
+ MMIO_OUT16(xgi_video_info.mmio_vbase, AGP_BASE, bpp);\
+ xgiCmdQueLen--;
+
+#define XGI310SetupRect(w,h) \
+ if (xgiCmdQueLen <= 0) XGI310Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, RECT_WIDTH, (h)<<16 | (w) );\
+ xgiCmdQueLen--;
+
+#define XGI310SetupPATFG(color) \
+ if (xgiCmdQueLen <= 0) XGI310Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, PAT_FGCOLOR, color);\
+ xgiCmdQueLen--;
+
+#define XGI310SetupPATBG(color) \
+ if (xgiCmdQueLen <= 0) XGI310Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, PAT_BGCOLOR, color);\
+ xgiCmdQueLen--;
+
+#define XGI310SetupSRCFG(color) \
+ if (xgiCmdQueLen <= 0) XGI310Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, SRC_FGCOLOR, color);\
+ xgiCmdQueLen--;
+
+#define XGI310SetupSRCBG(color) \
+ if (xgiCmdQueLen <= 0) XGI310Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, SRC_BGCOLOR, color);\
+ xgiCmdQueLen--;
+
+#define XGI310SetupSRCTrans(color) \
+ if (xgiCmdQueLen <= 1) XGI310Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, TRANS_SRC_KEY_HIGH, color);\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, TRANS_SRC_KEY_LOW, color);\
+ xgiCmdQueLen -= 2;
+
+#define XGI310SetupDSTTrans(color) \
+ if (xgiCmdQueLen <= 1) XGI310Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, TRANS_DST_KEY_HIGH, color); \
+ MMIO_OUT32(xgi_video_info.mmio_vbase, TRANS_DST_KEY_LOW, color); \
+ xgiCmdQueLen -= 2;
+
+#define XGI310SetupMONOPAT(p0,p1) \
+ if (xgiCmdQueLen <= 1) XGI310Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, MONO_MASK, p0);\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, MONO_MASK+4, p1);\
+ xgiCmdQueLen -= 2;
+
+#define XGI310SetupClipLT(left,top) \
+ if (xgiCmdQueLen <= 0) XGI310Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, LEFT_CLIP, ((left) & 0xFFFF) | (top)<<16 );\
+ xgiCmdQueLen--;
+
+#define XGI310SetupClipRB(right,bottom) \
+ if (xgiCmdQueLen <= 0) XGI310Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, RIGHT_CLIP, ((right) & 0xFFFF) | (bottom)<<16 );\
+ xgiCmdQueLen--;
+
+#define XGI310SetupROP(rop) \
+ xgi_video_info.CommandReg = (rop) << 8;
+
+#define XGI310SetupCMDFlag(flags) \
+ xgi_video_info.CommandReg |= (flags);
+
+#define XGI310DoCMD \
+ if (xgiCmdQueLen <= 1) XGI310Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, COMMAND_READY, xgi_video_info.CommandReg); \
+ MMIO_OUT32(xgi_video_info.mmio_vbase, FIRE_TRIGGER, 0); \
+ xgiCmdQueLen -= 2;
+
+#define XGI310SetupX0Y0(x,y) \
+ if (xgiCmdQueLen <= 0) XGI310Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, LINE_X0, (y)<<16 | (x) );\
+ xgiCmdQueLen--;
+
+#define XGI310SetupX1Y1(x,y) \
+ if (xgiCmdQueLen <= 0) XGI310Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, LINE_X1, (y)<<16 | (x) );\
+ xgiCmdQueLen--;
+
+#define XGI310SetupLineCount(c) \
+ if (xgiCmdQueLen <= 0) XGI310Idle;\
+ MMIO_OUT16(xgi_video_info.mmio_vbase, LINE_COUNT, c);\
+ xgiCmdQueLen--;
+
+#define XGI310SetupStylePeriod(p) \
+ if (xgiCmdQueLen <= 0) XGI310Idle;\
+ MMIO_OUT16(xgi_video_info.mmio_vbase, LINE_STYLE_PERIOD, p);\
+ xgiCmdQueLen--;
+
+#define XGI310SetupStyleLow(ls) \
+ if (xgiCmdQueLen <= 0) XGI310Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, LINE_STYLE_0, ls);\
+ xgiCmdQueLen--;
+
+#define XGI310SetupStyleHigh(ls) \
+ if (xgiCmdQueLen <= 0) XGI310Idle;\
+ MMIO_OUT32(xgi_video_info.mmio_vbase, LINE_STYLE_1, ls);\
+ xgiCmdQueLen--;
+
+int XGIfb_initaccel(void);
+void XGIfb_syncaccel(void);
+
+extern struct video_info xgi_video_info;
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33)
+void fbcon_XGI_bmove(struct display *p, int srcy, int srcx, int dsty,
+ int dstx, int height, int width);
+void fbcon_XGI_revc(struct display *p, int srcy, int srcx);
+void fbcon_XGI_clear8(struct vc_data *conp, struct display *p, int srcy,
+ int srcx, int height, int width);
+void fbcon_XGI_clear16(struct vc_data *conp, struct display *p, int srcy,
+ int srcx, int height, int width);
+void fbcon_XGI_clear32(struct vc_data *conp, struct display *p, int srcy,
+ int srcx, int height, int width);
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)
+extern int XGIfb_accel;
+void fbcon_XGI_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
+void fbcon_XGI_copyarea(struct fb_info *info, const struct fb_copyarea *area);
+#endif
+
+#endif
diff --git a/drivers/staging/xgifb/XGI_main.h b/drivers/staging/xgifb/XGI_main.h
new file mode 100644
index 0000000..4f4171e
--- /dev/null
+++ b/drivers/staging/xgifb/XGI_main.h
@@ -0,0 +1,1023 @@
+#ifndef _XGIFB_MAIN
+#define _XGIFB_MAIN
+
+
+/* ------------------- Constant Definitions ------------------------- */
+
+
+#include "XGIfb.h"
+#include "vb_struct.h"
+#include "vb_def.h"
+
+//#define LINUXBIOS /* turn this on when compiling for LINUXBIOS */
+#define AGPOFF /* default is turn off AGP */
+
+#define XGIFAIL(x) do { printk(x "\n"); return -EINVAL; } while(0)
+
+#define VER_MAJOR 0
+#define VER_MINOR 8
+#define VER_LEVEL 1
+
+#define DRIVER_DESC "XGI Volari Frame Buffer Module Version 0.8.1"
+
+#ifndef PCI_VENDOR_ID_XG
+#define PCI_VENDOR_ID_XG 0x18CA
+#endif
+
+#ifndef PCI_DEVICE_ID_XG_40
+#define PCI_DEVICE_ID_XG_40 0x040
+#endif
+#ifndef PCI_DEVICE_ID_XG_41
+#define PCI_DEVICE_ID_XG_41 0x041
+#endif
+#ifndef PCI_DEVICE_ID_XG_42
+#define PCI_DEVICE_ID_XG_42 0x042
+#endif
+#ifndef PCI_DEVICE_ID_XG_20
+#define PCI_DEVICE_ID_XG_20 0x020
+#endif
+#ifndef PCI_DEVICE_ID_XG_27
+#define PCI_DEVICE_ID_XG_27 0x027
+#endif
+
+
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
+#define XGI_IOTYPE1 void __iomem
+#define XGI_IOTYPE2 __iomem
+#define XGIINITSTATIC static
+#else
+#define XGI_IOTYPE1 unsigned char
+#define XGI_IOTYPE2
+#define XGIINITSTATIC
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+static struct pci_device_id __devinitdata xgifb_pci_table[] = {
+
+ { PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ { PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_27, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
+ { PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_40, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
+ { PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_42, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, xgifb_pci_table);
+#endif
+/* To be included in fb.h */
+#ifndef FB_ACCEL_XGI_GLAMOUR_2
+#define FB_ACCEL_XGI_GLAMOUR_2 40 /* XGI 315, 650, 740 */
+#endif
+#ifndef FB_ACCEL_XGI_XABRE
+#define FB_ACCEL_XGI_XABRE 41 /* XGI 330 ("Xabre") */
+#endif
+
+#define MAX_ROM_SCAN 0x10000
+
+#define HW_CURSOR_CAP 0x80
+#define TURBO_QUEUE_CAP 0x40
+#define AGP_CMD_QUEUE_CAP 0x20
+#define VM_CMD_QUEUE_CAP 0x10
+#define MMIO_CMD_QUEUE_CAP 0x08
+
+
+
+/* For 315 series */
+
+#define COMMAND_QUEUE_AREA_SIZE 0x80000 /* 512K */
+#define COMMAND_QUEUE_THRESHOLD 0x1F
+
+
+/* TW */
+#define HW_CURSOR_AREA_SIZE_315 0x4000 /* 16K */
+#define HW_CURSOR_AREA_SIZE_300 0x1000 /* 4K */
+
+#define OH_ALLOC_SIZE 4000
+#define SENTINEL 0x7fffffff
+
+#define SEQ_ADR 0x14
+#define SEQ_DATA 0x15
+#define DAC_ADR 0x18
+#define DAC_DATA 0x19
+#define CRTC_ADR 0x24
+#define CRTC_DATA 0x25
+#define DAC2_ADR (0x16-0x30)
+#define DAC2_DATA (0x17-0x30)
+#define VB_PART1_ADR (0x04-0x30)
+#define VB_PART1_DATA (0x05-0x30)
+#define VB_PART2_ADR (0x10-0x30)
+#define VB_PART2_DATA (0x11-0x30)
+#define VB_PART3_ADR (0x12-0x30)
+#define VB_PART3_DATA (0x13-0x30)
+#define VB_PART4_ADR (0x14-0x30)
+#define VB_PART4_DATA (0x15-0x30)
+
+#define XGISR XGI_Pr.P3c4
+#define XGICR XGI_Pr.P3d4
+#define XGIDACA XGI_Pr.P3c8
+#define XGIDACD XGI_Pr.P3c9
+#define XGIPART1 XGI_Pr.Part1Port
+#define XGIPART2 XGI_Pr.Part2Port
+#define XGIPART3 XGI_Pr.Part3Port
+#define XGIPART4 XGI_Pr.Part4Port
+#define XGIPART5 XGI_Pr.Part5Port
+#define XGIDAC2A XGIPART5
+#define XGIDAC2D (XGIPART5 + 1)
+#define XGIMISCR (XGI_Pr.RelIO + 0x1c)
+#define XGIINPSTAT (XGI_Pr.RelIO + 0x2a)
+
+#define IND_XGI_PASSWORD 0x05 /* SRs */
+#define IND_XGI_COLOR_MODE 0x06
+#define IND_XGI_RAMDAC_CONTROL 0x07
+#define IND_XGI_DRAM_SIZE 0x14
+#define IND_XGI_SCRATCH_REG_16 0x16
+#define IND_XGI_SCRATCH_REG_17 0x17
+#define IND_XGI_SCRATCH_REG_1A 0x1A
+#define IND_XGI_MODULE_ENABLE 0x1E
+#define IND_XGI_PCI_ADDRESS_SET 0x20
+#define IND_XGI_TURBOQUEUE_ADR 0x26
+#define IND_XGI_TURBOQUEUE_SET 0x27
+#define IND_XGI_POWER_ON_TRAP 0x38
+#define IND_XGI_POWER_ON_TRAP2 0x39
+#define IND_XGI_CMDQUEUE_SET 0x26
+#define IND_XGI_CMDQUEUE_THRESHOLD 0x27
+
+#define IND_XGI_SCRATCH_REG_CR30 0x30 /* CRs */
+#define IND_XGI_SCRATCH_REG_CR31 0x31
+#define IND_XGI_SCRATCH_REG_CR32 0x32
+#define IND_XGI_SCRATCH_REG_CR33 0x33
+#define IND_XGI_LCD_PANEL 0x36
+#define IND_XGI_SCRATCH_REG_CR37 0x37
+#define IND_XGI_AGP_IO_PAD 0x48
+
+#define IND_BRI_DRAM_STATUS 0x63 /* PCI config memory size offset */
+
+#define MMIO_QUEUE_PHYBASE 0x85C0
+#define MMIO_QUEUE_WRITEPORT 0x85C4
+#define MMIO_QUEUE_READPORT 0x85C8
+
+#define IND_XGI_CRT2_WRITE_ENABLE_300 0x24
+#define IND_XGI_CRT2_WRITE_ENABLE_315 0x2F
+
+#define XGI_PASSWORD 0x86 /* SR05 */
+#define XGI_INTERLACED_MODE 0x20 /* SR06 */
+#define XGI_8BPP_COLOR_MODE 0x0
+#define XGI_15BPP_COLOR_MODE 0x1
+#define XGI_16BPP_COLOR_MODE 0x2
+#define XGI_32BPP_COLOR_MODE 0x4
+
+#define XGI_DRAM_SIZE_MASK 0xF0 /*SR14 */
+#define XGI_DRAM_SIZE_1MB 0x00
+#define XGI_DRAM_SIZE_2MB 0x01
+#define XGI_DRAM_SIZE_4MB 0x02
+#define XGI_DRAM_SIZE_8MB 0x03
+#define XGI_DRAM_SIZE_16MB 0x04
+#define XGI_DRAM_SIZE_32MB 0x05
+#define XGI_DRAM_SIZE_64MB 0x06
+#define XGI_DRAM_SIZE_128MB 0x07
+#define XGI_DRAM_SIZE_256MB 0x08
+#define XGI_DATA_BUS_MASK 0x02
+#define XGI_DATA_BUS_64 0x00
+#define XGI_DATA_BUS_128 0x01
+#define XGI_DUAL_CHANNEL_MASK 0x0C
+#define XGI_SINGLE_CHANNEL_1_RANK 0x0
+#define XGI_SINGLE_CHANNEL_2_RANK 0x1
+#define XGI_ASYM_DDR 0x02
+#define XGI_DUAL_CHANNEL_1_RANK 0x3
+
+#define XGI550_DRAM_SIZE_MASK 0x3F /* 550/650/740 SR14 */
+#define XGI550_DRAM_SIZE_4MB 0x00
+#define XGI550_DRAM_SIZE_8MB 0x01
+#define XGI550_DRAM_SIZE_16MB 0x03
+#define XGI550_DRAM_SIZE_24MB 0x05
+#define XGI550_DRAM_SIZE_32MB 0x07
+#define XGI550_DRAM_SIZE_64MB 0x0F
+#define XGI550_DRAM_SIZE_96MB 0x17
+#define XGI550_DRAM_SIZE_128MB 0x1F
+#define XGI550_DRAM_SIZE_256MB 0x3F
+
+#define XGI_SCRATCH_REG_1A_MASK 0x10
+
+#define XGI_ENABLE_2D 0x40 /* SR1E */
+
+#define XGI_MEM_MAP_IO_ENABLE 0x01 /* SR20 */
+#define XGI_PCI_ADDR_ENABLE 0x80
+
+#define XGI_AGP_CMDQUEUE_ENABLE 0x80 /* 315/650/740 SR26 */
+#define XGI_VRAM_CMDQUEUE_ENABLE 0x40
+#define XGI_MMIO_CMD_ENABLE 0x20
+#define XGI_CMD_QUEUE_SIZE_512k 0x00
+#define XGI_CMD_QUEUE_SIZE_1M 0x04
+#define XGI_CMD_QUEUE_SIZE_2M 0x08
+#define XGI_CMD_QUEUE_SIZE_4M 0x0C
+#define XGI_CMD_QUEUE_RESET 0x01
+#define XGI_CMD_AUTO_CORR 0x02
+
+#define XGI_SIMULTANEOUS_VIEW_ENABLE 0x01 /* CR30 */
+#define XGI_MODE_SELECT_CRT2 0x02
+#define XGI_VB_OUTPUT_COMPOSITE 0x04
+#define XGI_VB_OUTPUT_SVIDEO 0x08
+#define XGI_VB_OUTPUT_SCART 0x10
+#define XGI_VB_OUTPUT_LCD 0x20
+#define XGI_VB_OUTPUT_CRT2 0x40
+#define XGI_VB_OUTPUT_HIVISION 0x80
+
+#define XGI_VB_OUTPUT_DISABLE 0x20 /* CR31 */
+#define XGI_DRIVER_MODE 0x40
+
+#define XGI_VB_COMPOSITE 0x01 /* CR32 */
+#define XGI_VB_SVIDEO 0x02
+#define XGI_VB_SCART 0x04
+#define XGI_VB_LCD 0x08
+#define XGI_VB_CRT2 0x10
+#define XGI_CRT1 0x20
+#define XGI_VB_HIVISION 0x40
+#define XGI_VB_YPBPR 0x80
+#define XGI_VB_TV (XGI_VB_COMPOSITE | XGI_VB_SVIDEO | \
+ XGI_VB_SCART | XGI_VB_HIVISION|XGI_VB_YPBPR)
+
+#define XGI_EXTERNAL_CHIP_MASK 0x0E /* CR37 */
+#define XGI_EXTERNAL_CHIP_XGI301 0x01 /* in CR37 << 1 ! */
+#define XGI_EXTERNAL_CHIP_LVDS 0x02 /* in CR37 << 1 ! */
+#define XGI_EXTERNAL_CHIP_TRUMPION 0x03 /* in CR37 << 1 ! */
+#define XGI_EXTERNAL_CHIP_LVDS_CHRONTEL 0x04 /* in CR37 << 1 ! */
+#define XGI_EXTERNAL_CHIP_CHRONTEL 0x05 /* in CR37 << 1 ! */
+#define XGI310_EXTERNAL_CHIP_LVDS 0x02 /* in CR37 << 1 ! */
+#define XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL 0x03 /* in CR37 << 1 ! */
+
+#define XGI_AGP_2X 0x20 /* CR48 */
+
+#define BRI_DRAM_SIZE_MASK 0x70 /* PCI bridge config data */
+#define BRI_DRAM_SIZE_2MB 0x00
+#define BRI_DRAM_SIZE_4MB 0x01
+#define BRI_DRAM_SIZE_8MB 0x02
+#define BRI_DRAM_SIZE_16MB 0x03
+#define BRI_DRAM_SIZE_32MB 0x04
+#define BRI_DRAM_SIZE_64MB 0x05
+
+#define HW_DEVICE_EXTENSION XGI_HW_DEVICE_INFO
+#define PHW_DEVICE_EXTENSION PXGI_HW_DEVICE_INFO
+
+#define SR_BUFFER_SIZE 5
+#define CR_BUFFER_SIZE 5
+
+/* Useful macros */
+#define inXGIREG(base) inb(base)
+#define outXGIREG(base,val) outb(val,base)
+#define orXGIREG(base,val) do { \
+ unsigned char __Temp = inb(base); \
+ outXGIREG(base, __Temp | (val)); \
+ } while (0)
+#define andXGIREG(base,val) do { \
+ unsigned char __Temp = inb(base); \
+ outXGIREG(base, __Temp & (val)); \
+ } while (0)
+#define inXGIIDXREG(base,idx,var) do { \
+ outb(idx,base); var=inb((base)+1); \
+ } while (0)
+#define outXGIIDXREG(base,idx,val) do { \
+ outb(idx,base); outb((val),(base)+1); \
+ } while (0)
+#define orXGIIDXREG(base,idx,val) do { \
+ unsigned char __Temp; \
+ outb(idx,base); \
+ __Temp = inb((base)+1)|(val); \
+ outXGIIDXREG(base,idx,__Temp); \
+ } while (0)
+#define andXGIIDXREG(base,idx,and) do { \
+ unsigned char __Temp; \
+ outb(idx,base); \
+ __Temp = inb((base)+1)&(and); \
+ outXGIIDXREG(base,idx,__Temp); \
+ } while (0)
+#define setXGIIDXREG(base,idx,and,or) do { \
+ unsigned char __Temp; \
+ outb(idx,base); \
+ __Temp = (inb((base)+1)&(and))|(or); \
+ outXGIIDXREG(base,idx,__Temp); \
+ } while (0)
+
+/* ------------------- Global Variables ----------------------------- */
+
+/* Fbcon variables */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+static struct fb_info* fb_info;
+#else
+static struct fb_info XGI_fb_info;
+#endif
+
+
+static int video_type = FB_TYPE_PACKED_PIXELS;
+
+static struct fb_var_screeninfo default_var = {
+ .xres = 0,
+ .yres = 0,
+ .xres_virtual = 0,
+ .yres_virtual = 0,
+ .xoffset = 0,
+ .yoffset = 0,
+ .bits_per_pixel = 0,
+ .grayscale = 0,
+ .red = {0, 8, 0},
+ .green = {0, 8, 0},
+ .blue = {0, 8, 0},
+ .transp = {0, 0, 0},
+ .nonstd = 0,
+ .activate = FB_ACTIVATE_NOW,
+ .height = -1,
+ .width = -1,
+ .accel_flags = 0,
+ .pixclock = 0,
+ .left_margin = 0,
+ .right_margin = 0,
+ .upper_margin = 0,
+ .lower_margin = 0,
+ .hsync_len = 0,
+ .vsync_len = 0,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ .reserved = {0, 0, 0, 0, 0, 0}
+#endif
+};
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+static struct fb_fix_screeninfo XGIfb_fix = {
+ .id = "XGI",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .xpanstep = 1,
+ .ypanstep = 1,
+};
+static char myid[20];
+static u32 pseudo_palette[17];
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+static struct display XGI_disp;
+
+static struct display_switch XGIfb_sw;
+
+static struct {
+ u16 blue, green, red, pad;
+} XGI_palette[256];
+
+static union {
+#ifdef FBCON_HAS_CFB16
+ u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+ u32 cfb32[16];
+#endif
+} XGI_fbcon_cmap;
+
+static int XGIfb_inverse = 0;
+#endif
+
+/* display status */
+static int XGIfb_off = 0;
+static int XGIfb_crt1off = 0;
+static int XGIfb_forcecrt1 = -1;
+static int XGIvga_enabled = 0;
+static int XGIfb_userom = 0;
+//static int XGIfb_useoem = -1;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+static int currcon = 0;
+#endif
+
+/* global flags */
+static int XGIfb_registered;
+static int XGIfb_tvmode = 0;
+static int XGIfb_mem = 0;
+static int XGIfb_pdc = 0;
+static int enable_dstn = 0;
+static int XGIfb_ypan = -1;
+
+
+int XGIfb_accel = 0;
+
+
+static int XGIfb_hwcursor_size = 0;
+static int XGIfb_CRT2_write_enable = 0;
+
+int XGIfb_crt2type = -1; /* TW: CRT2 type (for overriding autodetection) */
+int XGIfb_tvplug = -1; /* PR: Tv plug type (for overriding autodetection) */
+
+int XGIfb_queuemode = -1; /* TW: Use MMIO queue mode by default (310/325 series only) */
+
+unsigned char XGIfb_detectedpdc = 0;
+
+unsigned char XGIfb_detectedlcda = 0xff;
+
+
+
+
+/* TW: For ioctl XGIFB_GET_INFO */
+/* XGIfb_info XGIfbinfo; */
+
+/* TW: Hardware extension; contains data on hardware */
+HW_DEVICE_EXTENSION XGIhw_ext;
+
+/* TW: XGI private structure */
+VB_DEVICE_INFO XGI_Pr;
+
+/* card parameters */
+static unsigned long XGIfb_mmio_size = 0;
+static u8 XGIfb_caps = 0;
+
+typedef enum _XGI_CMDTYPE {
+ MMIO_CMD = 0,
+ AGP_CMD_QUEUE,
+ VM_CMD_QUEUE,
+} XGI_CMDTYPE;
+
+#define MD_XGI300 1
+#define MD_XGI315 2
+
+/* mode table */
+/* NOT const - will be patched for 1280x960 mode number chaos reasons */
+struct _XGIbios_mode {
+ char name[15];
+ u8 mode_no;
+ u16 vesa_mode_no_1; /* "XGI defined" VESA mode number */
+ u16 vesa_mode_no_2; /* Real VESA mode numbers */
+ u16 xres;
+ u16 yres;
+ u16 bpp;
+ u16 rate_idx;
+ u16 cols;
+ u16 rows;
+ u8 chipset;
+} XGIbios_mode[] = {
+#define MODE_INDEX_NONE 0 /* TW: index for mode=none */
+ {"none", 0xFF, 0x0000, 0x0000, 0, 0, 0, 0, 0, 0, MD_XGI300|MD_XGI315}, /* TW: for mode "none" */
+ {"320x240x16", 0x56, 0x0000, 0x0000, 320, 240, 16, 1, 40, 15, MD_XGI315},
+ {"320x480x8", 0x5A, 0x0000, 0x0000, 320, 480, 8, 1, 40, 30, MD_XGI315}, /* TW: FSTN */
+ {"320x480x16", 0x5B, 0x0000, 0x0000, 320, 480, 16, 1, 40, 30, MD_XGI315}, /* TW: FSTN */
+ {"640x480x8", 0x2E, 0x0101, 0x0101, 640, 480, 8, 1, 80, 30, MD_XGI300|MD_XGI315},
+ {"640x480x16", 0x44, 0x0111, 0x0111, 640, 480, 16, 1, 80, 30, MD_XGI300|MD_XGI315},
+ {"640x480x24", 0x62, 0x013a, 0x0112, 640, 480, 32, 1, 80, 30, MD_XGI300|MD_XGI315}, /* TW: That's for people who mix up color- and fb depth */
+ {"640x480x32", 0x62, 0x013a, 0x0112, 640, 480, 32, 1, 80, 30, MD_XGI300|MD_XGI315},
+ {"720x480x8", 0x31, 0x0000, 0x0000, 720, 480, 8, 1, 90, 30, MD_XGI300|MD_XGI315},
+ {"720x480x16", 0x33, 0x0000, 0x0000, 720, 480, 16, 1, 90, 30, MD_XGI300|MD_XGI315},
+ {"720x480x24", 0x35, 0x0000, 0x0000, 720, 480, 32, 1, 90, 30, MD_XGI300|MD_XGI315},
+ {"720x480x32", 0x35, 0x0000, 0x0000, 720, 480, 32, 1, 90, 30, MD_XGI300|MD_XGI315},
+ {"720x576x8", 0x32, 0x0000, 0x0000, 720, 576, 8, 1, 90, 36, MD_XGI300|MD_XGI315},
+ {"720x576x16", 0x34, 0x0000, 0x0000, 720, 576, 16, 1, 90, 36, MD_XGI300|MD_XGI315},
+ {"720x576x24", 0x36, 0x0000, 0x0000, 720, 576, 32, 1, 90, 36, MD_XGI300|MD_XGI315},
+ {"720x576x32", 0x36, 0x0000, 0x0000, 720, 576, 32, 1, 90, 36, MD_XGI300|MD_XGI315},
+ {"800x480x8", 0x70, 0x0000, 0x0000, 800, 480, 8, 1, 100, 30, MD_XGI300|MD_XGI315},
+ {"800x480x16", 0x7a, 0x0000, 0x0000, 800, 480, 16, 1, 100, 30, MD_XGI300|MD_XGI315},
+ {"800x480x24", 0x76, 0x0000, 0x0000, 800, 480, 32, 1, 100, 30, MD_XGI300|MD_XGI315},
+ {"800x480x32", 0x76, 0x0000, 0x0000, 800, 480, 32, 1, 100, 30, MD_XGI300|MD_XGI315},
+#define DEFAULT_MODE 21 /* TW: index for 800x600x8 */
+#define DEFAULT_LCDMODE 21 /* TW: index for 800x600x8 */
+#define DEFAULT_TVMODE 21 /* TW: index for 800x600x8 */
+ {"800x600x8", 0x30, 0x0103, 0x0103, 800, 600, 8, 1, 100, 37, MD_XGI300|MD_XGI315},
+ {"800x600x16", 0x47, 0x0114, 0x0114, 800, 600, 16, 1, 100, 37, MD_XGI300|MD_XGI315},
+ {"800x600x24", 0x63, 0x013b, 0x0115, 800, 600, 32, 1, 100, 37, MD_XGI300|MD_XGI315},
+ {"800x600x32", 0x63, 0x013b, 0x0115, 800, 600, 32, 1, 100, 37, MD_XGI300|MD_XGI315},
+ {"1024x576x8", 0x71, 0x0000, 0x0000, 1024, 576, 8, 1, 128, 36, MD_XGI300|MD_XGI315},
+ {"1024x576x16", 0x74, 0x0000, 0x0000, 1024, 576, 16, 1, 128, 36, MD_XGI300|MD_XGI315},
+ {"1024x576x24", 0x77, 0x0000, 0x0000, 1024, 576, 32, 1, 128, 36, MD_XGI300|MD_XGI315},
+ {"1024x576x32", 0x77, 0x0000, 0x0000, 1024, 576, 32, 1, 128, 36, MD_XGI300|MD_XGI315},
+ {"1024x600x8", 0x20, 0x0000, 0x0000, 1024, 600, 8, 1, 128, 37, MD_XGI300 }, /* TW: 300 series only */
+ {"1024x600x16", 0x21, 0x0000, 0x0000, 1024, 600, 16, 1, 128, 37, MD_XGI300 },
+ {"1024x600x24", 0x22, 0x0000, 0x0000, 1024, 600, 32, 1, 128, 37, MD_XGI300 },
+ {"1024x600x32", 0x22, 0x0000, 0x0000, 1024, 600, 32, 1, 128, 37, MD_XGI300 },
+ {"1024x768x8", 0x38, 0x0105, 0x0105, 1024, 768, 8, 1, 128, 48, MD_XGI300|MD_XGI315},
+ {"1024x768x16", 0x4A, 0x0117, 0x0117, 1024, 768, 16, 1, 128, 48, MD_XGI300|MD_XGI315},
+ {"1024x768x24", 0x64, 0x013c, 0x0118, 1024, 768, 32, 1, 128, 48, MD_XGI300|MD_XGI315},
+ {"1024x768x32", 0x64, 0x013c, 0x0118, 1024, 768, 32, 1, 128, 48, MD_XGI300|MD_XGI315},
+ {"1152x768x8", 0x23, 0x0000, 0x0000, 1152, 768, 8, 1, 144, 48, MD_XGI300 }, /* TW: 300 series only */
+ {"1152x768x16", 0x24, 0x0000, 0x0000, 1152, 768, 16, 1, 144, 48, MD_XGI300 },
+ {"1152x768x24", 0x25, 0x0000, 0x0000, 1152, 768, 32, 1, 144, 48, MD_XGI300 },
+ {"1152x768x32", 0x25, 0x0000, 0x0000, 1152, 768, 32, 1, 144, 48, MD_XGI300 },
+ {"1280x720x8", 0x79, 0x0000, 0x0000, 1280, 720, 8, 1, 160, 45, MD_XGI300|MD_XGI315},
+ {"1280x720x16", 0x75, 0x0000, 0x0000, 1280, 720, 16, 1, 160, 45, MD_XGI300|MD_XGI315},
+ {"1280x720x24", 0x78, 0x0000, 0x0000, 1280, 720, 32, 1, 160, 45, MD_XGI300|MD_XGI315},
+ {"1280x720x32", 0x78, 0x0000, 0x0000, 1280, 720, 32, 1, 160, 45, MD_XGI300|MD_XGI315},
+ {"1280x768x8", 0x23, 0x0000, 0x0000, 1280, 768, 8, 1, 160, 48, MD_XGI315}, /* TW: 310/325 series only */
+ {"1280x768x16", 0x24, 0x0000, 0x0000, 1280, 768, 16, 1, 160, 48, MD_XGI315},
+ {"1280x768x24", 0x25, 0x0000, 0x0000, 1280, 768, 32, 1, 160, 48, MD_XGI315},
+ {"1280x768x32", 0x25, 0x0000, 0x0000, 1280, 768, 32, 1, 160, 48, MD_XGI315},
+#define MODEINDEX_1280x960 48
+ {"1280x960x8", 0x7C, 0x0000, 0x0000, 1280, 960, 8, 1, 160, 60, MD_XGI300|MD_XGI315}, /* TW: Modenumbers being patched */
+ {"1280x960x16", 0x7D, 0x0000, 0x0000, 1280, 960, 16, 1, 160, 60, MD_XGI300|MD_XGI315},
+ {"1280x960x24", 0x7E, 0x0000, 0x0000, 1280, 960, 32, 1, 160, 60, MD_XGI300|MD_XGI315},
+ {"1280x960x32", 0x7E, 0x0000, 0x0000, 1280, 960, 32, 1, 160, 60, MD_XGI300|MD_XGI315},
+ {"1280x1024x8", 0x3A, 0x0107, 0x0107, 1280, 1024, 8, 1, 160, 64, MD_XGI300|MD_XGI315},
+ {"1280x1024x16", 0x4D, 0x011a, 0x011a, 1280, 1024, 16, 1, 160, 64, MD_XGI300|MD_XGI315},
+ {"1280x1024x24", 0x65, 0x013d, 0x011b, 1280, 1024, 32, 1, 160, 64, MD_XGI300|MD_XGI315},
+ {"1280x1024x32", 0x65, 0x013d, 0x011b, 1280, 1024, 32, 1, 160, 64, MD_XGI300|MD_XGI315},
+ {"1400x1050x8", 0x26, 0x0000, 0x0000, 1400, 1050, 8, 1, 175, 65, MD_XGI315}, /* TW: 310/325 series only */
+ {"1400x1050x16", 0x27, 0x0000, 0x0000, 1400, 1050, 16, 1, 175, 65, MD_XGI315},
+ {"1400x1050x24", 0x28, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65, MD_XGI315},
+ {"1400x1050x32", 0x28, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65, MD_XGI315},
+ {"1600x1200x8", 0x3C, 0x0130, 0x011c, 1600, 1200, 8, 1, 200, 75, MD_XGI300|MD_XGI315},
+ {"1600x1200x16", 0x3D, 0x0131, 0x011e, 1600, 1200, 16, 1, 200, 75, MD_XGI300|MD_XGI315},
+ {"1600x1200x24", 0x66, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_XGI300|MD_XGI315},
+ {"1600x1200x32", 0x66, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_XGI300|MD_XGI315},
+ {"1920x1440x8", 0x68, 0x013f, 0x0000, 1920, 1440, 8, 1, 240, 75, MD_XGI300|MD_XGI315},
+ {"1920x1440x16", 0x69, 0x0140, 0x0000, 1920, 1440, 16, 1, 240, 75, MD_XGI300|MD_XGI315},
+ {"1920x1440x24", 0x6B, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_XGI300|MD_XGI315},
+ {"1920x1440x32", 0x6B, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_XGI300|MD_XGI315},
+ {"2048x1536x8", 0x6c, 0x0000, 0x0000, 2048, 1536, 8, 1, 256, 96, MD_XGI315}, /* TW: 310/325 series only */
+ {"2048x1536x16", 0x6d, 0x0000, 0x0000, 2048, 1536, 16, 1, 256, 96, MD_XGI315},
+ {"2048x1536x24", 0x6e, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96, MD_XGI315},
+ {"2048x1536x32", 0x6e, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96, MD_XGI315},
+ {"\0", 0x00, 0, 0, 0, 0, 0, 0, 0}
+};
+
+/* mode-related variables */
+#ifdef MODULE
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+static int xgifb_mode_idx = 1;
+#else
+static int XGIfb_mode_idx = MODE_INDEX_NONE; /* Don't use a mode by default if we are a module */
+#endif
+#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+static int xgifb_mode_idx = -1; /* Use a default mode if we are inside the kernel */
+#else
+static int XGIfb_mode_idx = -1;
+#endif
+#endif
+u8 XGIfb_mode_no = 0;
+u8 XGIfb_rate_idx = 0;
+
+/* TW: CR36 evaluation */
+const USHORT XGI300paneltype[] =
+ { LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024,
+ LCD_1280x960, LCD_640x480, LCD_1024x600, LCD_1152x768,
+ LCD_1024x768, LCD_1024x768, LCD_1024x768,
+ LCD_1024x768, LCD_1024x768, LCD_1024x768, LCD_1024x768 };
+
+const USHORT XGI310paneltype[] =
+ { LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024,
+ LCD_640x480, LCD_1024x600, LCD_1152x864, LCD_1280x960,
+ LCD_1152x768, LCD_1400x1050,LCD_1280x768, LCD_1600x1200,
+ LCD_1024x768, LCD_1024x768, LCD_1024x768 };
+
+static const struct _XGI_crt2type {
+ char name[10];
+ int type_no;
+ int tvplug_no;
+} XGI_crt2type[] = {
+ {"NONE", 0, -1},
+ {"LCD", DISPTYPE_LCD, -1},
+ {"TV", DISPTYPE_TV, -1},
+ {"VGA", DISPTYPE_CRT2, -1},
+ {"SVIDEO", DISPTYPE_TV, TVPLUG_SVIDEO},
+ {"COMPOSITE", DISPTYPE_TV, TVPLUG_COMPOSITE},
+ {"SCART", DISPTYPE_TV, TVPLUG_SCART},
+ {"none", 0, -1},
+ {"lcd", DISPTYPE_LCD, -1},
+ {"tv", DISPTYPE_TV, -1},
+ {"vga", DISPTYPE_CRT2, -1},
+ {"svideo", DISPTYPE_TV, TVPLUG_SVIDEO},
+ {"composite", DISPTYPE_TV, TVPLUG_COMPOSITE},
+ {"scart", DISPTYPE_TV, TVPLUG_SCART},
+ {"\0", -1, -1}
+};
+
+/* Queue mode selection for 310 series */
+static const struct _XGI_queuemode {
+ char name[6];
+ int type_no;
+} XGI_queuemode[] = {
+ {"AGP", AGP_CMD_QUEUE},
+ {"VRAM", VM_CMD_QUEUE},
+ {"MMIO", MMIO_CMD},
+ {"agp", AGP_CMD_QUEUE},
+ {"vram", VM_CMD_QUEUE},
+ {"mmio", MMIO_CMD},
+ {"\0", -1}
+};
+
+/* TV standard */
+static const struct _XGI_tvtype {
+ char name[6];
+ int type_no;
+} XGI_tvtype[] = {
+ {"PAL", 1},
+ {"NTSC", 2},
+ {"pal", 1},
+ {"ntsc", 2},
+ {"\0", -1}
+};
+
+static const struct _XGI_vrate {
+ u16 idx;
+ u16 xres;
+ u16 yres;
+ u16 refresh;
+} XGIfb_vrate[] = {
+ {1, 640, 480, 60}, {2, 640, 480, 72}, {3, 640, 480, 75}, {4, 640, 480, 85},
+ {5, 640, 480,100}, {6, 640, 480, 120}, {7, 640, 480, 160}, {8, 640, 480, 200},
+ {1, 720, 480, 60},
+ {1, 720, 576, 58},
+ {1, 800, 480, 60}, {2, 800, 480, 75}, {3, 800, 480, 85},
+ {1, 800, 600, 60}, {2, 800, 600, 72}, {3, 800, 600, 75},
+ {4, 800, 600, 85}, {5, 800, 600, 100}, {6, 800, 600, 120}, {7, 800, 600, 160},
+ {1, 1024, 768, 60}, {2, 1024, 768, 70}, {3, 1024, 768, 75},
+ {4, 1024, 768, 85}, {5, 1024, 768, 100}, {6, 1024, 768, 120},
+ {1, 1024, 576, 60}, {2, 1024, 576, 75}, {3, 1024, 576, 85},
+ {1, 1024, 600, 60},
+ {1, 1152, 768, 60},
+ {1, 1280, 720, 60}, {2, 1280, 720, 75}, {3, 1280, 720, 85},
+ {1, 1280, 768, 60},
+ {1, 1280, 1024, 60}, {2, 1280, 1024, 75}, {3, 1280, 1024, 85},
+ {1, 1280, 960, 70},
+ {1, 1400, 1050, 60},
+ {1, 1600, 1200, 60}, {2, 1600, 1200, 65}, {3, 1600, 1200, 70}, {4, 1600, 1200, 75},
+ {5, 1600, 1200, 85}, {6, 1600, 1200, 100}, {7, 1600, 1200, 120},
+ {1, 1920, 1440, 60}, {2, 1920, 1440, 65}, {3, 1920, 1440, 70}, {4, 1920, 1440, 75},
+ {5, 1920, 1440, 85}, {6, 1920, 1440, 100},
+ {1, 2048, 1536, 60}, {2, 2048, 1536, 65}, {3, 2048, 1536, 70}, {4, 2048, 1536, 75},
+ {5, 2048, 1536, 85},
+ {0, 0, 0, 0}
+};
+
+static const struct _chswtable {
+ int subsysVendor;
+ int subsysCard;
+ char *vendorName;
+ char *cardName;
+} mychswtable[] = {
+ { 0x1631, 0x1002, "Mitachi", "0x1002" },
+ { 0, 0, "" , "" }
+};
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+/* Offscreen layout */
+typedef struct _XGI_GLYINFO {
+ unsigned char ch;
+ int fontwidth;
+ int fontheight;
+ u8 gmask[72];
+ int ngmask;
+} XGI_GLYINFO;
+#endif
+
+typedef struct _XGI_OH {
+ struct _XGI_OH *poh_next;
+ struct _XGI_OH *poh_prev;
+ unsigned long offset;
+ unsigned long size;
+} XGI_OH;
+
+typedef struct _XGI_OHALLOC {
+ struct _XGI_OHALLOC *poha_next;
+ XGI_OH aoh[1];
+} XGI_OHALLOC;
+
+typedef struct _XGI_HEAP {
+ XGI_OH oh_free;
+ XGI_OH oh_used;
+ XGI_OH *poh_freelist;
+ XGI_OHALLOC *poha_chain;
+ unsigned long max_freesize;
+} XGI_HEAP;
+
+static unsigned long XGIfb_hwcursor_vbase;
+
+static unsigned long XGIfb_heap_start;
+static unsigned long XGIfb_heap_end;
+static unsigned long XGIfb_heap_size;
+static XGI_HEAP XGIfb_heap;
+
+// Eden Chen
+static const struct _XGI_TV_filter {
+ u8 filter[9][4];
+} XGI_TV_filter[] = {
+ { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_0 */
+ {0x00,0xE0,0x10,0x60},
+ {0x00,0xEE,0x10,0x44},
+ {0x00,0xF4,0x10,0x38},
+ {0xF8,0xF4,0x18,0x38},
+ {0xFC,0xFB,0x14,0x2A},
+ {0x00,0x00,0x10,0x20},
+ {0x00,0x04,0x10,0x18},
+ {0xFF,0xFF,0xFF,0xFF} }},
+ { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_1 */
+ {0x00,0xE0,0x10,0x60},
+ {0x00,0xEE,0x10,0x44},
+ {0x00,0xF4,0x10,0x38},
+ {0xF8,0xF4,0x18,0x38},
+ {0xFC,0xFB,0x14,0x2A},
+ {0x00,0x00,0x10,0x20},
+ {0x00,0x04,0x10,0x18},
+ {0xFF,0xFF,0xFF,0xFF} }},
+ { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_2 */
+ {0xF5,0xEE,0x1B,0x44},
+ {0xF8,0xF4,0x18,0x38},
+ {0xEB,0x04,0x25,0x18},
+ {0xF1,0x05,0x1F,0x16},
+ {0xF6,0x06,0x1A,0x14},
+ {0xFA,0x06,0x16,0x14},
+ {0x00,0x04,0x10,0x18},
+ {0xFF,0xFF,0xFF,0xFF} }},
+ { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_3 */
+ {0xF1,0x04,0x1F,0x18},
+ {0xEE,0x0D,0x22,0x06},
+ {0xF7,0x06,0x19,0x14},
+ {0xF4,0x0B,0x1C,0x0A},
+ {0xFA,0x07,0x16,0x12},
+ {0xF9,0x0A,0x17,0x0C},
+ {0x00,0x07,0x10,0x12},
+ {0xFF,0xFF,0xFF,0xFF} }},
+ { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_4 */
+ {0x00,0xE0,0x10,0x60},
+ {0x00,0xEE,0x10,0x44},
+ {0x00,0xF4,0x10,0x38},
+ {0xF8,0xF4,0x18,0x38},
+ {0xFC,0xFB,0x14,0x2A},
+ {0x00,0x00,0x10,0x20},
+ {0x00,0x04,0x10,0x18},
+ {0xFF,0xFF,0xFF,0xFF} }},
+ { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_5 */
+ {0xF5,0xEE,0x1B,0x44},
+ {0xF8,0xF4,0x18,0x38},
+ {0xEB,0x04,0x25,0x18},
+ {0xF1,0x05,0x1F,0x16},
+ {0xF6,0x06,0x1A,0x14},
+ {0xFA,0x06,0x16,0x14},
+ {0x00,0x04,0x10,0x18},
+ {0xFF,0xFF,0xFF,0xFF} }},
+ { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_6 */
+ {0xEB,0x04,0x25,0x18},
+ {0xE7,0x0E,0x29,0x04},
+ {0xEE,0x0C,0x22,0x08},
+ {0xF6,0x0B,0x1A,0x0A},
+ {0xF9,0x0A,0x17,0x0C},
+ {0xFC,0x0A,0x14,0x0C},
+ {0x00,0x08,0x10,0x10},
+ {0xFF,0xFF,0xFF,0xFF} }},
+ { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_7 */
+ {0xEC,0x02,0x24,0x1C},
+ {0xF2,0x04,0x1E,0x18},
+ {0xEB,0x15,0x25,0xF6},
+ {0xF4,0x10,0x1C,0x00},
+ {0xF8,0x0F,0x18,0x02},
+ {0x00,0x04,0x10,0x18},
+ {0x01,0x06,0x0F,0x14},
+ {0xFF,0xFF,0xFF,0xFF} }},
+ { {{0x00,0x00,0x00,0x40}, /* PALFilter_0 */
+ {0x00,0xE0,0x10,0x60},
+ {0x00,0xEE,0x10,0x44},
+ {0x00,0xF4,0x10,0x38},
+ {0xF8,0xF4,0x18,0x38},
+ {0xFC,0xFB,0x14,0x2A},
+ {0x00,0x00,0x10,0x20},
+ {0x00,0x04,0x10,0x18},
+ {0xFF,0xFF,0xFF,0xFF} }},
+ { {{0x00,0x00,0x00,0x40}, /* PALFilter_1 */
+ {0x00,0xE0,0x10,0x60},
+ {0x00,0xEE,0x10,0x44},
+ {0x00,0xF4,0x10,0x38},
+ {0xF8,0xF4,0x18,0x38},
+ {0xFC,0xFB,0x14,0x2A},
+ {0x00,0x00,0x10,0x20},
+ {0x00,0x04,0x10,0x18},
+ {0xFF,0xFF,0xFF,0xFF} }},
+ { {{0x00,0x00,0x00,0x40}, /* PALFilter_2 */
+ {0xF5,0xEE,0x1B,0x44},
+ {0xF8,0xF4,0x18,0x38},
+ {0xF1,0xF7,0x01,0x32},
+ {0xF5,0xFB,0x1B,0x2A},
+ {0xF9,0xFF,0x17,0x22},
+ {0xFB,0x01,0x15,0x1E},
+ {0x00,0x04,0x10,0x18},
+ {0xFF,0xFF,0xFF,0xFF} }},
+ { {{0x00,0x00,0x00,0x40}, /* PALFilter_3 */
+ {0xF5,0xFB,0x1B,0x2A},
+ {0xEE,0xFE,0x22,0x24},
+ {0xF3,0x00,0x1D,0x20},
+ {0xF9,0x03,0x17,0x1A},
+ {0xFB,0x02,0x14,0x1E},
+ {0xFB,0x04,0x15,0x18},
+ {0x00,0x06,0x10,0x14},
+ {0xFF,0xFF,0xFF,0xFF} }},
+ { {{0x00,0x00,0x00,0x40}, /* PALFilter_4 */
+ {0x00,0xE0,0x10,0x60},
+ {0x00,0xEE,0x10,0x44},
+ {0x00,0xF4,0x10,0x38},
+ {0xF8,0xF4,0x18,0x38},
+ {0xFC,0xFB,0x14,0x2A},
+ {0x00,0x00,0x10,0x20},
+ {0x00,0x04,0x10,0x18},
+ {0xFF,0xFF,0xFF,0xFF} }},
+ { {{0x00,0x00,0x00,0x40}, /* PALFilter_5 */
+ {0xF5,0xEE,0x1B,0x44},
+ {0xF8,0xF4,0x18,0x38},
+ {0xF1,0xF7,0x1F,0x32},
+ {0xF5,0xFB,0x1B,0x2A},
+ {0xF9,0xFF,0x17,0x22},
+ {0xFB,0x01,0x15,0x1E},
+ {0x00,0x04,0x10,0x18},
+ {0xFF,0xFF,0xFF,0xFF} }},
+ { {{0x00,0x00,0x00,0x40}, /* PALFilter_6 */
+ {0xF5,0xEE,0x1B,0x2A},
+ {0xEE,0xFE,0x22,0x24},
+ {0xF3,0x00,0x1D,0x20},
+ {0xF9,0x03,0x17,0x1A},
+ {0xFB,0x02,0x14,0x1E},
+ {0xFB,0x04,0x15,0x18},
+ {0x00,0x06,0x10,0x14},
+ {0xFF,0xFF,0xFF,0xFF} }},
+ { {{0x00,0x00,0x00,0x40}, /* PALFilter_7 */
+ {0xF5,0xEE,0x1B,0x44},
+ {0xF8,0xF4,0x18,0x38},
+ {0xFC,0xFB,0x14,0x2A},
+ {0xEB,0x05,0x25,0x16},
+ {0xF1,0x05,0x1F,0x16},
+ {0xFA,0x07,0x16,0x12},
+ {0x00,0x07,0x10,0x12},
+ {0xFF,0xFF,0xFF,0xFF} }}
+};
+
+static int filter = -1;
+static unsigned char filter_tb;
+
+
+/* ---------------------- Routine prototypes ------------------------- */
+
+/* Interface used by the world */
+#ifndef MODULE
+XGIINITSTATIC int __init XGIfb_setup(char *options);
+#endif
+
+/* Interface to the low level console driver */
+
+
+
+/* fbdev routines */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ int XGIfb_init(void);
+static int XGIfb_get_fix(struct fb_fix_screeninfo *fix,
+ int con,
+ struct fb_info *info);
+static int XGIfb_get_var(struct fb_var_screeninfo *var,
+ int con,
+ struct fb_info *info);
+static int XGIfb_set_var(struct fb_var_screeninfo *var,
+ int con,
+ struct fb_info *info);
+static void XGIfb_crtc_to_var(struct fb_var_screeninfo *var);
+static int XGIfb_get_cmap(struct fb_cmap *cmap,
+ int kspc,
+ int con,
+ struct fb_info *info);
+static int XGIfb_set_cmap(struct fb_cmap *cmap,
+ int kspc,
+ int con,
+ struct fb_info *info);
+static int XGIfb_update_var(int con,
+ struct fb_info *info);
+static int XGIfb_switch(int con,
+ struct fb_info *info);
+static void XGIfb_blank(int blank,
+ struct fb_info *info);
+static void XGIfb_set_disp(int con,
+ struct fb_var_screeninfo *var,
+ struct fb_info *info);
+static int XGI_getcolreg(unsigned regno, unsigned *red, unsigned *green,
+ unsigned *blue, unsigned *transp,
+ struct fb_info *fb_info);
+static void XGIfb_do_install_cmap(int con,
+ struct fb_info *info);
+static void XGI_get_glyph(struct fb_info *info,
+ XGI_GLYINFO *gly);
+static int XGIfb_mmap(struct fb_info *info, struct file *file,
+ struct vm_area_struct *vma);
+static int XGIfb_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg, int con,
+ struct fb_info *info);
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+XGIINITSTATIC int __init xgifb_init(void);
+static int XGIfb_set_par(struct fb_info *info);
+static int XGIfb_blank(int blank,
+ struct fb_info *info);
+/*static int XGIfb_mmap(struct fb_info *info, struct file *file,
+ struct vm_area_struct *vma);
+*/
+extern void fbcon_XGI_fillrect(struct fb_info *info,
+ const struct fb_fillrect *rect);
+extern void fbcon_XGI_copyarea(struct fb_info *info,
+ const struct fb_copyarea *area);
+#if 0
+extern void cfb_imageblit(struct fb_info *info,
+ const struct fb_image *image);
+#endif
+extern int fbcon_XGI_sync(struct fb_info *info);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
+static int XGIfb_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg);
+#else
+static int XGIfb_ioctl(struct inode *inode,
+ struct file *file,
+ unsigned int cmd,
+ unsigned long arg,
+ struct fb_info *info);
+#endif
+
+/*
+extern int XGIfb_mode_rate_to_dclock(VB_DEVICE_INFO *XGI_Pr,
+ PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ unsigned char modeno, unsigned char rateindex);
+extern int XGIfb_mode_rate_to_ddata(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ unsigned char modeno, unsigned char rateindex,
+ unsigned int *left_margin, unsigned int *right_margin,
+ unsigned int *upper_margin, unsigned int *lower_margin,
+ unsigned int *hsync_len, unsigned int *vsync_len,
+ unsigned int *sync, unsigned int *vmode);
+*/
+#endif
+ extern BOOLEAN XGI_SearchModeID( USHORT ModeNo,USHORT *ModeIdIndex, PVB_DEVICE_INFO );
+static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info);
+
+/* Internal 2D accelerator functions */
+extern int XGIfb_initaccel(void);
+extern void XGIfb_syncaccel(void);
+
+/* Internal general routines */
+static void XGIfb_search_mode(const char *name);
+static int XGIfb_validate_mode(int modeindex);
+static u8 XGIfb_search_refresh_rate(unsigned int rate);
+static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *fb_info);
+static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
+ struct fb_info *info);
+static void XGIfb_pre_setmode(void);
+static void XGIfb_post_setmode(void);
+
+static BOOLEAN XGIfb_CheckVBRetrace(void);
+static BOOLEAN XGIfbcheckvretracecrt2(void);
+static BOOLEAN XGIfbcheckvretracecrt1(void);
+static BOOLEAN XGIfb_bridgeisslave(void);
+
+struct XGI_memreq {
+ unsigned long offset;
+ unsigned long size;
+};
+
+/* XGI-specific Export functions */
+void XGI_dispinfo(struct ap_data *rec);
+void XGI_malloc(struct XGI_memreq *req);
+void XGI_free(unsigned long base);
+
+/* Internal hardware access routines */
+void XGIfb_set_reg4(u16 port, unsigned long data);
+u32 XGIfb_get_reg3(u16 port);
+
+/* Chipset-dependent internal routines */
+
+
+static int XGIfb_get_dram_size(void);
+static void XGIfb_detect_VB(void);
+static void XGIfb_get_VB_type(void);
+static int XGIfb_has_VB(void);
+
+
+/* Internal heap routines */
+static int XGIfb_heap_init(void);
+static XGI_OH *XGIfb_poh_new_node(void);
+static XGI_OH *XGIfb_poh_allocate(unsigned long size);
+static void XGIfb_delete_node(XGI_OH *poh);
+static void XGIfb_insert_node(XGI_OH *pohList, XGI_OH *poh);
+static XGI_OH *XGIfb_poh_free(unsigned long base);
+static void XGIfb_free_node(XGI_OH *poh);
+
+/* Internal routines to access PCI configuration space */
+BOOLEAN XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
+ unsigned long offset, unsigned long set, unsigned long *value);
+//BOOLEAN XGIfb_query_north_bridge_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
+// unsigned long offset, unsigned long set, unsigned long *value);
+
+
+/* Routines from init.c/init301.c */
+extern void InitTo330Pointer(UCHAR,PVB_DEVICE_INFO pVBInfo);
+extern BOOLEAN XGIInitNew(PXGI_HW_DEVICE_INFO HwDeviceExtension);
+extern BOOLEAN XGISetModeNew(PXGI_HW_DEVICE_INFO HwDeviceExtension, USHORT ModeNo);
+//extern void XGI_SetEnableDstn(VB_DEVICE_INFO *XGI_Pr);
+extern void XGI_LongWait(VB_DEVICE_INFO *XGI_Pr);
+extern USHORT XGI_GetRatePtrCRT2( PXGI_HW_DEVICE_INFO pXGIHWDE, USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo );
+/* TW: Chrontel TV functions */
+extern USHORT XGI_GetCH700x(VB_DEVICE_INFO *XGI_Pr, USHORT tempbx);
+extern void XGI_SetCH700x(VB_DEVICE_INFO *XGI_Pr, USHORT tempbx);
+extern USHORT XGI_GetCH701x(VB_DEVICE_INFO *XGI_Pr, USHORT tempbx);
+extern void XGI_SetCH701x(VB_DEVICE_INFO *XGI_Pr, USHORT tempbx);
+extern void XGI_SetCH70xxANDOR(VB_DEVICE_INFO *XGI_Pr, USHORT tempax,USHORT tempbh);
+extern void XGI_DDC2Delay(VB_DEVICE_INFO *XGI_Pr, USHORT delaytime);
+
+/* TW: Sensing routines */
+void XGI_Sense30x(void);
+int XGIDoSense(int tempbl, int tempbh, int tempcl, int tempch);
+
+extern XGI21_LVDSCapStruct XGI21_LCDCapList[13];
+#endif
diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
new file mode 100644
index 0000000..867012b
--- /dev/null
+++ b/drivers/staging/xgifb/XGI_main_26.c
@@ -0,0 +1,3773 @@
+/*
+ * XG20, XG21, XG40, XG42 frame buffer device
+ * for Linux kernels 2.5.x, 2.6.x
+ * Base on TW's sis fbdev code.
+ */
+
+//#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/console.h>
+#include <linux/selection.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/vt_kern.h>
+#include <linux/capability.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/kernel.h>
+
+#include "osdef.h"
+
+
+#ifndef XGIFB_PAN
+#define XGIFB_PAN
+#endif
+
+#include <asm/io.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include "XGIfb.h"
+#include "vgatypes.h"
+#include "XGI_main.h"
+#include "vb_util.h"
+
+
+#define Index_CR_GPIO_Reg1 0x48
+#define Index_CR_GPIO_Reg2 0x49
+#define Index_CR_GPIO_Reg3 0x4a
+
+#define GPIOG_EN (1<<6)
+#define GPIOG_WRITE (1<<6)
+#define GPIOG_READ (1<<1)
+int XGIfb_GetXG21DefaultLVDSModeIdx(void);
+
+/* -------------------- Macro definitions ---------------------------- */
+
+#undef XGIFBDEBUG
+
+#ifdef XGIFBDEBUG
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#ifdef XGIFBDEBUG
+static void dumpVGAReg(void)
+{
+ u8 i,reg;
+
+outXGIIDXREG(XGISR, 0x05, 0x86);
+/*
+outXGIIDXREG(XGISR, 0x08, 0x4f);
+outXGIIDXREG(XGISR, 0x0f, 0x20);
+outXGIIDXREG(XGISR, 0x11, 0x4f);
+outXGIIDXREG(XGISR, 0x13, 0x45);
+outXGIIDXREG(XGISR, 0x14, 0x51);
+outXGIIDXREG(XGISR, 0x1e, 0x41);
+outXGIIDXREG(XGISR, 0x1f, 0x0);
+outXGIIDXREG(XGISR, 0x20, 0xa1);
+outXGIIDXREG(XGISR, 0x22, 0xfb);
+outXGIIDXREG(XGISR, 0x26, 0x22);
+outXGIIDXREG(XGISR, 0x3e, 0x07);
+*/
+
+//outXGIIDXREG(XGICR, 0x19, 0x00);
+//outXGIIDXREG(XGICR, 0x1a, 0x3C);
+//outXGIIDXREG(XGICR, 0x22, 0xff);
+//outXGIIDXREG(XGICR, 0x3D, 0x10);
+
+//outXGIIDXREG(XGICR, 0x4a, 0xf3);
+
+//outXGIIDXREG(XGICR, 0x57, 0x0);
+//outXGIIDXREG(XGICR, 0x7a, 0x2c);
+
+//outXGIIDXREG(XGICR, 0x82, 0xcc);
+//outXGIIDXREG(XGICR, 0x8c, 0x0);
+/*
+outXGIIDXREG(XGICR, 0x99, 0x1);
+outXGIIDXREG(XGICR, 0x41, 0x40);
+*/
+
+ for(i=0; i < 0x4f; i++)
+ {
+ inXGIIDXREG(XGISR, i, reg);
+ printk("\no 3c4 %x",i);
+ printk("\ni 3c5 => %x",reg);
+ }
+
+ for(i=0; i < 0xF0; i++)
+ {
+ inXGIIDXREG(XGICR, i, reg);
+ printk("\no 3d4 %x",i);
+ printk("\ni 3d5 => %x",reg);
+ }
+/*
+
+ outXGIIDXREG(XGIPART1,0x2F,1);
+ for(i=1; i < 0x50; i++)
+ {
+ inXGIIDXREG(XGIPART1, i, reg);
+ printk("\no d004 %x",i);
+ printk("\ni d005 => %x",reg);
+ }
+
+ for(i=0; i < 0x50; i++)
+ {
+ inXGIIDXREG(XGIPART2, i, reg);
+ printk("\no d010 %x",i);
+ printk("\ni d011 => %x",reg);
+ }
+ for(i=0; i < 0x50; i++)
+ {
+ inXGIIDXREG(XGIPART3, i, reg);
+ printk("\no d012 %x",i);
+ printk("\ni d013 => %x",reg);
+ }
+ for(i=0; i < 0x50; i++)
+ {
+ inXGIIDXREG(XGIPART4, i, reg);
+ printk("\no d014 %x",i);
+ printk("\ni d015 => %x",reg);
+ }
+*/
+}
+#else
+static inline void dumpVGAReg(void) {}
+#endif
+
+/* data for XGI components */
+struct video_info xgi_video_info;
+
+
+#if 1
+#define DEBUGPRN(x)
+#else
+#define DEBUGPRN(x) printk(KERN_INFO x "\n");
+#endif
+
+
+/* --------------- Hardware Access Routines -------------------------- */
+
+#ifdef LINUX_KERNEL
+int
+XGIfb_mode_rate_to_dclock(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ unsigned char modeno, unsigned char rateindex)
+{
+ USHORT ModeNo = modeno;
+ USHORT ModeIdIndex = 0, ClockIndex = 0;
+ USHORT RefreshRateTableIndex = 0;
+
+ /*ULONG temp = 0;*/
+ int Clock;
+ XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
+ InitTo330Pointer( HwDeviceExtension->jChipType, XGI_Pr ) ;
+
+ RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, XGI_Pr ) ;
+
+/*
+ temp = XGI_SearchModeID( ModeNo , &ModeIdIndex, XGI_Pr ) ;
+ if(!temp) {
+ printk(KERN_ERR "Could not find mode %x\n", ModeNo);
+ return 65000;
+ }
+
+ RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
+ RefreshRateTableIndex += (rateindex - 1);
+
+*/
+ ClockIndex = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
+ if(HwDeviceExtension->jChipType < XGI_315H) {
+ ClockIndex &= 0x3F;
+ }
+ Clock = XGI_Pr->VCLKData[ClockIndex].CLOCK * 1000 ;
+
+ return(Clock);
+}
+
+int
+XGIfb_mode_rate_to_ddata(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ unsigned char modeno, unsigned char rateindex,
+ u32 *left_margin, u32 *right_margin,
+ u32 *upper_margin, u32 *lower_margin,
+ u32 *hsync_len, u32 *vsync_len,
+ u32 *sync, u32 *vmode)
+{
+ USHORT ModeNo = modeno;
+ USHORT ModeIdIndex = 0, index = 0;
+ USHORT RefreshRateTableIndex = 0;
+
+ unsigned short VRE, VBE, VRS, VBS, VDE, VT;
+ unsigned short HRE, HBE, HRS, HBS, HDE, HT;
+ unsigned char sr_data, cr_data, cr_data2;
+ unsigned long cr_data3;
+ int A, B, C, D, E, F, temp, j;
+ XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
+ InitTo330Pointer( HwDeviceExtension->jChipType, XGI_Pr ) ;
+ RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, XGI_Pr ) ;
+/*
+ temp = XGI_SearchModeID( ModeNo, &ModeIdIndex, XGI_Pr);
+ if(!temp) return 0;
+
+ RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
+ RefreshRateTableIndex += (rateindex - 1);
+*/
+ index = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+
+ sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[5];
+
+ cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[0];
+
+ /* Horizontal total */
+ HT = (cr_data & 0xff) |
+ ((unsigned short) (sr_data & 0x03) << 8);
+ A = HT + 5;
+
+ /*cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
+
+ Horizontal display enable end
+ HDE = (cr_data & 0xff) |
+ ((unsigned short) (sr_data & 0x0C) << 6);*/
+ HDE = (XGI_Pr->RefIndex[RefreshRateTableIndex].XRes >> 3) -1;
+ E = HDE + 1;
+
+ cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[3];
+
+ /* Horizontal retrace (=sync) start */
+ HRS = (cr_data & 0xff) |
+ ((unsigned short) (sr_data & 0xC0) << 2);
+ F = HRS - E - 3;
+
+ cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
+
+ /* Horizontal blank start */
+ HBS = (cr_data & 0xff) |
+ ((unsigned short) (sr_data & 0x30) << 4);
+
+ sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[6];
+
+ cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[2];
+
+ cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[4];
+
+ /* Horizontal blank end */
+ HBE = (cr_data & 0x1f) |
+ ((unsigned short) (cr_data2 & 0x80) >> 2) |
+ ((unsigned short) (sr_data & 0x03) << 6);
+
+ /* Horizontal retrace (=sync) end */
+ HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
+
+ temp = HBE - ((E - 1) & 255);
+ B = (temp > 0) ? temp : (temp + 256);
+
+ temp = HRE - ((E + F + 3) & 63);
+ C = (temp > 0) ? temp : (temp + 64);
+
+ D = B - F - C;
+
+ *left_margin = D * 8;
+ *right_margin = F * 8;
+ *hsync_len = C * 8;
+
+ sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[14];
+
+ cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[8];
+
+ cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[9];
+
+ /* Vertical total */
+ VT = (cr_data & 0xFF) |
+ ((unsigned short) (cr_data2 & 0x01) << 8) |
+ ((unsigned short)(cr_data2 & 0x20) << 4) |
+ ((unsigned short) (sr_data & 0x01) << 10);
+ A = VT + 2;
+
+ //cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
+
+ /* Vertical display enable end */
+/* VDE = (cr_data & 0xff) |
+ ((unsigned short) (cr_data2 & 0x02) << 7) |
+ ((unsigned short) (cr_data2 & 0x40) << 3) |
+ ((unsigned short) (sr_data & 0x02) << 9); */
+ VDE = XGI_Pr->RefIndex[RefreshRateTableIndex].YRes -1;
+ E = VDE + 1;
+
+ cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
+
+ /* Vertical retrace (=sync) start */
+ VRS = (cr_data & 0xff) |
+ ((unsigned short) (cr_data2 & 0x04) << 6) |
+ ((unsigned short) (cr_data2 & 0x80) << 2) |
+ ((unsigned short) (sr_data & 0x08) << 7);
+ F = VRS + 1 - E;
+
+ cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[12];
+
+ cr_data3 = (XGI_Pr->XGINEWUB_CRT1Table[index].CR[14] & 0x80) << 5;
+
+ /* Vertical blank start */
+ VBS = (cr_data & 0xff) |
+ ((unsigned short) (cr_data2 & 0x08) << 5) |
+ ((unsigned short) (cr_data3 & 0x20) << 4) |
+ ((unsigned short) (sr_data & 0x04) << 8);
+
+ cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[13];
+
+ /* Vertical blank end */
+ VBE = (cr_data & 0xff) |
+ ((unsigned short) (sr_data & 0x10) << 4);
+ temp = VBE - ((E - 1) & 511);
+ B = (temp > 0) ? temp : (temp + 512);
+
+ cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[11];
+
+ /* Vertical retrace (=sync) end */
+ VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
+ temp = VRE - ((E + F - 1) & 31);
+ C = (temp > 0) ? temp : (temp + 32);
+
+ D = B - F - C;
+
+ *upper_margin = D;
+ *lower_margin = F;
+ *vsync_len = C;
+
+ if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
+ *sync &= ~FB_SYNC_VERT_HIGH_ACT;
+ else
+ *sync |= FB_SYNC_VERT_HIGH_ACT;
+
+ if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)
+ *sync &= ~FB_SYNC_HOR_HIGH_ACT;
+ else
+ *sync |= FB_SYNC_HOR_HIGH_ACT;
+
+ *vmode = FB_VMODE_NONINTERLACED;
+ if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
+ *vmode = FB_VMODE_INTERLACED;
+ else {
+ j = 0;
+ while(XGI_Pr->EModeIDTable[j].Ext_ModeID != 0xff) {
+ if(XGI_Pr->EModeIDTable[j].Ext_ModeID ==
+ XGI_Pr->RefIndex[RefreshRateTableIndex].ModeID) {
+ if(XGI_Pr->EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) {
+ *vmode = FB_VMODE_DOUBLE;
+ }
+ break;
+ }
+ j++;
+ }
+ }
+
+#if 0 /* That's bullshit, only the resolution needs to be shifted */
+ if((*vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+ *upper_margin <<= 1;
+ *lower_margin <<= 1;
+ *vsync_len <<= 1;
+ } else if((*vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+ *upper_margin >>= 1;
+ *lower_margin >>= 1;
+ *vsync_len >>= 1;
+ }
+#endif
+
+ return 1;
+}
+
+#endif
+
+
+
+void XGIRegInit(VB_DEVICE_INFO *XGI_Pr, ULONG BaseAddr)
+{
+ XGI_Pr->RelIO = BaseAddr;
+ XGI_Pr->P3c4 = BaseAddr + 0x14;
+ XGI_Pr->P3d4 = BaseAddr + 0x24;
+ XGI_Pr->P3c0 = BaseAddr + 0x10;
+ XGI_Pr->P3ce = BaseAddr + 0x1e;
+ XGI_Pr->P3c2 = BaseAddr + 0x12;
+ XGI_Pr->P3ca = BaseAddr + 0x1a;
+ XGI_Pr->P3c6 = BaseAddr + 0x16;
+ XGI_Pr->P3c7 = BaseAddr + 0x17;
+ XGI_Pr->P3c8 = BaseAddr + 0x18;
+ XGI_Pr->P3c9 = BaseAddr + 0x19;
+ XGI_Pr->P3da = BaseAddr + 0x2A;
+ XGI_Pr->Part1Port = BaseAddr + XGI_CRT2_PORT_04; /* Digital video interface registers (LCD) */
+ XGI_Pr->Part2Port = BaseAddr + XGI_CRT2_PORT_10; /* 301 TV Encoder registers */
+ XGI_Pr->Part3Port = BaseAddr + XGI_CRT2_PORT_12; /* 301 Macrovision registers */
+ XGI_Pr->Part4Port = BaseAddr + XGI_CRT2_PORT_14; /* 301 VGA2 (and LCD) registers */
+ XGI_Pr->Part5Port = BaseAddr + XGI_CRT2_PORT_14+2; /* 301 palette address port registers */
+
+}
+
+
+void XGIfb_set_reg4(u16 port, unsigned long data)
+{
+ outl((u32) (data & 0xffffffff), port);
+}
+
+u32 XGIfb_get_reg3(u16 port)
+{
+ u32 data;
+
+ data = inl(port);
+ return (data);
+}
+
+/* ------------ Interface for init & mode switching code ------------- */
+
+BOOLEAN
+XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
+ unsigned long offset, unsigned long set, unsigned long *value)
+{
+ static struct pci_dev *pdev = NULL;
+ static unsigned char init = 0, valid_pdev = 0;
+
+ if (!set)
+ DPRINTK("XGIfb: Get VGA offset 0x%lx\n", offset);
+ else
+ DPRINTK("XGIfb: Set offset 0x%lx to 0x%lx\n", offset, *value);
+
+ if (!init) {
+ init = TRUE;
+ pdev = pci_get_device(PCI_VENDOR_ID_XG, xgi_video_info.chip_id, pdev);
+ if (pdev) {
+ valid_pdev = TRUE;
+ pci_dev_put(pdev);
+ }
+ }
+
+ if (!valid_pdev) {
+ printk(KERN_DEBUG "XGIfb: Can't find XGI %d VGA device.\n",
+ xgi_video_info.chip_id);
+ return FALSE;
+ }
+
+ if (set == 0)
+ pci_read_config_dword(pdev, offset, (u32 *)value);
+ else
+ pci_write_config_dword(pdev, offset, (u32)(*value));
+
+ return TRUE;
+}
+
+/*BOOLEAN XGIfb_query_north_bridge_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
+ unsigned long offset, unsigned long set, unsigned long *value)
+{
+ static struct pci_dev *pdev = NULL;
+ static unsigned char init = 0, valid_pdev = 0;
+ u16 nbridge_id = 0;
+
+ if (!init) {
+ init = TRUE;
+ switch (xgi_video_info.chip) {
+ case XGI_540:
+ nbridge_id = PCI_DEVICE_ID_XG_540;
+ break;
+ case XGI_630:
+ nbridge_id = PCI_DEVICE_ID_XG_630;
+ break;
+ case XGI_730:
+ nbridge_id = PCI_DEVICE_ID_XG_730;
+ break;
+ case XGI_550:
+ nbridge_id = PCI_DEVICE_ID_XG_550;
+ break;
+ case XGI_650:
+ nbridge_id = PCI_DEVICE_ID_XG_650;
+ break;
+ case XGI_740:
+ nbridge_id = PCI_DEVICE_ID_XG_740;
+ break;
+ default:
+ nbridge_id = 0;
+ break;
+ }
+
+ pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridge_id, pdev);
+ if (pdev)
+ valid_pdev = TRUE;
+ }
+
+ if (!valid_pdev) {
+ printk(KERN_DEBUG "XGIfb: Can't find XGI %d North Bridge device.\n",
+ nbridge_id);
+ return FALSE;
+ }
+
+ if (set == 0)
+ pci_read_config_dword(pdev, offset, (u32 *)value);
+ else
+ pci_write_config_dword(pdev, offset, (u32)(*value));
+
+ return TRUE;
+}
+*/
+/* ------------------ Internal helper routines ----------------- */
+
+static void XGIfb_search_mode(const char *name)
+{
+ int i = 0, j = 0, l;
+
+ if(name == NULL) {
+ printk(KERN_ERR "XGIfb: Internal error, using default mode.\n");
+ xgifb_mode_idx = DEFAULT_MODE;
+ if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD))
+ {
+ xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
+ }
+ return;
+ }
+
+
+ if (!strcmp(name, XGIbios_mode[MODE_INDEX_NONE].name)) {
+ printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
+ xgifb_mode_idx = DEFAULT_MODE;
+ if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD))
+ {
+ xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
+ }
+ return;
+ }
+
+ while(XGIbios_mode[i].mode_no != 0) {
+ l = min(strlen(name), strlen(XGIbios_mode[i].name));
+ if (!strncmp(name, XGIbios_mode[i].name, l)) {
+ xgifb_mode_idx = i;
+ j = 1;
+ break;
+ }
+ i++;
+ }
+ if(!j) printk(KERN_INFO "XGIfb: Invalid mode '%s'\n", name);
+}
+
+static void XGIfb_search_vesamode(unsigned int vesamode)
+{
+ int i = 0, j = 0;
+
+ if(vesamode == 0) {
+
+ printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
+ xgifb_mode_idx = DEFAULT_MODE;
+ if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD))
+ {
+ xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
+ }
+ return;
+ }
+
+ vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
+
+ while(XGIbios_mode[i].mode_no != 0) {
+ if( (XGIbios_mode[i].vesa_mode_no_1 == vesamode) ||
+ (XGIbios_mode[i].vesa_mode_no_2 == vesamode) ) {
+ xgifb_mode_idx = i;
+ j = 1;
+ break;
+ }
+ i++;
+ }
+ if(!j) printk(KERN_INFO "XGIfb: Invalid VESA mode 0x%x'\n", vesamode);
+}
+
+int XGIfb_GetXG21LVDSData(void)
+{
+ u8 tmp;
+ unsigned char *pData;
+ int i,j,k;
+
+ inXGIIDXREG(XGISR,0x1e,tmp);
+ outXGIIDXREG(XGISR, 0x1e, tmp|4);
+
+ pData = xgi_video_info.mmio_vbase+0x20000;
+ if ((pData[0x0]==0x55) && (pData[0x1]==0xAA) && (pData[0x65] & 0x1))
+ {
+ i = pData[ 0x316 ] | ( pData[ 0x317 ] << 8 );
+ j = pData[ i-1 ] ;
+ if ( j == 0xff )
+ {
+ j = 1;
+ }
+ k = 0;
+ do
+ {
+ XGI21_LCDCapList[k].LVDS_Capability = pData[ i ] | ( pData[ i + 1 ] << 8 );
+ XGI21_LCDCapList[k].LVDSHT = pData[ i + 2 ] | ( pData[ i + 3 ] << 8 ) ;
+ XGI21_LCDCapList[k].LVDSVT = pData[ i + 4 ] | ( pData[ i + 5 ] << 8 );
+ XGI21_LCDCapList[k].LVDSHDE = pData[ i + 6 ] | ( pData[ i + 7 ] << 8 );
+ XGI21_LCDCapList[k].LVDSVDE = pData[ i + 8 ] | ( pData[ i + 9 ] << 8 );
+ XGI21_LCDCapList[k].LVDSHFP = pData[ i + 10 ] | ( pData[ i + 11 ] << 8 );
+ XGI21_LCDCapList[k].LVDSVFP = pData[ i + 12 ] | ( pData[ i + 13 ] << 8 );
+ XGI21_LCDCapList[k].LVDSHSYNC = pData[ i + 14 ] | ( pData[ i + 15 ] << 8 );
+ XGI21_LCDCapList[k].LVDSVSYNC = pData[ i + 16 ] | ( pData[ i + 17 ] << 8 );
+ XGI21_LCDCapList[k].VCLKData1 = pData[ i + 18 ] ;
+ XGI21_LCDCapList[k].VCLKData2 = pData[ i + 19 ] ;
+ XGI21_LCDCapList[k].PSC_S1 = pData[ i + 20 ] ;
+ XGI21_LCDCapList[k].PSC_S2 = pData[ i + 21 ] ;
+ XGI21_LCDCapList[k].PSC_S3 = pData[ i + 22 ] ;
+ XGI21_LCDCapList[k].PSC_S4 = pData[ i + 23 ] ;
+ XGI21_LCDCapList[k].PSC_S5 = pData[ i + 24 ] ;
+ i += 25;
+ j--;
+ k++;
+ } while ( (j>0) && ( k < (sizeof(XGI21_LCDCapList)/sizeof(XGI21_LVDSCapStruct)) ) );
+ return 1;
+ }
+ return 0;
+}
+
+int XGIfb_GetXG21DefaultLVDSModeIdx(void)
+{
+
+ int found_mode = 0;
+ int XGIfb_mode_idx = 0;
+
+ found_mode = 0;
+ while( (XGIbios_mode[XGIfb_mode_idx].mode_no != 0) &&
+ (XGIbios_mode[XGIfb_mode_idx].xres <= XGI21_LCDCapList[0].LVDSHDE) )
+ {
+ if( (XGIbios_mode[XGIfb_mode_idx].xres == XGI21_LCDCapList[0].LVDSHDE) &&
+ (XGIbios_mode[XGIfb_mode_idx].yres == XGI21_LCDCapList[0].LVDSVDE) &&
+ (XGIbios_mode[XGIfb_mode_idx].bpp == 8))
+ {
+ XGIfb_mode_no = XGIbios_mode[XGIfb_mode_idx].mode_no;
+ found_mode = 1;
+ break;
+ }
+ XGIfb_mode_idx++;
+ }
+ if (!found_mode)
+ XGIfb_mode_idx = 0;
+
+ return (XGIfb_mode_idx);
+}
+
+
+static int XGIfb_validate_mode(int myindex)
+{
+ u16 xres, yres;
+
+ if (xgi_video_info.chip == XG21)
+ {
+ if ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD)
+ {
+ xres = XGI21_LCDCapList[0].LVDSHDE;
+ yres = XGI21_LCDCapList[0].LVDSVDE;
+ if(XGIbios_mode[myindex].xres > xres)
+ return(-1);
+ if(XGIbios_mode[myindex].yres > yres)
+ return(-1);
+ if ((XGIbios_mode[myindex].xres < xres) && (XGIbios_mode[myindex].yres < yres) )
+ {
+ if (XGIbios_mode[myindex].bpp > 8)
+ return(-1);
+ }
+
+ }
+ return(myindex);
+
+ }
+
+ /* FIXME: for now, all is valid on XG27 */
+ if (xgi_video_info.chip == XG27)
+ return(myindex);
+
+ if(!(XGIbios_mode[myindex].chipset & MD_XGI315))
+ return(-1);
+
+ switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
+ case DISPTYPE_LCD:
+ switch (XGIhw_ext.ulCRT2LCDType) {
+ case LCD_640x480:
+ xres = 640; yres = 480; break;
+ case LCD_800x600:
+ xres = 800; yres = 600; break;
+ case LCD_1024x600:
+ xres = 1024; yres = 600; break;
+ case LCD_1024x768:
+ xres = 1024; yres = 768; break;
+ case LCD_1152x768:
+ xres = 1152; yres = 768; break;
+ case LCD_1280x960:
+ xres = 1280; yres = 960; break;
+ case LCD_1280x768:
+ xres = 1280; yres = 768; break;
+ case LCD_1280x1024:
+ xres = 1280; yres = 1024; break;
+ case LCD_1400x1050:
+ xres = 1400; yres = 1050; break;
+ case LCD_1600x1200:
+ xres = 1600; yres = 1200; break;
+// case LCD_320x480: // TW: FSTN
+// xres = 320; yres = 480; break;
+ default:
+ xres = 0; yres = 0; break;
+ }
+ if(XGIbios_mode[myindex].xres > xres) {
+ return(-1);
+ }
+ if(XGIbios_mode[myindex].yres > yres) {
+ return(-1);
+ }
+ if((XGIhw_ext.ulExternalChip == 0x01) || // LVDS
+ (XGIhw_ext.ulExternalChip == 0x05)) // LVDS+Chrontel
+ {
+ switch (XGIbios_mode[myindex].xres) {
+ case 512:
+ if(XGIbios_mode[myindex].yres != 512) return -1;
+ if(XGIhw_ext.ulCRT2LCDType == LCD_1024x600) return -1;
+ break;
+ case 640:
+ if((XGIbios_mode[myindex].yres != 400) &&
+ (XGIbios_mode[myindex].yres != 480))
+ return -1;
+ break;
+ case 800:
+ if(XGIbios_mode[myindex].yres != 600) return -1;
+ break;
+ case 1024:
+ if((XGIbios_mode[myindex].yres != 600) &&
+ (XGIbios_mode[myindex].yres != 768))
+ return -1;
+ if((XGIbios_mode[myindex].yres == 600) &&
+ (XGIhw_ext.ulCRT2LCDType != LCD_1024x600))
+ return -1;
+ break;
+ case 1152:
+ if((XGIbios_mode[myindex].yres) != 768) return -1;
+ if(XGIhw_ext.ulCRT2LCDType != LCD_1152x768) return -1;
+ break;
+ case 1280:
+ if((XGIbios_mode[myindex].yres != 768) &&
+ (XGIbios_mode[myindex].yres != 1024))
+ return -1;
+ if((XGIbios_mode[myindex].yres == 768) &&
+ (XGIhw_ext.ulCRT2LCDType != LCD_1280x768))
+ return -1;
+ break;
+ case 1400:
+ if(XGIbios_mode[myindex].yres != 1050) return -1;
+ break;
+ case 1600:
+ if(XGIbios_mode[myindex].yres != 1200) return -1;
+ break;
+ default:
+ return -1;
+ }
+ } else {
+ switch (XGIbios_mode[myindex].xres) {
+ case 512:
+ if(XGIbios_mode[myindex].yres != 512) return -1;
+ break;
+ case 640:
+ if((XGIbios_mode[myindex].yres != 400) &&
+ (XGIbios_mode[myindex].yres != 480))
+ return -1;
+ break;
+ case 800:
+ if(XGIbios_mode[myindex].yres != 600) return -1;
+ break;
+ case 1024:
+ if(XGIbios_mode[myindex].yres != 768) return -1;
+ break;
+ case 1280:
+ if((XGIbios_mode[myindex].yres != 960) &&
+ (XGIbios_mode[myindex].yres != 1024))
+ return -1;
+ if(XGIbios_mode[myindex].yres == 960) {
+ if(XGIhw_ext.ulCRT2LCDType == LCD_1400x1050)
+ return -1;
+ }
+ break;
+ case 1400:
+ if(XGIbios_mode[myindex].yres != 1050) return -1;
+ break;
+ case 1600:
+ if(XGIbios_mode[myindex].yres != 1200) return -1;
+ break;
+ default:
+ return -1;
+ }
+ }
+ break;
+ case DISPTYPE_TV:
+ switch (XGIbios_mode[myindex].xres) {
+ case 512:
+ case 640:
+ case 800:
+ break;
+ case 720:
+ if (xgi_video_info.TV_type == TVMODE_NTSC) {
+ if (XGIbios_mode[myindex].yres != 480) {
+ return(-1);
+ }
+ } else if (xgi_video_info.TV_type == TVMODE_PAL) {
+ if (XGIbios_mode[myindex].yres != 576) {
+ return(-1);
+ }
+ }
+ // TW: LVDS/CHRONTEL does not support 720
+ if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL ||
+ xgi_video_info.hasVB == HASVB_CHRONTEL) {
+ return(-1);
+ }
+ break;
+ case 1024:
+ if (xgi_video_info.TV_type == TVMODE_NTSC) {
+ if(XGIbios_mode[myindex].bpp == 32) {
+ return(-1);
+ }
+ }
+ // TW: LVDS/CHRONTEL only supports < 800 (1024 on 650/Ch7019)
+ if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL ||
+ xgi_video_info.hasVB == HASVB_CHRONTEL) {
+ if(xgi_video_info.chip < XGI_315H) {
+ return(-1);
+ }
+ }
+ break;
+ default:
+ return(-1);
+ }
+ break;
+ case DISPTYPE_CRT2:
+ if(XGIbios_mode[myindex].xres > 1280) return -1;
+ break;
+ }
+ return(myindex);
+
+}
+
+static void XGIfb_search_crt2type(const char *name)
+{
+ int i = 0;
+
+ if(name == NULL)
+ return;
+
+ while(XGI_crt2type[i].type_no != -1) {
+ if (!strcmp(name, XGI_crt2type[i].name)) {
+ XGIfb_crt2type = XGI_crt2type[i].type_no;
+ XGIfb_tvplug = XGI_crt2type[i].tvplug_no;
+ break;
+ }
+ i++;
+ }
+ if(XGIfb_crt2type < 0)
+ printk(KERN_INFO "XGIfb: Invalid CRT2 type: %s\n", name);
+}
+
+static void XGIfb_search_queuemode(const char *name)
+{
+ int i = 0;
+
+ if(name == NULL)
+ return;
+
+ while (XGI_queuemode[i].type_no != -1) {
+ if (!strcmp(name, XGI_queuemode[i].name)) {
+ XGIfb_queuemode = XGI_queuemode[i].type_no;
+ break;
+ }
+ i++;
+ }
+ if (XGIfb_queuemode < 0)
+ printk(KERN_INFO "XGIfb: Invalid queuemode type: %s\n", name);
+}
+
+static u8 XGIfb_search_refresh_rate(unsigned int rate)
+{
+ u16 xres, yres;
+ int i = 0;
+
+ xres = XGIbios_mode[xgifb_mode_idx].xres;
+ yres = XGIbios_mode[xgifb_mode_idx].yres;
+
+ XGIfb_rate_idx = 0;
+ while ((XGIfb_vrate[i].idx != 0) && (XGIfb_vrate[i].xres <= xres)) {
+ if ((XGIfb_vrate[i].xres == xres) && (XGIfb_vrate[i].yres == yres)) {
+ if (XGIfb_vrate[i].refresh == rate) {
+ XGIfb_rate_idx = XGIfb_vrate[i].idx;
+ break;
+ } else if (XGIfb_vrate[i].refresh > rate) {
+ if ((XGIfb_vrate[i].refresh - rate) <= 3) {
+ DPRINTK("XGIfb: Adjusting rate from %d up to %d\n",
+ rate, XGIfb_vrate[i].refresh);
+ XGIfb_rate_idx = XGIfb_vrate[i].idx;
+ xgi_video_info.refresh_rate = XGIfb_vrate[i].refresh;
+ } else if (((rate - XGIfb_vrate[i-1].refresh) <= 2)
+ && (XGIfb_vrate[i].idx != 1)) {
+ DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
+ rate, XGIfb_vrate[i-1].refresh);
+ XGIfb_rate_idx = XGIfb_vrate[i-1].idx;
+ xgi_video_info.refresh_rate = XGIfb_vrate[i-1].refresh;
+ }
+ break;
+ } else if((rate - XGIfb_vrate[i].refresh) <= 2) {
+ DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
+ rate, XGIfb_vrate[i].refresh);
+ XGIfb_rate_idx = XGIfb_vrate[i].idx;
+ break;
+ }
+ }
+ i++;
+ }
+ if (XGIfb_rate_idx > 0) {
+ return XGIfb_rate_idx;
+ } else {
+ printk(KERN_INFO
+ "XGIfb: Unsupported rate %d for %dx%d\n", rate, xres, yres);
+ return 0;
+ }
+}
+
+static void XGIfb_search_tvstd(const char *name)
+{
+ int i = 0;
+
+ if(name == NULL)
+ return;
+
+ while (XGI_tvtype[i].type_no != -1) {
+ if (!strcmp(name, XGI_tvtype[i].name)) {
+ XGIfb_tvmode = XGI_tvtype[i].type_no;
+ break;
+ }
+ i++;
+ }
+}
+
+static BOOLEAN XGIfb_bridgeisslave(void)
+{
+ unsigned char usScratchP1_00;
+
+ if(xgi_video_info.hasVB == HASVB_NONE) return FALSE;
+
+ inXGIIDXREG(XGIPART1,0x00,usScratchP1_00);
+ if( (usScratchP1_00 & 0x50) == 0x10) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+static BOOLEAN XGIfbcheckvretracecrt1(void)
+{
+ unsigned char temp;
+
+ inXGIIDXREG(XGICR,0x17,temp);
+ if(!(temp & 0x80)) return FALSE;
+
+
+ inXGIIDXREG(XGISR,0x1f,temp);
+ if(temp & 0xc0) return FALSE;
+
+
+ if(inXGIREG(XGIINPSTAT) & 0x08) return TRUE;
+ else return FALSE;
+}
+
+static BOOLEAN XGIfbcheckvretracecrt2(void)
+{
+ unsigned char temp;
+ if(xgi_video_info.hasVB == HASVB_NONE) return FALSE;
+ inXGIIDXREG(XGIPART1, 0x30, temp);
+ if(temp & 0x02) return FALSE;
+ else return TRUE;
+}
+
+static BOOLEAN XGIfb_CheckVBRetrace(void)
+{
+ if(xgi_video_info.disp_state & DISPTYPE_DISP2) {
+ if(XGIfb_bridgeisslave()) {
+ return(XGIfbcheckvretracecrt1());
+ } else {
+ return(XGIfbcheckvretracecrt2());
+ }
+ }
+ return(XGIfbcheckvretracecrt1());
+}
+
+/* ----------- FBDev related routines for all series ----------- */
+
+
+static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var)
+{
+ switch(var->bits_per_pixel) {
+ case 8:
+ var->red.offset = var->green.offset = var->blue.offset = 0;
+ var->red.length = var->green.length = var->blue.length = 6;
+ xgi_video_info.video_cmap_len = 256;
+ break;
+ case 16:
+ var->red.offset = 11;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 6;
+ var->blue.offset = 0;
+ var->blue.length = 5;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ xgi_video_info.video_cmap_len = 16;
+ break;
+ case 32:
+ var->red.offset = 16;
+ var->red.length = 8;
+ var->green.offset = 8;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+ var->transp.offset = 24;
+ var->transp.length = 8;
+ xgi_video_info.video_cmap_len = 16;
+ break;
+ }
+}
+
+
+
+static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
+ struct fb_info *info)
+{
+
+ unsigned int htotal = var->left_margin + var->xres +
+ var->right_margin + var->hsync_len;
+ unsigned int vtotal = var->upper_margin + var->yres +
+ var->lower_margin + var->vsync_len;
+#if defined(__powerpc__)
+ u8 sr_data, cr_data;
+#endif
+ unsigned int drate = 0, hrate = 0;
+ int found_mode = 0;
+ int old_mode;
+// unsigned char reg,reg1;
+
+ DEBUGPRN("Inside do_set_var");
+// printk(KERN_DEBUG "XGIfb:var->yres=%d, var->upper_margin=%d, var->lower_margin=%d, var->vsync_len=%d\n", var->yres,var->upper_margin,var->lower_margin,var->vsync_len);
+
+ info->var.xres_virtual = var->xres_virtual;
+ info->var.yres_virtual = var->yres_virtual;
+ info->var.bits_per_pixel = var->bits_per_pixel;
+
+ if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
+ vtotal <<= 1;
+ else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
+ vtotal <<= 2;
+ else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
+ {
+// vtotal <<= 1;
+// var->yres <<= 1;
+ }
+
+ if(!htotal || !vtotal) {
+ DPRINTK("XGIfb: Invalid 'var' information\n");
+ return -EINVAL;
+ }
+ printk(KERN_DEBUG "XGIfb: var->pixclock=%d, htotal=%d, vtotal=%d\n",
+ var->pixclock,htotal,vtotal);
+
+
+
+ if(var->pixclock && htotal && vtotal) {
+ drate = 1000000000 / var->pixclock;
+ hrate = (drate * 1000) / htotal;
+ xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
+ } else {
+ xgi_video_info.refresh_rate = 60;
+ }
+
+ printk(KERN_DEBUG "XGIfb: Change mode to %dx%dx%d-%dHz\n",
+ var->xres,var->yres,var->bits_per_pixel,xgi_video_info.refresh_rate);
+
+ old_mode = xgifb_mode_idx;
+ xgifb_mode_idx = 0;
+
+ while( (XGIbios_mode[xgifb_mode_idx].mode_no != 0) &&
+ (XGIbios_mode[xgifb_mode_idx].xres <= var->xres) ) {
+ if( (XGIbios_mode[xgifb_mode_idx].xres == var->xres) &&
+ (XGIbios_mode[xgifb_mode_idx].yres == var->yres) &&
+ (XGIbios_mode[xgifb_mode_idx].bpp == var->bits_per_pixel)) {
+ XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
+ found_mode = 1;
+ break;
+ }
+ xgifb_mode_idx++;
+ }
+
+ if(found_mode)
+ xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
+ else
+ xgifb_mode_idx = -1;
+
+ if(xgifb_mode_idx < 0) {
+ printk(KERN_ERR "XGIfb: Mode %dx%dx%d not supported\n", var->xres,
+ var->yres, var->bits_per_pixel);
+ xgifb_mode_idx = old_mode;
+ return -EINVAL;
+ }
+
+ if(XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
+ XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
+ xgi_video_info.refresh_rate = 60;
+ }
+
+ if(isactive) {
+
+
+ XGIfb_pre_setmode();
+ if(XGISetModeNew( &XGIhw_ext, XGIfb_mode_no) == 0) {
+ printk(KERN_ERR "XGIfb: Setting mode[0x%x] failed\n", XGIfb_mode_no);
+ return -EINVAL;
+ }
+ info->fix.line_length = ((info->var.xres_virtual * info->var.bits_per_pixel)>>6);
+
+ outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
+
+ outXGIIDXREG(XGICR,0x13,(info->fix.line_length & 0x00ff));
+ outXGIIDXREG(XGISR,0x0E,(info->fix.line_length & 0xff00)>>8);
+
+ XGIfb_post_setmode();
+
+ DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d \n",
+ XGIbios_mode[xgifb_mode_idx].xres,
+ XGIbios_mode[xgifb_mode_idx].yres,
+ XGIbios_mode[xgifb_mode_idx].bpp,
+ xgi_video_info.refresh_rate);
+
+ xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
+ xgi_video_info.video_vwidth = info->var.xres_virtual;
+ xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
+ xgi_video_info.video_vheight = info->var.yres_virtual;
+ xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
+ xgi_video_info.org_x = xgi_video_info.org_y = 0;
+ xgi_video_info.video_linelength = info->var.xres_virtual * (xgi_video_info.video_bpp >> 3);
+ xgi_video_info.accel = 0;
+ if(XGIfb_accel) {
+ xgi_video_info.accel = (var->accel_flags & FB_ACCELF_TEXT) ? -1 : 0;
+ }
+ switch(xgi_video_info.video_bpp)
+ {
+ case 8:
+ xgi_video_info.DstColor = 0x0000;
+ xgi_video_info.XGI310_AccelDepth = 0x00000000;
+ xgi_video_info.video_cmap_len = 256;
+#if defined(__powerpc__)
+ inXGIIDXREG (XGICR, 0x4D, cr_data);
+ outXGIIDXREG(XGICR, 0x4D, (cr_data & 0xE0));
+#endif
+ break;
+ case 16:
+ xgi_video_info.DstColor = 0x8000;
+ xgi_video_info.XGI310_AccelDepth = 0x00010000;
+#if defined(__powerpc__)
+ inXGIIDXREG (XGICR, 0x4D, cr_data);
+ outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B));
+#endif
+ xgi_video_info.video_cmap_len = 16;
+ break;
+ case 32:
+ xgi_video_info.DstColor = 0xC000;
+ xgi_video_info.XGI310_AccelDepth = 0x00020000;
+ xgi_video_info.video_cmap_len = 16;
+#if defined(__powerpc__)
+ inXGIIDXREG (XGICR, 0x4D, cr_data);
+ outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15));
+#endif
+ break;
+ default:
+ xgi_video_info.video_cmap_len = 16;
+ printk(KERN_ERR "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
+ xgi_video_info.accel = 0;
+ break;
+ }
+ }
+ XGIfb_bpp_to_var(var); /*update ARGB info*/
+ DEBUGPRN("End of do_set_var");
+
+ dumpVGAReg();
+ return 0;
+}
+
+#ifdef XGIFB_PAN
+static int XGIfb_pan_var(struct fb_var_screeninfo *var)
+{
+ unsigned int base;
+
+// printk("Inside pan_var");
+
+ if (var->xoffset > (var->xres_virtual - var->xres)) {
+// printk( "Pan: xo: %d xv %d xr %d\n",
+// var->xoffset, var->xres_virtual, var->xres);
+ return -EINVAL;
+ }
+ if(var->yoffset > (var->yres_virtual - var->yres)) {
+// printk( "Pan: yo: %d yv %d yr %d\n",
+// var->yoffset, var->yres_virtual, var->yres);
+ return -EINVAL;
+ }
+ base = var->yoffset * var->xres_virtual + var->xoffset;
+
+ /* calculate base bpp dep. */
+ switch(var->bits_per_pixel) {
+ case 16:
+ base >>= 1;
+ break;
+ case 32:
+ break;
+ case 8:
+ default:
+ base >>= 2;
+ break;
+ }
+
+ outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
+
+ outXGIIDXREG(XGICR, 0x0D, base & 0xFF);
+ outXGIIDXREG(XGICR, 0x0C, (base >> 8) & 0xFF);
+ outXGIIDXREG(XGISR, 0x0D, (base >> 16) & 0xFF);
+ outXGIIDXREG(XGISR, 0x37, (base >> 24) & 0x03);
+ setXGIIDXREG(XGISR, 0x37, 0xDF, (base >> 21) & 0x04);
+
+ if(xgi_video_info.disp_state & DISPTYPE_DISP2) {
+ orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
+ outXGIIDXREG(XGIPART1, 0x06, (base & 0xFF));
+ outXGIIDXREG(XGIPART1, 0x05, ((base >> 8) & 0xFF));
+ outXGIIDXREG(XGIPART1, 0x04, ((base >> 16) & 0xFF));
+ setXGIIDXREG(XGIPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
+ }
+// printk("End of pan_var");
+ return 0;
+}
+#endif
+
+
+void XGI_dispinfo(struct ap_data *rec)
+{
+ rec->minfo.bpp = xgi_video_info.video_bpp;
+ rec->minfo.xres = xgi_video_info.video_width;
+ rec->minfo.yres = xgi_video_info.video_height;
+ rec->minfo.v_xres = xgi_video_info.video_vwidth;
+ rec->minfo.v_yres = xgi_video_info.video_vheight;
+ rec->minfo.org_x = xgi_video_info.org_x;
+ rec->minfo.org_y = xgi_video_info.org_y;
+ rec->minfo.vrate = xgi_video_info.refresh_rate;
+ rec->iobase = xgi_video_info.vga_base - 0x30;
+ rec->mem_size = xgi_video_info.video_size;
+ rec->disp_state = xgi_video_info.disp_state;
+ rec->version = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL;
+ rec->hasVB = xgi_video_info.hasVB;
+ rec->TV_type = xgi_video_info.TV_type;
+ rec->TV_plug = xgi_video_info.TV_plug;
+ rec->chip = xgi_video_info.chip;
+}
+
+
+
+
+static int XGIfb_open(struct fb_info *info, int user)
+{
+ return 0;
+}
+
+static int XGIfb_release(struct fb_info *info, int user)
+{
+ return 0;
+}
+
+static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var)
+{
+ int rc = 16;
+
+ switch(var->bits_per_pixel) {
+ case 8:
+ rc = 256;
+ break;
+ case 16:
+ rc = 16;
+ break;
+ case 32:
+ rc = 16;
+ break;
+ }
+ return rc;
+}
+
+static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
+ unsigned transp, struct fb_info *info)
+{
+ if (regno >= XGIfb_get_cmap_len(&info->var))
+ return 1;
+
+ switch (info->var.bits_per_pixel) {
+ case 8:
+ outXGIREG(XGIDACA, regno);
+ outXGIREG(XGIDACD, (red >> 10));
+ outXGIREG(XGIDACD, (green >> 10));
+ outXGIREG(XGIDACD, (blue >> 10));
+ if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
+ outXGIREG(XGIDAC2A, regno);
+ outXGIREG(XGIDAC2D, (red >> 8));
+ outXGIREG(XGIDAC2D, (green >> 8));
+ outXGIREG(XGIDAC2D, (blue >> 8));
+ }
+ break;
+ case 16:
+ ((u32 *)(info->pseudo_palette))[regno] =
+ ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
+ break;
+ case 32:
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+ ((u32 *) (info->pseudo_palette))[regno] =
+ (red << 16) | (green << 8) | (blue);
+ break;
+ }
+ return 0;
+}
+
+static int XGIfb_set_par(struct fb_info *info)
+{
+ int err;
+
+// printk("XGIfb: inside set_par\n");
+ if((err = XGIfb_do_set_var(&info->var, 1, info)))
+ return err;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
+ XGIfb_get_fix(&info->fix, info->currcon, info);
+#else
+ XGIfb_get_fix(&info->fix, -1, info);
+#endif
+// printk("XGIfb:end of set_par\n");
+ return 0;
+}
+
+static int XGIfb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ unsigned int htotal =
+ var->left_margin + var->xres + var->right_margin +
+ var->hsync_len;
+ unsigned int vtotal = 0;
+ unsigned int drate = 0, hrate = 0;
+ int found_mode = 0;
+ int refresh_rate, search_idx;
+
+ DEBUGPRN("Inside check_var");
+
+ if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
+ vtotal = var->upper_margin + var->yres + var->lower_margin +
+ var->vsync_len;
+ vtotal <<= 1;
+ } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+ vtotal = var->upper_margin + var->yres + var->lower_margin +
+ var->vsync_len;
+ vtotal <<= 2;
+ } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+ vtotal = var->upper_margin + (var->yres/2) + var->lower_margin +
+ var->vsync_len;
+ } else vtotal = var->upper_margin + var->yres + var->lower_margin +
+ var->vsync_len;
+
+ if(!(htotal) || !(vtotal)) {
+ XGIFAIL("XGIfb: no valid timing data");
+ }
+
+
+ if(var->pixclock && htotal && vtotal) {
+ drate = 1000000000 / var->pixclock;
+ hrate = (drate * 1000) / htotal;
+ xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
+ printk(KERN_DEBUG \
+ "%s: pixclock = %d ,htotal=%d, vtotal=%d\n" \
+ "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
+ __func__,var->pixclock, htotal, vtotal,
+ __func__, drate, hrate, xgi_video_info.refresh_rate);
+ } else {
+ xgi_video_info.refresh_rate = 60;
+ }
+
+/*
+ if((var->pixclock) && (htotal)) {
+ drate = 1E12 / var->pixclock;
+ hrate = drate / htotal;
+ refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
+ } else refresh_rate = 60;
+*/
+ /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
+ if((var->xres == 1024) && (var->yres == 600)) refresh_rate = 60;
+
+ search_idx = 0;
+ while((XGIbios_mode[search_idx].mode_no != 0) &&
+ (XGIbios_mode[search_idx].xres <= var->xres) ) {
+ if((XGIbios_mode[search_idx].xres == var->xres) &&
+ (XGIbios_mode[search_idx].yres == var->yres) &&
+ (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) {
+ if(XGIfb_validate_mode(search_idx) > 0) {
+ found_mode = 1;
+ break;
+ }
+ }
+ search_idx++;
+ }
+
+ if(!found_mode) {
+
+ printk(KERN_ERR "XGIfb: %dx%dx%d is no valid mode\n",
+ var->xres, var->yres, var->bits_per_pixel);
+
+ search_idx = 0;
+ while(XGIbios_mode[search_idx].mode_no != 0) {
+
+ if( (var->xres <= XGIbios_mode[search_idx].xres) &&
+ (var->yres <= XGIbios_mode[search_idx].yres) &&
+ (var->bits_per_pixel == XGIbios_mode[search_idx].bpp) ) {
+ if(XGIfb_validate_mode(search_idx) > 0) {
+ found_mode = 1;
+ break;
+ }
+ }
+ search_idx++;
+ }
+ if(found_mode) {
+ var->xres = XGIbios_mode[search_idx].xres;
+ var->yres = XGIbios_mode[search_idx].yres;
+ printk(KERN_DEBUG "XGIfb: Adapted to mode %dx%dx%d\n",
+ var->xres, var->yres, var->bits_per_pixel);
+
+ } else {
+ printk(KERN_ERR "XGIfb: Failed to find similar mode to %dx%dx%d\n",
+ var->xres, var->yres, var->bits_per_pixel);
+ return -EINVAL;
+ }
+ }
+
+ /* TW: TODO: Check the refresh rate */
+
+ /* Adapt RGB settings */
+ XGIfb_bpp_to_var(var);
+
+ /* Sanity check for offsets */
+ if (var->xoffset < 0)
+ var->xoffset = 0;
+ if (var->yoffset < 0)
+ var->yoffset = 0;
+
+
+ if(!XGIfb_ypan) {
+ if(var->xres != var->xres_virtual)
+ var->xres_virtual = var->xres;
+ if(var->yres != var->yres_virtual)
+ var->yres_virtual = var->yres;
+ }/* else {
+ // TW: Now patch yres_virtual if we use panning
+ // May I do this?
+ var->yres_virtual = xgi_video_info.heapstart / (var->xres * (var->bits_per_pixel >> 3));
+ if(var->yres_virtual <= var->yres) {
+ // TW: Paranoia check
+ var->yres_virtual = var->yres;
+ }
+ }*/
+
+ /* Truncate offsets to maximum if too high */
+ if (var->xoffset > var->xres_virtual - var->xres)
+ var->xoffset = var->xres_virtual - var->xres - 1;
+
+ if (var->yoffset > var->yres_virtual - var->yres)
+ var->yoffset = var->yres_virtual - var->yres - 1;
+
+ /* Set everything else to 0 */
+ var->red.msb_right =
+ var->green.msb_right =
+ var->blue.msb_right =
+ var->transp.offset = var->transp.length = var->transp.msb_right = 0;
+
+ DEBUGPRN("end of check_var");
+ return 0;
+}
+
+#ifdef XGIFB_PAN
+static int XGIfb_pan_display( struct fb_var_screeninfo *var,
+ struct fb_info* info)
+{
+ int err;
+
+// printk("\nInside pan_display:");
+
+ if (var->xoffset > (var->xres_virtual - var->xres))
+ return -EINVAL;
+ if (var->yoffset > (var->yres_virtual - var->yres))
+ return -EINVAL;
+
+ if (var->vmode & FB_VMODE_YWRAP) {
+ if (var->yoffset < 0
+ || var->yoffset >= info->var.yres_virtual
+ || var->xoffset) return -EINVAL;
+ } else {
+ if (var->xoffset + info->var.xres > info->var.xres_virtual ||
+ var->yoffset + info->var.yres > info->var.yres_virtual)
+ return -EINVAL;
+ }
+
+ if((err = XGIfb_pan_var(var)) < 0) return err;
+
+ info->var.xoffset = var->xoffset;
+ info->var.yoffset = var->yoffset;
+ if (var->vmode & FB_VMODE_YWRAP)
+ info->var.vmode |= FB_VMODE_YWRAP;
+ else
+ info->var.vmode &= ~FB_VMODE_YWRAP;
+
+// printk(" End of pan_display");
+ return 0;
+}
+#endif
+
+#if 0
+static int XGIfb_mmap(struct fb_info *info, struct file *file,
+ struct vm_area_struct *vma)
+{
+ unsigned long start;
+ unsigned long off;
+ u32 len, mmio_off;
+
+ DEBUGPRN("inside mmap");
+ if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) return -EINVAL;
+
+ off = vma->vm_pgoff << PAGE_SHIFT;
+
+ start = (unsigned long) xgi_video_info.video_base;
+ len = PAGE_ALIGN((start & ~PAGE_MASK) + xgi_video_info.video_size);
+ start &= PAGE_MASK;
+#if 0
+ if (off >= len) {
+ off -= len;
+#endif
+ /* By Jake Page: Treat mmap request with offset beyond heapstart
+ * as request for mapping the mmio area
+ */
+ #if 1
+ mmio_off = PAGE_ALIGN((start & ~PAGE_MASK) + xgi_video_info.heapstart);
+ if(off >= mmio_off) {
+ off -= mmio_off;
+ if(info->var.accel_flags) return -EINVAL;
+
+ start = (unsigned long) xgi_video_info.mmio_base;
+ len = PAGE_ALIGN((start & ~PAGE_MASK) + XGIfb_mmio_size);
+ }
+ start &= PAGE_MASK;
+ #endif
+ if((vma->vm_end - vma->vm_start + off) > len) return -EINVAL;
+
+ off += start;
+ vma->vm_pgoff = off >> PAGE_SHIFT;
+ vma->vm_flags |= VM_IO; /* by Jake Page; is that really needed? */
+
+#if defined(__i386__) || defined(__x86_64__)
+ if (boot_cpu_data.x86 > 3)
+ pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
+#endif
+ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, vma->vm_end - vma->vm_start,
+ vma->vm_page_prot))
+ return -EAGAIN;
+
+ DEBUGPRN("end of mmap");
+ return 0;
+}
+#endif
+static int XGIfb_blank(int blank, struct fb_info *info)
+{
+ u8 reg;
+
+ inXGIIDXREG(XGICR, 0x17, reg);
+
+ if(blank > 0)
+ reg &= 0x7f;
+ else
+ reg |= 0x80;
+
+ outXGIIDXREG(XGICR, 0x17, reg);
+ outXGIIDXREG(XGISR, 0x00, 0x01); /* Synchronous Reset */
+ outXGIIDXREG(XGISR, 0x00, 0x03); /* End Reset */
+ return(0);
+}
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
+static int XGIfb_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
+#else
+static int XGIfb_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg,
+ struct fb_info *info)
+#endif
+
+{
+ DEBUGPRN("inside ioctl");
+ switch (cmd) {
+ case FBIO_ALLOC:
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+ XGI_malloc((struct XGI_memreq *) arg);
+ break;
+ case FBIO_FREE:
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+ XGI_free(*(unsigned long *) arg);
+ break;
+ case FBIOGET_HWCINFO:
+ {
+ unsigned long *hwc_offset = (unsigned long *) arg;
+
+ if (XGIfb_caps & HW_CURSOR_CAP)
+ *hwc_offset = XGIfb_hwcursor_vbase -
+ (unsigned long) xgi_video_info.video_vbase;
+ else
+ *hwc_offset = 0;
+
+ break;
+ }
+ case FBIOPUT_MODEINFO:
+ {
+ struct mode_info *x = (struct mode_info *)arg;
+
+ xgi_video_info.video_bpp = x->bpp;
+ xgi_video_info.video_width = x->xres;
+ xgi_video_info.video_height = x->yres;
+ xgi_video_info.video_vwidth = x->v_xres;
+ xgi_video_info.video_vheight = x->v_yres;
+ xgi_video_info.org_x = x->org_x;
+ xgi_video_info.org_y = x->org_y;
+ xgi_video_info.refresh_rate = x->vrate;
+ xgi_video_info.video_linelength = xgi_video_info.video_vwidth * (xgi_video_info.video_bpp >> 3);
+ switch(xgi_video_info.video_bpp) {
+ case 8:
+ xgi_video_info.DstColor = 0x0000;
+ xgi_video_info.XGI310_AccelDepth = 0x00000000;
+ xgi_video_info.video_cmap_len = 256;
+ break;
+ case 16:
+ xgi_video_info.DstColor = 0x8000;
+ xgi_video_info.XGI310_AccelDepth = 0x00010000;
+ xgi_video_info.video_cmap_len = 16;
+ break;
+ case 32:
+ xgi_video_info.DstColor = 0xC000;
+ xgi_video_info.XGI310_AccelDepth = 0x00020000;
+ xgi_video_info.video_cmap_len = 16;
+ break;
+ default:
+ xgi_video_info.video_cmap_len = 16;
+ printk(KERN_ERR "XGIfb: Unsupported accel depth %d", xgi_video_info.video_bpp);
+ xgi_video_info.accel = 0;
+ break;
+ }
+
+ break;
+ }
+ case FBIOGET_DISPINFO:
+ XGI_dispinfo((struct ap_data *)arg);
+ break;
+ case XGIFB_GET_INFO: /* TW: New for communication with X driver */
+ {
+ XGIfb_info *x = (XGIfb_info *)arg;
+
+ //x->XGIfb_id = XGIFB_ID;
+ x->XGIfb_version = VER_MAJOR;
+ x->XGIfb_revision = VER_MINOR;
+ x->XGIfb_patchlevel = VER_LEVEL;
+ x->chip_id = xgi_video_info.chip_id;
+ x->memory = xgi_video_info.video_size / 1024;
+ x->heapstart = xgi_video_info.heapstart / 1024;
+ x->fbvidmode = XGIfb_mode_no;
+ x->XGIfb_caps = XGIfb_caps;
+ x->XGIfb_tqlen = 512; /* yet unused */
+ x->XGIfb_pcibus = xgi_video_info.pcibus;
+ x->XGIfb_pcislot = xgi_video_info.pcislot;
+ x->XGIfb_pcifunc = xgi_video_info.pcifunc;
+ x->XGIfb_lcdpdc = XGIfb_detectedpdc;
+ x->XGIfb_lcda = XGIfb_detectedlcda;
+ break;
+ }
+ case XGIFB_GET_VBRSTATUS:
+ {
+ unsigned long *vbrstatus = (unsigned long *) arg;
+ if(XGIfb_CheckVBRetrace()) *vbrstatus = 1;
+ else *vbrstatus = 0;
+ }
+ default:
+ return -EINVAL;
+ }
+ DEBUGPRN("end of ioctl");
+ return 0;
+
+}
+
+
+
+/* ----------- FBDev related routines for all series ---------- */
+
+static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info)
+{
+ DEBUGPRN("inside get_fix");
+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+
+ strcpy(fix->id, myid);
+
+ fix->smem_start = xgi_video_info.video_base;
+
+ fix->smem_len = xgi_video_info.video_size;
+
+
+/* if((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
+ if (xgi_video_info.video_size > 0x1000000) {
+ fix->smem_len = 0xD00000;
+ } else if (xgi_video_info.video_size > 0x800000)
+ fix->smem_len = 0x800000;
+ else
+ fix->smem_len = 0x400000;
+ } else
+ fix->smem_len = XGIfb_mem * 1024;
+*/
+ fix->type = video_type;
+ fix->type_aux = 0;
+ if(xgi_video_info.video_bpp == 8)
+ fix->visual = FB_VISUAL_PSEUDOCOLOR;
+ else
+ fix->visual = FB_VISUAL_DIRECTCOLOR;
+ fix->xpanstep = 0;
+#ifdef XGIFB_PAN
+ if(XGIfb_ypan) fix->ypanstep = 1;
+#endif
+ fix->ywrapstep = 0;
+ fix->line_length = xgi_video_info.video_linelength;
+ fix->mmio_start = xgi_video_info.mmio_base;
+ fix->mmio_len = XGIfb_mmio_size;
+ if(xgi_video_info.chip >= XG40)
+ fix->accel = FB_ACCEL_XGI_XABRE;
+ else
+ fix->accel = FB_ACCEL_XGI_GLAMOUR_2;
+
+
+ DEBUGPRN("end of get_fix");
+ return 0;
+}
+
+
+static struct fb_ops XGIfb_ops = {
+ .owner = THIS_MODULE,
+ .fb_open = XGIfb_open,
+ .fb_release = XGIfb_release,
+ .fb_check_var = XGIfb_check_var,
+ .fb_set_par = XGIfb_set_par,
+ .fb_setcolreg = XGIfb_setcolreg,
+#ifdef XGIFB_PAN
+ .fb_pan_display = XGIfb_pan_display,
+#endif
+ .fb_blank = XGIfb_blank,
+ .fb_fillrect = fbcon_XGI_fillrect,
+ .fb_copyarea = fbcon_XGI_copyarea,
+ .fb_imageblit = cfb_imageblit,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
+ .fb_cursor = soft_cursor,
+#endif
+ .fb_sync = fbcon_XGI_sync,
+ .fb_ioctl = XGIfb_ioctl,
+// .fb_mmap = XGIfb_mmap,
+};
+
+/* ---------------- Chip generation dependent routines ---------------- */
+
+
+/* for XGI 315/550/650/740/330 */
+
+static int XGIfb_get_dram_size(void)
+{
+
+ u8 ChannelNum,tmp;
+ u8 reg = 0;
+
+ /* xorg driver sets 32MB * 1 channel */
+ if (xgi_video_info.chip == XG27)
+ outXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, 0x51);
+
+ inXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, reg);
+ switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) {
+ case XGI_DRAM_SIZE_1MB:
+ xgi_video_info.video_size = 0x100000;
+ break;
+ case XGI_DRAM_SIZE_2MB:
+ xgi_video_info.video_size = 0x200000;
+ break;
+ case XGI_DRAM_SIZE_4MB:
+ xgi_video_info.video_size = 0x400000;
+ break;
+ case XGI_DRAM_SIZE_8MB:
+ xgi_video_info.video_size = 0x800000;
+ break;
+ case XGI_DRAM_SIZE_16MB:
+ xgi_video_info.video_size = 0x1000000;
+ break;
+ case XGI_DRAM_SIZE_32MB:
+ xgi_video_info.video_size = 0x2000000;
+ break;
+ case XGI_DRAM_SIZE_64MB:
+ xgi_video_info.video_size = 0x4000000;
+ break;
+ case XGI_DRAM_SIZE_128MB:
+ xgi_video_info.video_size = 0x8000000;
+ break;
+ case XGI_DRAM_SIZE_256MB:
+ xgi_video_info.video_size = 0x10000000;
+ break;
+ default:
+ return -1;
+ }
+
+ tmp = (reg & 0x0c) >> 2;
+ switch(xgi_video_info.chip)
+ {
+ case XG20:
+ case XG21:
+ case XG27:
+ ChannelNum = 1;
+ break;
+
+ case XG42:
+ if(reg & 0x04)
+ ChannelNum = 2;
+ else
+ ChannelNum = 1;
+ break;
+
+ case XG45:
+ if(tmp == 1)
+ ChannelNum = 2;
+ else
+ if(tmp == 2)
+ ChannelNum = 3;
+ else
+ if(tmp == 3)
+ ChannelNum = 4;
+ else
+ ChannelNum = 1;
+ break;
+
+ case XG40:
+ default:
+ if(tmp == 2)
+ ChannelNum = 2;
+ else
+ if(tmp == 3)
+ ChannelNum = 3;
+ else
+ ChannelNum = 1;
+ break;
+ }
+
+
+ xgi_video_info.video_size = xgi_video_info.video_size * ChannelNum;
+ //PLiad fixed for benchmarking and fb set
+ //xgi_video_info.video_size = 0x200000;//1024x768x16
+ //xgi_video_info.video_size = 0x1000000;//benchmark
+
+ printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n",reg,xgi_video_info.video_size ,ChannelNum );
+ return 0;
+
+}
+
+static void XGIfb_detect_VB(void)
+{
+ u8 cr32, temp=0;
+
+ xgi_video_info.TV_plug = xgi_video_info.TV_type = 0;
+
+ switch(xgi_video_info.hasVB) {
+ case HASVB_LVDS_CHRONTEL:
+ case HASVB_CHRONTEL:
+ break;
+ case HASVB_301:
+ case HASVB_302:
+// XGI_Sense30x(); //Yi-Lin TV Sense?
+ break;
+ }
+
+ inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR32, cr32);
+
+ if ((cr32 & XGI_CRT1) && !XGIfb_crt1off)
+ XGIfb_crt1off = 0;
+ else {
+ if (cr32 & 0x5F)
+ XGIfb_crt1off = 1;
+ else
+ XGIfb_crt1off = 0;
+ }
+
+ if (XGIfb_crt2type != -1)
+ /* TW: Override with option */
+ xgi_video_info.disp_state = XGIfb_crt2type;
+ else if (cr32 & XGI_VB_TV)
+ xgi_video_info.disp_state = DISPTYPE_TV;
+ else if (cr32 & XGI_VB_LCD)
+ xgi_video_info.disp_state = DISPTYPE_LCD;
+ else if (cr32 & XGI_VB_CRT2)
+ xgi_video_info.disp_state = DISPTYPE_CRT2;
+ else
+ xgi_video_info.disp_state = 0;
+
+ if(XGIfb_tvplug != -1)
+ /* PR/TW: Override with option */
+ xgi_video_info.TV_plug = XGIfb_tvplug;
+ else if (cr32 & XGI_VB_HIVISION) {
+ xgi_video_info.TV_type = TVMODE_HIVISION;
+ xgi_video_info.TV_plug = TVPLUG_SVIDEO;
+ }
+ else if (cr32 & XGI_VB_SVIDEO)
+ xgi_video_info.TV_plug = TVPLUG_SVIDEO;
+ else if (cr32 & XGI_VB_COMPOSITE)
+ xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
+ else if (cr32 & XGI_VB_SCART)
+ xgi_video_info.TV_plug = TVPLUG_SCART;
+
+ if(xgi_video_info.TV_type == 0) {
+ /* TW: PAL/NTSC changed for 650 */
+ if((xgi_video_info.chip <= XGI_315PRO) || (xgi_video_info.chip >= XGI_330)) {
+
+ inXGIIDXREG(XGICR, 0x38, temp);
+ if(temp & 0x10)
+ xgi_video_info.TV_type = TVMODE_PAL;
+ else
+ xgi_video_info.TV_type = TVMODE_NTSC;
+
+ } else {
+
+ inXGIIDXREG(XGICR, 0x79, temp);
+ if(temp & 0x20)
+ xgi_video_info.TV_type = TVMODE_PAL;
+ else
+ xgi_video_info.TV_type = TVMODE_NTSC;
+ }
+ }
+
+ /* TW: Copy forceCRT1 option to CRT1off if option is given */
+ if (XGIfb_forcecrt1 != -1) {
+ if (XGIfb_forcecrt1) XGIfb_crt1off = 0;
+ else XGIfb_crt1off = 1;
+ }
+}
+
+static void XGIfb_get_VB_type(void)
+{
+ u8 reg;
+
+ if (!XGIfb_has_VB()) {
+ inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR37, reg);
+ switch ((reg & XGI_EXTERNAL_CHIP_MASK) >> 1) {
+ case XGI310_EXTERNAL_CHIP_LVDS:
+ xgi_video_info.hasVB = HASVB_LVDS;
+ break;
+ case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL:
+ xgi_video_info.hasVB = HASVB_LVDS_CHRONTEL;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+
+static int XGIfb_has_VB(void)
+{
+ u8 vb_chipid;
+
+ inXGIIDXREG(XGIPART4, 0x00, vb_chipid);
+ switch (vb_chipid) {
+ case 0x01:
+ xgi_video_info.hasVB = HASVB_301;
+ break;
+ case 0x02:
+ xgi_video_info.hasVB = HASVB_302;
+ break;
+ default:
+ xgi_video_info.hasVB = HASVB_NONE;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+
+/* ------------------ Sensing routines ------------------ */
+
+/* TW: Determine and detect attached devices on XGI30x */
+int
+XGIDoSense(int tempbl, int tempbh, int tempcl, int tempch)
+{
+ int temp,i;
+
+ outXGIIDXREG(XGIPART4,0x11,tempbl);
+ temp = tempbh | tempcl;
+ setXGIIDXREG(XGIPART4,0x10,0xe0,temp);
+ for(i=0; i<10; i++) XGI_LongWait(&XGI_Pr);
+ tempch &= 0x7f;
+ inXGIIDXREG(XGIPART4,0x03,temp);
+ temp ^= 0x0e;
+ temp &= tempch;
+ return(temp);
+}
+
+void
+XGI_Sense30x(void)
+{
+ u8 backupP4_0d;
+ u8 testsvhs_tempbl, testsvhs_tempbh;
+ u8 testsvhs_tempcl, testsvhs_tempch;
+ u8 testcvbs_tempbl, testcvbs_tempbh;
+ u8 testcvbs_tempcl, testcvbs_tempch;
+ u8 testvga2_tempbl, testvga2_tempbh;
+ u8 testvga2_tempcl, testvga2_tempch;
+ int myflag, result;
+
+ inXGIIDXREG(XGIPART4,0x0d,backupP4_0d);
+ outXGIIDXREG(XGIPART4,0x0d,(backupP4_0d | 0x04));
+
+
+
+ testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1;
+ testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9;
+ testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3;
+ if((XGIhw_ext.ujVBChipID != VB_CHIP_301) &&
+ (XGIhw_ext.ujVBChipID != VB_CHIP_302)) {
+ testvga2_tempbh = 0x01; testvga2_tempbl = 0x90;
+ testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b;
+ testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74;
+ if(XGIhw_ext.ujVBChipID == VB_CHIP_301LV ||
+ XGIhw_ext.ujVBChipID == VB_CHIP_302LV) {
+ testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
+ testsvhs_tempbh = 0x02; testsvhs_tempbl = 0x00;
+ testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x00;
+ }
+ }
+ if(XGIhw_ext.ujVBChipID != VB_CHIP_301LV &&
+ XGIhw_ext.ujVBChipID != VB_CHIP_302LV) {
+ inXGIIDXREG(XGIPART4,0x01,myflag);
+ if(myflag & 0x04) {
+ testvga2_tempbh = 0x00; testvga2_tempbl = 0xfd;
+ testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xdd;
+ testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xee;
+ }
+ }
+ if((XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
+ (XGIhw_ext.ujVBChipID == VB_CHIP_302LV) ) {
+ testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
+ testvga2_tempch = 0x00; testvga2_tempcl = 0x00;
+ testsvhs_tempch = 0x04; testsvhs_tempcl = 0x08;
+ testcvbs_tempch = 0x08; testcvbs_tempcl = 0x08;
+ } else {
+ testvga2_tempch = 0x0e; testvga2_tempcl = 0x08;
+ testsvhs_tempch = 0x06; testsvhs_tempcl = 0x04;
+ testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04;
+ }
+
+
+ if(testvga2_tempch || testvga2_tempcl || testvga2_tempbh || testvga2_tempbl) {
+ result = XGIDoSense(testvga2_tempbl, testvga2_tempbh,
+ testvga2_tempcl, testvga2_tempch);
+ if(result) {
+ printk(KERN_INFO "XGIfb: Detected secondary VGA connection\n");
+ orXGIIDXREG(XGICR, 0x32, 0x10);
+ }
+ }
+
+ result = XGIDoSense(testsvhs_tempbl, testsvhs_tempbh,
+ testsvhs_tempcl, testsvhs_tempch);
+ if(result) {
+ printk(KERN_INFO "XGIfb: Detected TV connected to SVHS output\n");
+ /* TW: So we can be sure that there IS a SVHS output */
+ xgi_video_info.TV_plug = TVPLUG_SVIDEO;
+ orXGIIDXREG(XGICR, 0x32, 0x02);
+ }
+
+ if(!result) {
+ result = XGIDoSense(testcvbs_tempbl, testcvbs_tempbh,
+ testcvbs_tempcl, testcvbs_tempch);
+ if(result) {
+ printk(KERN_INFO "XGIfb: Detected TV connected to CVBS output\n");
+ /* TW: So we can be sure that there IS a CVBS output */
+ xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
+ orXGIIDXREG(XGICR, 0x32, 0x01);
+ }
+ }
+ XGIDoSense(0, 0, 0, 0);
+
+ outXGIIDXREG(XGIPART4,0x0d,backupP4_0d);
+}
+
+
+
+/* ------------------------ Heap routines -------------------------- */
+
+static int XGIfb_heap_init(void)
+{
+ XGI_OH *poh;
+ u8 temp=0;
+
+ int agp_enabled = 1;
+ u32 agp_size;
+ unsigned long *cmdq_baseport = 0;
+ unsigned long *read_port = 0;
+ unsigned long *write_port = 0;
+ XGI_CMDTYPE cmd_type;
+#ifndef AGPOFF
+ struct agp_kern_info *agp_info;
+ struct agp_memory *agp;
+ u32 agp_phys;
+#endif
+
+/* TW: The heap start is either set manually using the "mem" parameter, or
+ * defaults as follows:
+ * -) If more than 16MB videoRAM available, let our heap start at 12MB.
+ * -) If more than 8MB videoRAM available, let our heap start at 8MB.
+ * -) If 4MB or less is available, let it start at 4MB.
+ * This is for avoiding a clash with X driver which uses the beginning
+ * of the videoRAM. To limit size of X framebuffer, use Option MaxXFBMem
+ * in XF86Config-4.
+ * The heap start can also be specified by parameter "mem" when starting the XGIfb
+ * driver. XGIfb mem=1024 lets heap starts at 1MB, etc.
+ */
+ if ((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
+ if (xgi_video_info.video_size > 0x1000000) {
+ xgi_video_info.heapstart = 0xD00000;
+ } else if (xgi_video_info.video_size > 0x800000) {
+ xgi_video_info.heapstart = 0x800000;
+ } else {
+ xgi_video_info.heapstart = 0x400000;
+ }
+ } else {
+ xgi_video_info.heapstart = XGIfb_mem * 1024;
+ }
+ XGIfb_heap_start =
+ (unsigned long) (xgi_video_info.video_vbase + xgi_video_info.heapstart);
+ printk(KERN_INFO "XGIfb: Memory heap starting at %dK\n",
+ (int)(xgi_video_info.heapstart / 1024));
+
+ XGIfb_heap_end = (unsigned long) xgi_video_info.video_vbase + xgi_video_info.video_size;
+ XGIfb_heap_size = XGIfb_heap_end - XGIfb_heap_start;
+
+
+
+ /* TW: Now initialize the 310 series' command queue mode.
+ * On 310/325, there are three queue modes available which
+ * are chosen by setting bits 7:5 in SR26:
+ * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep
+ * track of the queue, the FIFO, command parsing and so
+ * on. This is the one comparable to the 300 series.
+ * 2. VRAM queue mode (bit 6, 0x40). In this case, one will
+ * have to do queue management himself. Register 0x85c4 will
+ * hold the location of the next free queue slot, 0x85c8
+ * is the "queue read pointer" whose way of working is
+ * unknown to me. Anyway, this mode would require a
+ * translation of the MMIO commands to some kind of
+ * accelerator assembly and writing these commands
+ * to the memory location pointed to by 0x85c4.
+ * We will not use this, as nobody knows how this
+ * "assembly" works, and as it would require a complete
+ * re-write of the accelerator code.
+ * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the
+ * queue in AGP memory space.
+ *
+ * SR26 bit 4 is called "Bypass H/W queue".
+ * SR26 bit 1 is called "Enable Command Queue Auto Correction"
+ * SR26 bit 0 resets the queue
+ * Size of queue memory is encoded in bits 3:2 like this:
+ * 00 (0x00) 512K
+ * 01 (0x04) 1M
+ * 10 (0x08) 2M
+ * 11 (0x0C) 4M
+ * The queue location is to be written to 0x85C0.
+ *
+ */
+ cmdq_baseport = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_PHYBASE);
+ write_port = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_WRITEPORT);
+ read_port = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_READPORT);
+
+ DPRINTK("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport, read_port, write_port);
+
+ agp_size = COMMAND_QUEUE_AREA_SIZE;
+
+#ifndef AGPOFF
+ if (XGIfb_queuemode == AGP_CMD_QUEUE) {
+ agp_info = vmalloc(sizeof(*agp_info));
+ memset((void*)agp_info, 0x00, sizeof(*agp_info));
+ agp_copy_info(agp_info);
+
+ agp_backend_acquire();
+
+ agp = agp_allocate_memory(COMMAND_QUEUE_AREA_SIZE/PAGE_SIZE,
+ AGP_NORMAL_MEMORY);
+ if (agp == NULL) {
+ DPRINTK("XGIfb: Allocating AGP buffer failed.\n");
+ agp_enabled = 0;
+ } else {
+ if (agp_bind_memory(agp, agp->pg_start) != 0) {
+ DPRINTK("XGIfb: AGP: Failed to bind memory\n");
+ /* TODO: Free AGP memory here */
+ agp_enabled = 0;
+ } else {
+ agp_enable(0);
+ }
+ }
+ }
+#else
+ agp_enabled = 0;
+#endif
+
+ /* TW: Now select the queue mode */
+
+ if ((agp_enabled) && (XGIfb_queuemode == AGP_CMD_QUEUE)) {
+ cmd_type = AGP_CMD_QUEUE;
+ printk(KERN_INFO "XGIfb: Using AGP queue mode\n");
+/* } else if (XGIfb_heap_size >= COMMAND_QUEUE_AREA_SIZE) */
+ } else if (XGIfb_queuemode == VM_CMD_QUEUE) {
+ cmd_type = VM_CMD_QUEUE;
+ printk(KERN_INFO "XGIfb: Using VRAM queue mode\n");
+ } else {
+ printk(KERN_INFO "XGIfb: Using MMIO queue mode\n");
+ cmd_type = MMIO_CMD;
+ }
+
+ switch (agp_size) {
+ case 0x80000:
+ temp = XGI_CMD_QUEUE_SIZE_512k;
+ break;
+ case 0x100000:
+ temp = XGI_CMD_QUEUE_SIZE_1M;
+ break;
+ case 0x200000:
+ temp = XGI_CMD_QUEUE_SIZE_2M;
+ break;
+ case 0x400000:
+ temp = XGI_CMD_QUEUE_SIZE_4M;
+ break;
+ }
+
+ switch (cmd_type) {
+ case AGP_CMD_QUEUE:
+#ifndef AGPOFF
+ DPRINTK("XGIfb: AGP buffer base = 0x%lx, offset = 0x%x, size = %dK\n",
+ agp_info->aper_base, agp->physical, agp_size/1024);
+
+ agp_phys = agp_info->aper_base + agp->physical;
+
+ outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, 0);
+ outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, XGI_AGP_2X);
+
+ outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
+
+ outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
+
+ *write_port = *read_port;
+
+ temp |= XGI_AGP_CMDQUEUE_ENABLE;
+ outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
+
+ *cmdq_baseport = agp_phys;
+
+ XGIfb_caps |= AGP_CMD_QUEUE_CAP;
+#endif
+ break;
+
+ case VM_CMD_QUEUE:
+ XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
+ XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
+
+ outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
+
+ outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
+
+ *write_port = *read_port;
+
+ temp |= XGI_VRAM_CMDQUEUE_ENABLE;
+ outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
+
+ *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE;
+
+ XGIfb_caps |= VM_CMD_QUEUE_CAP;
+
+ DPRINTK("XGIfb: VM Cmd Queue offset = 0x%lx, size is %dK\n",
+ *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
+ break;
+
+ default: /* MMIO */
+
+// printk("%s:%d - I'm here\n", __FUNCTION__, __LINE__);
+ /* TW: This previously only wrote XGI_MMIO_CMD_ENABLE
+ * to IND_XGI_CMDQUEUE_SET. I doubt that this is
+ * enough. Reserve memory in any way.
+ */
+// FIXME XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
+// FIXME XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
+// FIXME
+// FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
+// FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
+// FIXME
+// FIXME *write_port = *read_port;
+// FIXME
+// FIXME /* TW: Set Auto_Correction bit */
+// FIXME temp |= (XGI_MMIO_CMD_ENABLE | XGI_CMD_AUTO_CORR);
+// FIXME // FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
+// FIXME
+// FIXME *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE;
+// FIXME
+// FIXME XGIfb_caps |= MMIO_CMD_QUEUE_CAP;
+// FIXME
+// FIXME DPRINTK("XGIfb: MMIO Cmd Queue offset = 0x%lx, size is %dK\n",
+// FIXME *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
+ break;
+ }
+
+
+
+
+ /* TW: Now reserve memory for the HWCursor. It is always located at the very
+ top of the videoRAM, right below the TB memory area (if used). */
+ if (XGIfb_heap_size >= XGIfb_hwcursor_size) {
+ XGIfb_heap_end -= XGIfb_hwcursor_size;
+ XGIfb_heap_size -= XGIfb_hwcursor_size;
+ XGIfb_hwcursor_vbase = XGIfb_heap_end;
+
+ XGIfb_caps |= HW_CURSOR_CAP;
+
+ DPRINTK("XGIfb: Hardware Cursor start at 0x%lx, size is %dK\n",
+ XGIfb_heap_end, XGIfb_hwcursor_size/1024);
+ }
+
+ XGIfb_heap.poha_chain = NULL;
+ XGIfb_heap.poh_freelist = NULL;
+
+ poh = XGIfb_poh_new_node();
+
+ if(poh == NULL) return 1;
+
+ poh->poh_next = &XGIfb_heap.oh_free;
+ poh->poh_prev = &XGIfb_heap.oh_free;
+ poh->size = XGIfb_heap_end - XGIfb_heap_start + 1;
+ poh->offset = XGIfb_heap_start - (unsigned long) xgi_video_info.video_vbase;
+
+ DPRINTK("XGIfb: Heap start:0x%p, end:0x%p, len=%dk\n",
+ (char *) XGIfb_heap_start, (char *) XGIfb_heap_end,
+ (unsigned int) poh->size / 1024);
+
+ DPRINTK("XGIfb: First Node offset:0x%x, size:%dk\n",
+ (unsigned int) poh->offset, (unsigned int) poh->size / 1024);
+
+ XGIfb_heap.oh_free.poh_next = poh;
+ XGIfb_heap.oh_free.poh_prev = poh;
+ XGIfb_heap.oh_free.size = 0;
+ XGIfb_heap.max_freesize = poh->size;
+
+ XGIfb_heap.oh_used.poh_next = &XGIfb_heap.oh_used;
+ XGIfb_heap.oh_used.poh_prev = &XGIfb_heap.oh_used;
+ XGIfb_heap.oh_used.size = SENTINEL;
+
+ return 0;
+}
+
+static XGI_OH *XGIfb_poh_new_node(void)
+{
+ int i;
+ unsigned long cOhs;
+ XGI_OHALLOC *poha;
+ XGI_OH *poh;
+
+ if (XGIfb_heap.poh_freelist == NULL) {
+ poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
+ if(!poha) return NULL;
+
+ poha->poha_next = XGIfb_heap.poha_chain;
+ XGIfb_heap.poha_chain = poha;
+
+ cOhs = (OH_ALLOC_SIZE - sizeof(XGI_OHALLOC)) / sizeof(XGI_OH) + 1;
+
+ poh = &poha->aoh[0];
+ for (i = cOhs - 1; i != 0; i--) {
+ poh->poh_next = poh + 1;
+ poh = poh + 1;
+ }
+
+ poh->poh_next = NULL;
+ XGIfb_heap.poh_freelist = &poha->aoh[0];
+ }
+
+ poh = XGIfb_heap.poh_freelist;
+ XGIfb_heap.poh_freelist = poh->poh_next;
+
+ return (poh);
+}
+
+static XGI_OH *XGIfb_poh_allocate(unsigned long size)
+{
+ XGI_OH *pohThis;
+ XGI_OH *pohRoot;
+ int bAllocated = 0;
+
+ if (size > XGIfb_heap.max_freesize) {
+ DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
+ (unsigned int) size / 1024);
+ return (NULL);
+ }
+
+ pohThis = XGIfb_heap.oh_free.poh_next;
+
+ while (pohThis != &XGIfb_heap.oh_free) {
+ if (size <= pohThis->size) {
+ bAllocated = 1;
+ break;
+ }
+ pohThis = pohThis->poh_next;
+ }
+
+ if (!bAllocated) {
+ DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
+ (unsigned int) size / 1024);
+ return (NULL);
+ }
+
+ if (size == pohThis->size) {
+ pohRoot = pohThis;
+ XGIfb_delete_node(pohThis);
+ } else {
+ pohRoot = XGIfb_poh_new_node();
+
+ if (pohRoot == NULL) {
+ return (NULL);
+ }
+
+ pohRoot->offset = pohThis->offset;
+ pohRoot->size = size;
+
+ pohThis->offset += size;
+ pohThis->size -= size;
+ }
+
+ XGIfb_heap.max_freesize -= size;
+
+ pohThis = &XGIfb_heap.oh_used;
+ XGIfb_insert_node(pohThis, pohRoot);
+
+ return (pohRoot);
+}
+
+static void XGIfb_delete_node(XGI_OH *poh)
+{
+ XGI_OH *poh_prev;
+ XGI_OH *poh_next;
+
+ poh_prev = poh->poh_prev;
+ poh_next = poh->poh_next;
+
+ poh_prev->poh_next = poh_next;
+ poh_next->poh_prev = poh_prev;
+
+}
+
+static void XGIfb_insert_node(XGI_OH *pohList, XGI_OH *poh)
+{
+ XGI_OH *pohTemp;
+
+ pohTemp = pohList->poh_next;
+
+ pohList->poh_next = poh;
+ pohTemp->poh_prev = poh;
+
+ poh->poh_prev = pohList;
+ poh->poh_next = pohTemp;
+}
+
+static XGI_OH *XGIfb_poh_free(unsigned long base)
+{
+ XGI_OH *pohThis;
+ XGI_OH *poh_freed;
+ XGI_OH *poh_prev;
+ XGI_OH *poh_next;
+ unsigned long ulUpper;
+ unsigned long ulLower;
+ int foundNode = 0;
+
+ poh_freed = XGIfb_heap.oh_used.poh_next;
+
+ while(poh_freed != &XGIfb_heap.oh_used) {
+ if(poh_freed->offset == base) {
+ foundNode = 1;
+ break;
+ }
+
+ poh_freed = poh_freed->poh_next;
+ }
+
+ if (!foundNode) return (NULL);
+
+ XGIfb_heap.max_freesize += poh_freed->size;
+
+ poh_prev = poh_next = NULL;
+ ulUpper = poh_freed->offset + poh_freed->size;
+ ulLower = poh_freed->offset;
+
+ pohThis = XGIfb_heap.oh_free.poh_next;
+
+ while (pohThis != &XGIfb_heap.oh_free) {
+ if (pohThis->offset == ulUpper) {
+ poh_next = pohThis;
+ }
+ else if ((pohThis->offset + pohThis->size) ==
+ ulLower) {
+ poh_prev = pohThis;
+ }
+ pohThis = pohThis->poh_next;
+ }
+
+ XGIfb_delete_node(poh_freed);
+
+ if (poh_prev && poh_next) {
+ poh_prev->size += (poh_freed->size + poh_next->size);
+ XGIfb_delete_node(poh_next);
+ XGIfb_free_node(poh_freed);
+ XGIfb_free_node(poh_next);
+ return (poh_prev);
+ }
+
+ if (poh_prev) {
+ poh_prev->size += poh_freed->size;
+ XGIfb_free_node(poh_freed);
+ return (poh_prev);
+ }
+
+ if (poh_next) {
+ poh_next->size += poh_freed->size;
+ poh_next->offset = poh_freed->offset;
+ XGIfb_free_node(poh_freed);
+ return (poh_next);
+ }
+
+ XGIfb_insert_node(&XGIfb_heap.oh_free, poh_freed);
+
+ return (poh_freed);
+}
+
+static void XGIfb_free_node(XGI_OH *poh)
+{
+ if(poh == NULL) return;
+
+ poh->poh_next = XGIfb_heap.poh_freelist;
+ XGIfb_heap.poh_freelist = poh;
+
+}
+
+void XGI_malloc(struct XGI_memreq *req)
+{
+ XGI_OH *poh;
+
+ poh = XGIfb_poh_allocate(req->size);
+
+ if(poh == NULL) {
+ req->offset = 0;
+ req->size = 0;
+ DPRINTK("XGIfb: Video RAM allocation failed\n");
+ } else {
+ DPRINTK("XGIfb: Video RAM allocation succeeded: 0x%p\n",
+ (char *) (poh->offset + (unsigned long) xgi_video_info.video_vbase));
+
+ req->offset = poh->offset;
+ req->size = poh->size;
+ }
+
+}
+
+void XGI_free(unsigned long base)
+{
+ XGI_OH *poh;
+
+ poh = XGIfb_poh_free(base);
+
+ if(poh == NULL) {
+ DPRINTK("XGIfb: XGIfb_poh_free() failed at base 0x%x\n",
+ (unsigned int) base);
+ }
+}
+
+/* --------------------- SetMode routines ------------------------- */
+
+static void XGIfb_pre_setmode(void)
+{
+ u8 cr30 = 0, cr31 = 0;
+
+ inXGIIDXREG(XGICR, 0x31, cr31);
+ cr31 &= ~0x60;
+
+ switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
+ case DISPTYPE_CRT2:
+ cr30 = (XGI_VB_OUTPUT_CRT2 | XGI_SIMULTANEOUS_VIEW_ENABLE);
+ cr31 |= XGI_DRIVER_MODE;
+ break;
+ case DISPTYPE_LCD:
+ cr30 = (XGI_VB_OUTPUT_LCD | XGI_SIMULTANEOUS_VIEW_ENABLE);
+ cr31 |= XGI_DRIVER_MODE;
+ break;
+ case DISPTYPE_TV:
+ if (xgi_video_info.TV_type == TVMODE_HIVISION)
+ cr30 = (XGI_VB_OUTPUT_HIVISION | XGI_SIMULTANEOUS_VIEW_ENABLE);
+ else if (xgi_video_info.TV_plug == TVPLUG_SVIDEO)
+ cr30 = (XGI_VB_OUTPUT_SVIDEO | XGI_SIMULTANEOUS_VIEW_ENABLE);
+ else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE)
+ cr30 = (XGI_VB_OUTPUT_COMPOSITE | XGI_SIMULTANEOUS_VIEW_ENABLE);
+ else if (xgi_video_info.TV_plug == TVPLUG_SCART)
+ cr30 = (XGI_VB_OUTPUT_SCART | XGI_SIMULTANEOUS_VIEW_ENABLE);
+ cr31 |= XGI_DRIVER_MODE;
+
+ if (XGIfb_tvmode == 1 || xgi_video_info.TV_type == TVMODE_PAL)
+ cr31 |= 0x01;
+ else
+ cr31 &= ~0x01;
+ break;
+ default: /* disable CRT2 */
+ cr30 = 0x00;
+ cr31 |= (XGI_DRIVER_MODE | XGI_VB_OUTPUT_DISABLE);
+ }
+
+ outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
+ outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
+ outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR33, (XGIfb_rate_idx & 0x0F));
+
+ if(xgi_video_info.accel) XGIfb_syncaccel();
+
+
+}
+
+static void XGIfb_post_setmode(void)
+{
+ u8 reg;
+ BOOLEAN doit = TRUE;
+#if 0 /* TW: Wrong: Is not in MMIO space, but in RAM */
+ /* Backup mode number to MMIO space */
+ if(xgi_video_info.mmio_vbase) {
+ *(volatile u8 *)(((u8*)xgi_video_info.mmio_vbase) + 0x449) = (unsigned char)XGIfb_mode_no;
+ }
+#endif
+/* outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
+ outXGIIDXREG(XGICR,0x13,0x00);
+ setXGIIDXREG(XGISR,0x0E,0xF0,0x01);
+*test**/
+ if (xgi_video_info.video_bpp == 8) {
+ /* TW: We can't switch off CRT1 on LVDS/Chrontel in 8bpp Modes */
+ if ((xgi_video_info.hasVB == HASVB_LVDS) || (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL)) {
+ doit = FALSE;
+ }
+ /* TW: We can't switch off CRT1 on 301B-DH in 8bpp Modes if using LCD */
+ if (xgi_video_info.disp_state & DISPTYPE_LCD) {
+ doit = FALSE;
+ }
+ }
+
+ /* TW: We can't switch off CRT1 if bridge is in slave mode */
+ if(xgi_video_info.hasVB != HASVB_NONE) {
+ inXGIIDXREG(XGIPART1, 0x00, reg);
+
+
+ if((reg & 0x50) == 0x10) {
+ doit = FALSE;
+ }
+
+ } else XGIfb_crt1off = 0;
+
+ inXGIIDXREG(XGICR, 0x17, reg);
+ if((XGIfb_crt1off) && (doit))
+ reg &= ~0x80;
+ else
+ reg |= 0x80;
+ outXGIIDXREG(XGICR, 0x17, reg);
+
+ andXGIIDXREG(XGISR, IND_XGI_RAMDAC_CONTROL, ~0x04);
+
+ if((xgi_video_info.disp_state & DISPTYPE_TV) && (xgi_video_info.hasVB == HASVB_301)) {
+
+ inXGIIDXREG(XGIPART4, 0x01, reg);
+
+ if(reg < 0xB0) { /* Set filter for XGI301 */
+
+ switch (xgi_video_info.video_width) {
+ case 320:
+ filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 4 : 12;
+ break;
+ case 640:
+ filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 5 : 13;
+ break;
+ case 720:
+ filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 6 : 14;
+ break;
+ case 800:
+ filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 7 : 15;
+ break;
+ default:
+ filter = -1;
+ break;
+ }
+
+ orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
+
+ if(xgi_video_info.TV_type == TVMODE_NTSC) {
+
+ andXGIIDXREG(XGIPART2, 0x3a, 0x1f);
+
+ if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
+
+ andXGIIDXREG(XGIPART2, 0x30, 0xdf);
+
+ } else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE) {
+
+ orXGIIDXREG(XGIPART2, 0x30, 0x20);
+
+ switch (xgi_video_info.video_width) {
+ case 640:
+ outXGIIDXREG(XGIPART2, 0x35, 0xEB);
+ outXGIIDXREG(XGIPART2, 0x36, 0x04);
+ outXGIIDXREG(XGIPART2, 0x37, 0x25);
+ outXGIIDXREG(XGIPART2, 0x38, 0x18);
+ break;
+ case 720:
+ outXGIIDXREG(XGIPART2, 0x35, 0xEE);
+ outXGIIDXREG(XGIPART2, 0x36, 0x0C);
+ outXGIIDXREG(XGIPART2, 0x37, 0x22);
+ outXGIIDXREG(XGIPART2, 0x38, 0x08);
+ break;
+ case 800:
+ outXGIIDXREG(XGIPART2, 0x35, 0xEB);
+ outXGIIDXREG(XGIPART2, 0x36, 0x15);
+ outXGIIDXREG(XGIPART2, 0x37, 0x25);
+ outXGIIDXREG(XGIPART2, 0x38, 0xF6);
+ break;
+ }
+ }
+
+ } else if(xgi_video_info.TV_type == TVMODE_PAL) {
+
+ andXGIIDXREG(XGIPART2, 0x3A, 0x1F);
+
+ if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
+
+ andXGIIDXREG(XGIPART2, 0x30, 0xDF);
+
+ } else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE) {
+
+ orXGIIDXREG(XGIPART2, 0x30, 0x20);
+
+ switch (xgi_video_info.video_width) {
+ case 640:
+ outXGIIDXREG(XGIPART2, 0x35, 0xF1);
+ outXGIIDXREG(XGIPART2, 0x36, 0xF7);
+ outXGIIDXREG(XGIPART2, 0x37, 0x1F);
+ outXGIIDXREG(XGIPART2, 0x38, 0x32);
+ break;
+ case 720:
+ outXGIIDXREG(XGIPART2, 0x35, 0xF3);
+ outXGIIDXREG(XGIPART2, 0x36, 0x00);
+ outXGIIDXREG(XGIPART2, 0x37, 0x1D);
+ outXGIIDXREG(XGIPART2, 0x38, 0x20);
+ break;
+ case 800:
+ outXGIIDXREG(XGIPART2, 0x35, 0xFC);
+ outXGIIDXREG(XGIPART2, 0x36, 0xFB);
+ outXGIIDXREG(XGIPART2, 0x37, 0x14);
+ outXGIIDXREG(XGIPART2, 0x38, 0x2A);
+ break;
+ }
+ }
+ }
+
+ if ((filter >= 0) && (filter <=7)) {
+ DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb, filter,
+ XGI_TV_filter[filter_tb].filter[filter][0],
+ XGI_TV_filter[filter_tb].filter[filter][1],
+ XGI_TV_filter[filter_tb].filter[filter][2],
+ XGI_TV_filter[filter_tb].filter[filter][3]
+ );
+ outXGIIDXREG(XGIPART2, 0x35, (XGI_TV_filter[filter_tb].filter[filter][0]));
+ outXGIIDXREG(XGIPART2, 0x36, (XGI_TV_filter[filter_tb].filter[filter][1]));
+ outXGIIDXREG(XGIPART2, 0x37, (XGI_TV_filter[filter_tb].filter[filter][2]));
+ outXGIIDXREG(XGIPART2, 0x38, (XGI_TV_filter[filter_tb].filter[filter][3]));
+ }
+
+ }
+
+ }
+
+}
+
+#ifndef MODULE
+XGIINITSTATIC int __init XGIfb_setup(char *options)
+{
+ char *this_opt;
+
+
+
+ xgi_video_info.refresh_rate = 0;
+
+ printk(KERN_INFO "XGIfb: Options %s\n", options);
+
+ if (!options || !*options)
+ return 0;
+
+ while((this_opt = strsep(&options, ",")) != NULL) {
+
+ if (!*this_opt) continue;
+
+ if (!strncmp(this_opt, "mode:", 5)) {
+ XGIfb_search_mode(this_opt + 5);
+ } else if (!strncmp(this_opt, "vesa:", 5)) {
+ XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
+ } else if (!strncmp(this_opt, "mode:", 5)) {
+ XGIfb_search_mode(this_opt + 5);
+ } else if (!strncmp(this_opt, "vesa:", 5)) {
+ XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
+ } else if (!strncmp(this_opt, "vrate:", 6)) {
+ xgi_video_info.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0);
+ } else if (!strncmp(this_opt, "rate:", 5)) {
+ xgi_video_info.refresh_rate = simple_strtoul(this_opt + 5, NULL, 0);
+ } else if (!strncmp(this_opt, "off", 3)) {
+ XGIfb_off = 1;
+ } else if (!strncmp(this_opt, "crt1off", 7)) {
+ XGIfb_crt1off = 1;
+ } else if (!strncmp(this_opt, "filter:", 7)) {
+ filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
+ } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
+ XGIfb_search_crt2type(this_opt + 14);
+ } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
+ XGIfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
+ } else if (!strncmp(this_opt, "tvmode:",7)) {
+ XGIfb_search_tvstd(this_opt + 7);
+ } else if (!strncmp(this_opt, "tvstandard:",11)) {
+ XGIfb_search_tvstd(this_opt + 7);
+ } else if (!strncmp(this_opt, "mem:",4)) {
+ XGIfb_mem = simple_strtoul(this_opt + 4, NULL, 0);
+ } else if (!strncmp(this_opt, "dstn", 4)) {
+ enable_dstn = 1;
+ /* TW: DSTN overrules forcecrt2type */
+ XGIfb_crt2type = DISPTYPE_LCD;
+ } else if (!strncmp(this_opt, "queuemode:", 10)) {
+ XGIfb_search_queuemode(this_opt + 10);
+ } else if (!strncmp(this_opt, "pdc:", 4)) {
+ XGIfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
+ if(XGIfb_pdc & ~0x3c) {
+ printk(KERN_INFO "XGIfb: Illegal pdc parameter\n");
+ XGIfb_pdc = 0;
+ }
+ } else if (!strncmp(this_opt, "noaccel", 7)) {
+ XGIfb_accel = 0;
+ } else if (!strncmp(this_opt, "noypan", 6)) {
+ XGIfb_ypan = 0;
+ } else if (!strncmp(this_opt, "userom:", 7)) {
+ XGIfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
+// } else if (!strncmp(this_opt, "useoem:", 7)) {
+// XGIfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
+ } else {
+ XGIfb_search_mode(this_opt);
+// printk(KERN_INFO "XGIfb: Invalid option %s\n", this_opt);
+ }
+
+ /* TW: Acceleration only with MMIO mode */
+ if((XGIfb_queuemode != -1) && (XGIfb_queuemode != MMIO_CMD)) {
+ XGIfb_ypan = 0;
+ XGIfb_accel = 0;
+ }
+ /* TW: Panning only with acceleration */
+ if(XGIfb_accel == 0) XGIfb_ypan = 0;
+
+ }
+ printk("\nxgifb: outa xgifb_setup 3450");
+ return 0;
+}
+#endif
+
+static unsigned char VBIOS_BUF[65535];
+
+unsigned char* attempt_map_rom(struct pci_dev *dev,void *copy_address)
+{
+ u32 rom_size = 0;
+ u32 rom_address = 0;
+ int j;
+
+ /* Get the size of the expansion rom */
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0xFFFFFFFF);
+ pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_size);
+ if ((rom_size & 0x01) == 0)
+ {
+ printk("No ROM\n");
+ return NULL;
+ }
+
+ rom_size &= 0xFFFFF800;
+ rom_size = (~rom_size)+1;
+
+ rom_address = pci_resource_start(dev, 0);
+ if (rom_address == 0 || rom_address == 0xFFFFFFF0)
+ {
+ printk("No suitable rom address found\n"); return NULL;
+ }
+
+ printk("ROM Size is %dK, Address is %x\n", rom_size/1024, rom_address);
+
+ /* Map ROM */
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS, rom_address | PCI_ROM_ADDRESS_ENABLE);
+
+ /* memcpy(copy_address, rom_address, rom_size); */
+ {
+ unsigned char *virt_addr = ioremap(rom_address, 0x8000000);
+
+ unsigned char *from = (unsigned char *)virt_addr;
+ unsigned char *to = (unsigned char *)copy_address;
+ for (j=0; j<65536 /*rom_size*/; j++) *to++ = *from++;
+ }
+
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
+
+ printk("Copy is done\n");
+
+ return copy_address;
+}
+
+int __devinit xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ u16 reg16;
+ u8 reg, reg1;
+ u8 CR48,CR38;
+ if (XGIfb_off)
+ return -ENXIO;
+
+ XGIfb_registered = 0;
+
+ memset(&XGIhw_ext, 0, sizeof(HW_DEVICE_EXTENSION));
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
+ fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
+ if(!fb_info) return -ENOMEM;
+#else
+ XGI_fb_info = kmalloc( sizeof(struct fb_info), GFP_KERNEL);
+ if(!XGI_fb_info) return -ENOMEM;
+ memset(XGI_fb_info, 0, sizeof(struct fb_info));
+#endif
+
+ xgi_video_info.chip_id = pdev->device;
+ pci_read_config_byte(pdev, PCI_REVISION_ID,&xgi_video_info.revision_id);
+ pci_read_config_word(pdev, PCI_COMMAND, ®16);
+ XGIhw_ext.jChipRevision = xgi_video_info.revision_id;
+ XGIvga_enabled = reg16 & 0x01;
+
+ xgi_video_info.pcibus = pdev->bus->number;
+ xgi_video_info.pcislot = PCI_SLOT(pdev->devfn);
+ xgi_video_info.pcifunc = PCI_FUNC(pdev->devfn);
+ xgi_video_info.subsysvendor = pdev->subsystem_vendor;
+ xgi_video_info.subsysdevice = pdev->subsystem_device;
+
+ xgi_video_info.video_base = pci_resource_start(pdev, 0);
+ xgi_video_info.mmio_base = pci_resource_start(pdev, 1);
+ XGIfb_mmio_size = pci_resource_len(pdev, 1);
+ xgi_video_info.vga_base = pci_resource_start(pdev, 2) + 0x30;
+ XGIhw_ext.pjIOAddress = (PUCHAR)xgi_video_info.vga_base;
+ //XGI_Pr.RelIO = ioremap(pci_resource_start(pdev, 2), 128) + 0x30;
+ printk("XGIfb: Relocate IO address: %lx [%08lx] \n", (unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO);
+
+ if (pci_enable_device(pdev))
+ return -EIO;
+
+ XGIRegInit(&XGI_Pr, (ULONG)XGIhw_ext.pjIOAddress);
+
+ outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
+ inXGIIDXREG(XGISR, IND_XGI_PASSWORD, reg1);
+
+ if(reg1 != 0xa1) /*I/O error */
+ {
+ printk("\nXGIfb: I/O error!!!");
+ return -EIO;
+ }
+
+ switch (xgi_video_info.chip_id) {
+ case PCI_DEVICE_ID_XG_20:
+ orXGIIDXREG(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
+ inXGIIDXREG(XGICR, Index_CR_GPIO_Reg1, CR48);
+ if (CR48&GPIOG_READ)
+ xgi_video_info.chip = XG21;
+ else
+ xgi_video_info.chip = XG20;
+ XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
+ XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
+ break;
+ case PCI_DEVICE_ID_XG_40:
+ xgi_video_info.chip = XG40;
+ XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
+ XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
+ break;
+ case PCI_DEVICE_ID_XG_41:
+ xgi_video_info.chip = XG41;
+ XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
+ XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
+ break;
+ case PCI_DEVICE_ID_XG_42:
+ xgi_video_info.chip = XG42;
+ XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
+ XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
+ break;
+ case PCI_DEVICE_ID_XG_27:
+ xgi_video_info.chip = XG27;
+ XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
+ XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ printk("XGIfb:chipid = %x\n",xgi_video_info.chip);
+ XGIhw_ext.jChipType = xgi_video_info.chip;
+
+ switch (xgi_video_info.chip) {
+ case XG40:
+ case XG41:
+ case XG42:
+ case XG45:
+ case XG20:
+ case XG21:
+ case XG27:
+ XGIhw_ext.bIntegratedMMEnabled = TRUE;
+ break;
+
+ default:
+ break;
+ }
+
+
+ XGIhw_ext.pDevice = NULL;
+ if ((xgi_video_info.chip == XG21) || (XGIfb_userom))
+ {
+ XGIhw_ext.pjVirtualRomBase = attempt_map_rom(pdev, VBIOS_BUF);
+
+ if(XGIhw_ext.pjVirtualRomBase)
+ printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n",XGIhw_ext.pjVirtualRomBase);
+ else
+ printk(KERN_INFO "XGIfb: Video ROM not found\n");
+ } else {
+ XGIhw_ext.pjVirtualRomBase = NULL;
+ printk(KERN_INFO "XGIfb: Video ROM usage disabled\n");
+ }
+ XGIhw_ext.pjCustomizedROMImage = NULL;
+ XGIhw_ext.bSkipDramSizing = 0;
+ XGIhw_ext.pQueryVGAConfigSpace = &XGIfb_query_VGA_config_space;
+// XGIhw_ext.pQueryNorthBridgeSpace = &XGIfb_query_north_bridge_space;
+ strcpy(XGIhw_ext.szVBIOSVer, "0.84");
+
+
+ XGIhw_ext.pSR = vmalloc(sizeof(XGI_DSReg) * SR_BUFFER_SIZE);
+ if (XGIhw_ext.pSR == NULL)
+ {
+ printk(KERN_ERR "XGIfb: Fatal error: Allocating SRReg space failed.\n");
+ return -ENODEV;
+ }
+ XGIhw_ext.pSR[0].jIdx = XGIhw_ext.pSR[0].jVal = 0xFF;
+
+ XGIhw_ext.pCR = vmalloc(sizeof(XGI_DSReg) * CR_BUFFER_SIZE);
+ if (XGIhw_ext.pCR == NULL)
+ {
+ vfree(XGIhw_ext.pSR);
+ printk(KERN_ERR "XGIfb: Fatal error: Allocating CRReg space failed.\n");
+ return -ENODEV;
+ }
+ XGIhw_ext.pCR[0].jIdx = XGIhw_ext.pCR[0].jVal = 0xFF;
+
+
+
+
+ if (!XGIvga_enabled)
+ {
+ /* Mapping Max FB Size for 315 Init */
+ XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
+ if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
+ {
+#ifdef LINUXBIOS
+ printk("XGIfb: XGIInit() ...");
+ /* XGIInitNewt for LINUXBIOS only */
+ if(XGIInitNew(&XGIhw_ext))
+ {
+ printk("OK\n");
+ }
+ else
+ {
+ printk("Fail\n");
+ }
+#endif
+
+ outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
+
+
+ }
+ }
+#ifdef LINUXBIOS
+ else
+ {
+ XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
+ if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
+ {
+
+ outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
+
+ // yilin Because no VBIOS DRAM Sizing, Dram size will error.
+ // Set SR13 ,14 temporarily for UDtech
+ outXGIIDXREG(XGISR, 0x13, 0x45);
+ outXGIIDXREG(XGISR, 0x14, 0x51);
+
+
+ }
+ }
+#endif
+ if (XGIfb_get_dram_size())
+ {
+ vfree(XGIhw_ext.pSR);
+ vfree(XGIhw_ext.pCR);
+ printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n");
+ return -ENODEV;
+ }
+
+
+
+ if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
+ {
+ /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
+ orXGIIDXREG(XGISR, IND_XGI_PCI_ADDRESS_SET, (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE));
+ /* Enable 2D accelerator engine */
+ orXGIIDXREG(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D);
+ }
+
+ XGIhw_ext.ulVideoMemorySize = xgi_video_info.video_size;
+
+ if (!request_mem_region(xgi_video_info.video_base, xgi_video_info.video_size, "XGIfb FB"))
+ { printk("unable request memory size %x",xgi_video_info.video_size);
+ printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
+ printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n");
+ vfree(XGIhw_ext.pSR);
+ vfree(XGIhw_ext.pCR);
+ return -ENODEV;
+ }
+
+ if (!request_mem_region(xgi_video_info.mmio_base, XGIfb_mmio_size, "XGIfb MMIO"))
+ {
+ printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n");
+ release_mem_region(xgi_video_info.video_base, xgi_video_info.video_size);
+ vfree(XGIhw_ext.pSR);
+ vfree(XGIhw_ext.pCR);
+ return -ENODEV;
+ }
+
+ xgi_video_info.video_vbase = XGIhw_ext.pjVideoMemoryAddress =
+ ioremap(xgi_video_info.video_base, xgi_video_info.video_size);
+ xgi_video_info.mmio_vbase = ioremap(xgi_video_info.mmio_base, XGIfb_mmio_size);
+
+ printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
+ xgi_video_info.video_base, xgi_video_info.video_vbase,xgi_video_info.video_size / 1024);
+
+ printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
+ xgi_video_info.mmio_base, xgi_video_info.mmio_vbase,XGIfb_mmio_size / 1024);
+ printk("XGIfb: XGIInitNew() ...");
+ if(XGIInitNew(&XGIhw_ext))
+ {
+ printk("OK\n");
+ }
+ else
+ {
+ printk("Fail\n");
+ }
+
+ if(XGIfb_heap_init())
+ {
+ printk(KERN_WARNING "XGIfb: Failed to initialize offscreen memory heap\n");
+ }
+
+
+ xgi_video_info.mtrr = (unsigned int) 0;
+
+ if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
+ {
+ xgi_video_info.hasVB = HASVB_NONE;
+ if((xgi_video_info.chip == XG20)||(xgi_video_info.chip == XG27))
+ xgi_video_info.hasVB = HASVB_NONE;
+ else if(xgi_video_info.chip == XG21) {
+ inXGIIDXREG(XGICR,0x38,CR38);
+ if ((CR38&0xE0) == 0xC0) {
+ xgi_video_info.disp_state = DISPTYPE_LCD;
+ if (!XGIfb_GetXG21LVDSData()) {
+ int m;
+ for (m=0; m < sizeof(XGI21_LCDCapList)/sizeof(XGI21_LVDSCapStruct); m++) {
+ if ((XGI21_LCDCapList[m].LVDSHDE == XGIbios_mode[xgifb_mode_idx].xres) &&
+ (XGI21_LCDCapList[m].LVDSVDE == XGIbios_mode[xgifb_mode_idx].yres)) {
+ XGINew_SetReg1( XGI_Pr.P3d4 , 0x36, m) ;
+ }
+ }
+ }
+ }
+ else if ((CR38&0xE0) == 0x60)
+ xgi_video_info.hasVB = HASVB_CHRONTEL ;
+ else
+ xgi_video_info.hasVB = HASVB_NONE;
+ }
+ else
+ XGIfb_get_VB_type();
+
+ XGIhw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
+
+ XGIhw_ext.ulExternalChip = 0;
+
+ switch (xgi_video_info.hasVB) {
+ case HASVB_301:
+ inXGIIDXREG(XGIPART4, 0x01, reg);
+ if (reg >= 0xE0) {
+ XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
+ printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
+ } else if (reg >= 0xD0) {
+ XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
+ printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n",reg);
+ }
+ /* else if (reg >= 0xB0) {
+ XGIhw_ext.ujVBChipID = VB_CHIP_301B;
+ inXGIIDXREG(XGIPART4,0x23,reg1);
+ printk("XGIfb: XGI301B bridge detected\n");
+ }*/
+ else {
+ XGIhw_ext.ujVBChipID = VB_CHIP_301;
+ printk("XGIfb: XGI301 bridge detected\n");
+ }
+ break;
+ case HASVB_302:
+ inXGIIDXREG(XGIPART4, 0x01, reg);
+ if (reg >= 0xE0) {
+ XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
+ printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
+ } else if (reg >= 0xD0) {
+ XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
+ printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
+ } else if (reg >= 0xB0) {
+ inXGIIDXREG(XGIPART4,0x23,reg1);
+
+ XGIhw_ext.ujVBChipID = VB_CHIP_302B;
+
+ } else {
+ XGIhw_ext.ujVBChipID = VB_CHIP_302;
+ printk(KERN_INFO "XGIfb: XGI302 bridge detected\n");
+ }
+ break;
+ case HASVB_LVDS:
+ XGIhw_ext.ulExternalChip = 0x1;
+ printk(KERN_INFO "XGIfb: LVDS transmitter detected\n");
+ break;
+ case HASVB_TRUMPION:
+ XGIhw_ext.ulExternalChip = 0x2;
+ printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n");
+ break;
+ case HASVB_CHRONTEL:
+ XGIhw_ext.ulExternalChip = 0x4;
+ printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n");
+ break;
+ case HASVB_LVDS_CHRONTEL:
+ XGIhw_ext.ulExternalChip = 0x5;
+ printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
+ break;
+ default:
+ printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n");
+ break;
+ }
+
+ if (xgi_video_info.hasVB != HASVB_NONE) {
+ XGIfb_detect_VB();
+ }
+
+ if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
+ if (XGIfb_crt1off)
+ xgi_video_info.disp_state |= DISPMODE_SINGLE;
+ else
+ xgi_video_info.disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
+ } else {
+ xgi_video_info.disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
+ }
+
+ if (xgi_video_info.disp_state & DISPTYPE_LCD) {
+ if (!enable_dstn) {
+ inXGIIDXREG(XGICR, IND_XGI_LCD_PANEL, reg);
+ reg &= 0x0f;
+ XGIhw_ext.ulCRT2LCDType = XGI310paneltype[reg];
+
+ } else {
+ // TW: FSTN/DSTN
+ XGIhw_ext.ulCRT2LCDType = LCD_320x480;
+ }
+ }
+
+ XGIfb_detectedpdc = 0;
+
+ XGIfb_detectedlcda = 0xff;
+#ifndef LINUXBIOS
+
+ /* TW: Try to find about LCDA */
+
+ if((XGIhw_ext.ujVBChipID == VB_CHIP_302B) ||
+ (XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
+ (XGIhw_ext.ujVBChipID == VB_CHIP_302LV))
+ {
+ int tmp;
+ inXGIIDXREG(XGICR,0x34,tmp);
+ if(tmp <= 0x13)
+ {
+ // Currently on LCDA? (Some BIOSes leave CR38)
+ inXGIIDXREG(XGICR,0x38,tmp);
+ if((tmp & 0x03) == 0x03)
+ {
+// XGI_Pr.XGI_UseLCDA = TRUE;
+ }else
+ {
+ // Currently on LCDA? (Some newer BIOSes set D0 in CR35)
+ inXGIIDXREG(XGICR,0x35,tmp);
+ if(tmp & 0x01)
+ {
+// XGI_Pr.XGI_UseLCDA = TRUE;
+ }else
+ {
+ inXGIIDXREG(XGICR,0x30,tmp);
+ if(tmp & 0x20)
+ {
+ inXGIIDXREG(XGIPART1,0x13,tmp);
+ if(tmp & 0x04)
+ {
+// XGI_Pr.XGI_UseLCDA = TRUE;
+ }
+ }
+ }
+ }
+ }
+
+ }
+
+
+#endif
+
+ if (xgifb_mode_idx >= 0)
+ xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
+
+ if (xgifb_mode_idx < 0) {
+ switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
+ case DISPTYPE_LCD:
+ xgifb_mode_idx = DEFAULT_LCDMODE;
+ if (xgi_video_info.chip == XG21)
+ {
+ xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
+ }
+ break;
+ case DISPTYPE_TV:
+ xgifb_mode_idx = DEFAULT_TVMODE;
+ break;
+ default:
+ xgifb_mode_idx = DEFAULT_MODE;
+ break;
+ }
+ }
+
+ XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
+
+
+ if( xgi_video_info.refresh_rate == 0)
+ xgi_video_info.refresh_rate = 60; /*yilin set default refresh rate */
+ if(XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0)
+ {
+ XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
+ xgi_video_info.refresh_rate = 60;
+ }
+
+ xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
+ xgi_video_info.video_vwidth = xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
+ xgi_video_info.video_vheight = xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
+ xgi_video_info.org_x = xgi_video_info.org_y = 0;
+ xgi_video_info.video_linelength = xgi_video_info.video_width * (xgi_video_info.video_bpp >> 3);
+ switch(xgi_video_info.video_bpp) {
+ case 8:
+ xgi_video_info.DstColor = 0x0000;
+ xgi_video_info.XGI310_AccelDepth = 0x00000000;
+ xgi_video_info.video_cmap_len = 256;
+ break;
+ case 16:
+ xgi_video_info.DstColor = 0x8000;
+ xgi_video_info.XGI310_AccelDepth = 0x00010000;
+ xgi_video_info.video_cmap_len = 16;
+ break;
+ case 32:
+ xgi_video_info.DstColor = 0xC000;
+ xgi_video_info.XGI310_AccelDepth = 0x00020000;
+ xgi_video_info.video_cmap_len = 16;
+ break;
+ default:
+ xgi_video_info.video_cmap_len = 16;
+ printk(KERN_INFO "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
+ break;
+ }
+
+
+
+ printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n",
+ xgi_video_info.video_width, xgi_video_info.video_height, xgi_video_info.video_bpp,
+ xgi_video_info.refresh_rate);
+
+ default_var.xres = default_var.xres_virtual = xgi_video_info.video_width;
+ default_var.yres = default_var.yres_virtual = xgi_video_info.video_height;
+ default_var.bits_per_pixel = xgi_video_info.video_bpp;
+
+ XGIfb_bpp_to_var(&default_var);
+
+ default_var.pixclock = (u32) (1000000000 /
+ XGIfb_mode_rate_to_dclock(&XGI_Pr, &XGIhw_ext,
+ XGIfb_mode_no, XGIfb_rate_idx));
+
+ if(XGIfb_mode_rate_to_ddata(&XGI_Pr, &XGIhw_ext,
+ XGIfb_mode_no, XGIfb_rate_idx,
+ &default_var.left_margin, &default_var.right_margin,
+ &default_var.upper_margin, &default_var.lower_margin,
+ &default_var.hsync_len, &default_var.vsync_len,
+ &default_var.sync, &default_var.vmode)) {
+
+ if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+ default_var.yres <<= 1;
+ default_var.yres_virtual <<= 1;
+ } else if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+ default_var.pixclock >>= 1;
+ default_var.yres >>= 1;
+ default_var.yres_virtual >>= 1;
+ }
+
+ }
+
+
+#if 0
+#ifdef XGIFB_PAN
+ if(XGIfb_ypan) {
+ default_var.yres_virtual =
+ xgi_video_info.heapstart / (default_var.xres * (default_var.bits_per_pixel >> 3));
+ if(default_var.yres_virtual <= default_var.yres) {
+ default_var.yres_virtual = default_var.yres;
+ }
+ }
+#endif
+#endif
+
+
+ xgi_video_info.accel = 0;
+ if(XGIfb_accel) {
+ xgi_video_info.accel = -1;
+ default_var.accel_flags |= FB_ACCELF_TEXT;
+ XGIfb_initaccel();
+ }
+
+ fb_info->flags = FBINFO_FLAG_DEFAULT;
+ fb_info->var = default_var;
+ fb_info->fix = XGIfb_fix;
+ fb_info->par = &xgi_video_info;
+ fb_info->screen_base = xgi_video_info.video_vbase;
+ fb_info->fbops = &XGIfb_ops;
+ XGIfb_get_fix(&fb_info->fix, -1, fb_info);
+ fb_info->pseudo_palette = pseudo_palette;
+
+ fb_alloc_cmap(&fb_info->cmap, 256 , 0);
+
+
+#ifdef CONFIG_MTRR
+ xgi_video_info.mtrr = mtrr_add((unsigned int) xgi_video_info.video_base,
+ (unsigned int) xgi_video_info.video_size,
+ MTRR_TYPE_WRCOMB, 1);
+ if(xgi_video_info.mtrr) {
+ printk(KERN_INFO "XGIfb: Added MTRRs\n");
+ }
+#endif
+
+ if(register_framebuffer(fb_info) < 0)
+ {
+ return -EINVAL;
+ }
+
+ XGIfb_registered = 1;
+
+ printk(KERN_INFO "XGIfb: Installed XGIFB_GET_INFO ioctl (%x)\n", XGIFB_GET_INFO);
+
+/* printk(KERN_INFO "XGIfb: 2D acceleration is %s, scrolling mode %s\n",
+ XGIfb_accel ? "enabled" : "disabled",
+ XGIfb_ypan ? "ypan" : "redraw");
+*/
+ printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
+ fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
+
+
+ }
+
+ dumpVGAReg();
+
+ return 0;
+}
+
+
+/*****************************************************/
+/* PCI DEVICE HANDLING */
+/*****************************************************/
+
+static void __devexit xgifb_remove(struct pci_dev *pdev)
+{
+ /* Unregister the framebuffer */
+// if(xgi_video_info.registered) {
+ unregister_framebuffer(fb_info);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
+ framebuffer_release(fb_info);
+#else
+ kfree(fb_info);
+#endif
+// }
+
+ pci_set_drvdata(pdev, NULL);
+
+};
+
+static struct pci_driver xgifb_driver = {
+ .name = "xgifb",
+ .id_table = xgifb_pci_table,
+ .probe = xgifb_probe,
+ .remove = __devexit_p(xgifb_remove)
+};
+
+XGIINITSTATIC int __init xgifb_init(void)
+{
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
+#ifndef MODULE
+ char *option = NULL;
+
+ if (fb_get_options("xgifb", &option))
+ return -ENODEV;
+ XGIfb_setup(option);
+#endif
+#endif
+ return(pci_register_driver(&xgifb_driver));
+}
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
+#ifndef MODULE
+module_init(xgifb_init);
+#endif
+#endif
+
+/*****************************************************/
+/* MODULE */
+/*****************************************************/
+
+#ifdef MODULE
+
+static char *mode = NULL;
+static int vesa = 0;
+static unsigned int rate = 0;
+static unsigned int crt1off = 1;
+static unsigned int mem = 0;
+static char *forcecrt2type = NULL;
+static int forcecrt1 = -1;
+static int pdc = -1;
+static int pdc1 = -1;
+static int noaccel = -1;
+static int noypan = -1;
+static int nomax = -1;
+static int userom = -1;
+static int useoem = -1;
+static char *tvstandard = NULL;
+static int nocrt2rate = 0;
+static int scalelcd = -1;
+static char *specialtiming = NULL;
+static int lvdshl = -1;
+static int tvxposoffset = 0, tvyposoffset = 0;
+#if !defined(__i386__) && !defined(__x86_64__)
+static int resetcard = 0;
+static int videoram = 0;
+#endif
+
+MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("XGITECH , Others");
+
+
+
+module_param(mem, int, 0);
+module_param(noaccel, int, 0);
+module_param(noypan, int, 0);
+module_param(nomax, int, 0);
+module_param(userom, int, 0);
+module_param(useoem, int, 0);
+module_param(mode, charp, 0);
+module_param(vesa, int, 0);
+module_param(rate, int, 0);
+module_param(forcecrt1, int, 0);
+module_param(forcecrt2type, charp, 0);
+module_param(scalelcd, int, 0);
+module_param(pdc, int, 0);
+module_param(pdc1, int, 0);
+module_param(specialtiming, charp, 0);
+module_param(lvdshl, int, 0);
+module_param(tvstandard, charp, 0);
+module_param(tvxposoffset, int, 0);
+module_param(tvyposoffset, int, 0);
+module_param(filter, int, 0);
+module_param(nocrt2rate, int, 0);
+#if !defined(__i386__) && !defined(__x86_64__)
+module_param(resetcard, int, 0);
+module_param(videoram, int, 0);
+#endif
+
+
+MODULE_PARM_DESC(mem,
+ "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
+ "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
+ "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
+ "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
+ "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n"
+ "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
+ "for XFree86 4.x/X.org 6.7 and later.\n");
+
+MODULE_PARM_DESC(noaccel,
+ "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
+ "(default: 0)\n");
+
+MODULE_PARM_DESC(noypan,
+ "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
+ "will be performed by redrawing the screen. (default: 0)\n");
+
+MODULE_PARM_DESC(nomax,
+ "\nIf y-panning is enabled, xgifb will by default use the entire available video\n"
+ "memory for the virtual screen in order to optimize scrolling performance. If\n"
+ "this is set to anything other than 0, xgifb will not do this and thereby \n"
+ "enable the user to positively specify a virtual Y size of the screen using\n"
+ "fbset. (default: 0)\n");
+
+
+
+MODULE_PARM_DESC(mode,
+ "\nSelects the desired default display mode in the format XxYxDepth,\n"
+ "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
+ "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
+ "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
+
+MODULE_PARM_DESC(vesa,
+ "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
+ "0x117 (default: 0x0103)\n");
+
+
+MODULE_PARM_DESC(rate,
+ "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
+ "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
+ "will be ignored (default: 60)\n");
+
+MODULE_PARM_DESC(forcecrt1,
+ "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
+ "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
+ "0=CRT1 OFF) (default: [autodetected])\n");
+
+MODULE_PARM_DESC(forcecrt2type,
+ "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
+ "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
+ "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
+ "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
+ "be used instead of TV to override the TV detection. Furthermore, on systems\n"
+ "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
+ "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
+ "depends on the very hardware in use. (default: [autodetected])\n");
+
+MODULE_PARM_DESC(scalelcd,
+ "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
+ "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
+ "show black bars around the image, TMDS panels will probably do the scaling\n"
+ "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
+
+MODULE_PARM_DESC(pdc,
+ "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
+ "should detect this correctly in most cases; however, sometimes this is not\n"
+ "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
+ "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
+ "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
+ "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
+
+MODULE_PARM_DESC(pdc1,
+ "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
+ "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
+ "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
+ "implemented yet.\n");
+
+MODULE_PARM_DESC(specialtiming,
+ "\nPlease refer to documentation for more information on this option.\n");
+
+MODULE_PARM_DESC(lvdshl,
+ "\nPlease refer to documentation for more information on this option.\n");
+
+MODULE_PARM_DESC(tvstandard,
+ "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
+ "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
+
+MODULE_PARM_DESC(tvxposoffset,
+ "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
+ "Default: 0\n");
+
+MODULE_PARM_DESC(tvyposoffset,
+ "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
+ "Default: 0\n");
+
+MODULE_PARM_DESC(filter,
+ "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
+ "(Possible values 0-7, default: [no filter])\n");
+
+MODULE_PARM_DESC(nocrt2rate,
+ "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
+ "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
+
+
+
+
+int __init xgifb_init_module(void)
+{
+ printk("\nXGIfb_init_module");
+ if(mode)
+ XGIfb_search_mode(mode);
+ else if (vesa != -1)
+ XGIfb_search_vesamode(vesa);
+
+ return(xgifb_init());
+}
+
+static void __exit xgifb_remove_module(void)
+{
+ pci_unregister_driver(&xgifb_driver);
+ printk(KERN_DEBUG "xgifb: Module unloaded\n");
+}
+
+module_init(xgifb_init_module);
+module_exit(xgifb_remove_module);
+
+#endif /* /MODULE */
+
+EXPORT_SYMBOL(XGI_malloc);
+EXPORT_SYMBOL(XGI_free);
+
diff --git a/drivers/staging/xgifb/XGIfb.h b/drivers/staging/xgifb/XGIfb.h
new file mode 100644
index 0000000..41bf163
--- /dev/null
+++ b/drivers/staging/xgifb/XGIfb.h
@@ -0,0 +1,215 @@
+#ifndef _LINUX_XGIFB
+#define _LINUX_XGIFB
+#include <linux/spinlock.h>
+#include <asm/ioctl.h>
+#include <asm/types.h>
+
+#define DISPTYPE_CRT1 0x00000008L
+#define DISPTYPE_CRT2 0x00000004L
+#define DISPTYPE_LCD 0x00000002L
+#define DISPTYPE_TV 0x00000001L
+#define DISPTYPE_DISP1 DISPTYPE_CRT1
+#define DISPTYPE_DISP2 (DISPTYPE_CRT2 | DISPTYPE_LCD | DISPTYPE_TV)
+#define DISPMODE_SINGLE 0x00000020L
+#define DISPMODE_MIRROR 0x00000010L
+#define DISPMODE_DUALVIEW 0x00000040L
+
+#define HASVB_NONE 0x00
+#define HASVB_301 0x01
+#define HASVB_LVDS 0x02
+#define HASVB_TRUMPION 0x04
+#define HASVB_LVDS_CHRONTEL 0x10
+#define HASVB_302 0x20
+#define HASVB_303 0x40
+#define HASVB_CHRONTEL 0x80
+
+#ifndef XGIFB_ID
+#define XGIFB_ID 0x53495346 /* Identify myself with 'XGIF' */
+#endif
+
+typedef enum _XGI_CHIP_TYPE {
+ XGI_VGALegacy = 0,
+ XGI_300,
+ XGI_630,
+ XGI_730,
+ XGI_540,
+ XGI_315H,
+ XGI_315,
+ XGI_315PRO,
+ XGI_550,
+ XGI_640,
+ XGI_740,
+ XGI_650,
+ XGI_650M,
+ XGI_330 = 16,
+ XGI_660,
+ XGI_661,
+ XGI_760,
+ XG40 = 32,
+ XG41,
+ XG42,
+ XG45,
+ XG20 = 48,
+ XG21,
+ XG27,
+ MAX_XGI_CHIP
+} XGI_CHIP_TYPE;
+
+typedef enum _TVTYPE {
+ TVMODE_NTSC = 0,
+ TVMODE_PAL,
+ TVMODE_HIVISION,
+ TVTYPE_PALM, // vicki@030226
+ TVTYPE_PALN, // vicki@030226
+ TVTYPE_NTSCJ, // vicki@030226
+ TVMODE_TOTAL
+} XGI_TV_TYPE;
+
+
+typedef struct _XGIFB_INFO XGIfb_info;
+struct _XGIFB_INFO {
+
+unsigned long XGIfb_id;
+ int chip_id; /* PCI ID of detected chip */
+ int memory; /* video memory in KB which XGIfb manages */
+ int heapstart; /* heap start (= XGIfb "mem" argument) in KB */
+ unsigned char fbvidmode; /* current XGIfb mode */
+
+ unsigned char XGIfb_version;
+ unsigned char XGIfb_revision;
+ unsigned char XGIfb_patchlevel;
+
+ unsigned char XGIfb_caps; /* XGIfb capabilities */
+
+ int XGIfb_tqlen; /* turbo queue length (in KB) */
+
+ unsigned int XGIfb_pcibus; /* The card's PCI ID */
+ unsigned int XGIfb_pcislot;
+ unsigned int XGIfb_pcifunc;
+
+ unsigned char XGIfb_lcdpdc; /* PanelDelayCompensation */
+
+ unsigned char XGIfb_lcda; /* Detected status of LCDA for low res/text modes */
+
+ char reserved[235]; /* for future use */
+};
+
+
+
+
+typedef enum _TVPLUGTYPE { // vicki@030226
+// TVPLUG_Legacy = 0,
+// TVPLUG_COMPOSITE,
+// TVPLUG_SVIDEO,
+// TVPLUG_SCART,
+// TVPLUG_TOTAL
+ TVPLUG_UNKNOWN = 0,
+ TVPLUG_COMPOSITE = 1,
+ TVPLUG_SVIDEO = 2,
+ TVPLUG_COMPOSITE_AND_SVIDEO = 3,
+ TVPLUG_SCART = 4,
+ TVPLUG_YPBPR_525i = 5,
+ TVPLUG_YPBPR_525P = 6,
+ TVPLUG_YPBPR_750P = 7,
+ TVPLUG_YPBPR_1080i = 8,
+ TVPLUG_TOTAL
+} XGI_TV_PLUG;
+
+
+struct mode_info {
+ int bpp;
+ int xres;
+ int yres;
+ int v_xres;
+ int v_yres;
+ int org_x;
+ int org_y;
+ unsigned int vrate;
+};
+
+struct ap_data {
+ struct mode_info minfo;
+ unsigned long iobase;
+ unsigned int mem_size;
+ unsigned long disp_state;
+ XGI_CHIP_TYPE chip;
+ unsigned char hasVB;
+ XGI_TV_TYPE TV_type;
+ XGI_TV_PLUG TV_plug;
+ unsigned long version;
+ char reserved[256];
+};
+
+
+
+/* If changing this, vgatypes.h must also be changed (for X driver) */
+
+
+/*
+ * NOTE! The ioctl types used to be "size_t" by mistake, but were
+ * really meant to be __u32. Changed to "__u32" even though that
+ * changes the value on 64-bit architectures, because the value
+ * (with a 4-byte size) is also hardwired in vgatypes.h for user
+ * space exports. So "__u32" is actually more compatible, duh!
+ */
+#define XGIFB_GET_INFO _IOR('n',0xF8,__u32)
+#define XGIFB_GET_VBRSTATUS _IOR('n',0xF9,__u32)
+
+
+
+struct video_info{
+ int chip_id;
+ unsigned int video_size;
+ unsigned long video_base;
+ char * video_vbase;
+ unsigned long mmio_base;
+ char * mmio_vbase;
+ unsigned long vga_base;
+ unsigned long mtrr;
+ unsigned long heapstart;
+
+ int video_bpp;
+ int video_cmap_len;
+ int video_width;
+ int video_height;
+ int video_vwidth;
+ int video_vheight;
+ int org_x;
+ int org_y;
+ int video_linelength;
+ unsigned int refresh_rate;
+
+ unsigned long disp_state;
+ unsigned char hasVB;
+ unsigned char TV_type;
+ unsigned char TV_plug;
+
+ XGI_CHIP_TYPE chip;
+ unsigned char revision_id;
+
+ unsigned short DstColor;
+ unsigned long XGI310_AccelDepth;
+ unsigned long CommandReg;
+
+ spinlock_t lockaccel;
+
+ unsigned int pcibus;
+ unsigned int pcislot;
+ unsigned int pcifunc;
+
+ int accel;
+ unsigned short subsysvendor;
+ unsigned short subsysdevice;
+
+ char reserved[236];
+};
+
+
+extern struct video_info xgi_video_info;
+
+#ifdef __KERNEL__
+//extern void xgi_malloc(struct xgi_memreq *req);
+extern void xgi_free(unsigned long base);
+extern void xgi_dispinfo(struct ap_data *rec);
+#endif
+#endif
diff --git a/drivers/staging/xgifb/osdef.h b/drivers/staging/xgifb/osdef.h
new file mode 100644
index 0000000..4bc7d3a
--- /dev/null
+++ b/drivers/staging/xgifb/osdef.h
@@ -0,0 +1,153 @@
+#ifndef _OSDEF_H_
+#define _OSDEF_H_
+
+/* #define WINCE_HEADER*/
+/*#define WIN2000*/
+/* #define TC */
+#define LINUX_KERNEL
+/* #define LINUX_XF86 */
+
+/**********************************************************************/
+#ifdef LINUX_KERNEL
+//#include <linux/config.h>
+#endif
+
+
+/**********************************************************************/
+#ifdef TC
+#endif
+#ifdef WIN2000
+#endif
+#ifdef WINCE_HEADER
+#endif
+#ifdef LINUX_XF86
+#define LINUX
+#endif
+#ifdef LINUX_KERNEL
+#define LINUX
+#endif
+
+/**********************************************************************/
+#ifdef TC
+#define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize);
+#endif
+#ifdef WIN2000
+#define XGI_SetMemory(MemoryAddress,MemorySize,value) MemFill((PVOID) MemoryAddress,(ULONG) MemorySize,(UCHAR) value);
+#endif
+#ifdef WINCE_HEADER
+#define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize);
+#endif
+#ifdef LINUX_XF86
+#define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
+#endif
+#ifdef LINUX_KERNEL
+#define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
+#endif
+/**********************************************************************/
+
+/**********************************************************************/
+
+#ifdef TC
+#define XGI_MemoryCopy(Destination,Soruce,Length) memmove(Destination, Soruce, Length);
+#endif
+#ifdef WIN2000
+#define XGI_MemoryCopy(Destination,Soruce,Length) /*VideoPortMoveMemory((PUCHAR)Destination , Soruce,length);*/
+#endif
+#ifdef WINCE_HEADER
+#define XGI_MemoryCopy(Destination,Soruce,Length) memmove(Destination, Soruce, Length);
+#endif
+#ifdef LINUX_XF86
+#define XGI_MemoryCopy(Destination,Soruce,Length) memcpy(Destination,Soruce,Length)
+#endif
+#ifdef LINUX_KERNEL
+#define XGI_MemoryCopy(Destination,Soruce,Length) memcpy(Destination,Soruce,Length)
+#endif
+
+/**********************************************************************/
+
+#ifdef OutPortByte
+#undef OutPortByte
+#endif /* OutPortByte */
+
+#ifdef OutPortWord
+#undef OutPortWord
+#endif /* OutPortWord */
+
+#ifdef OutPortLong
+#undef OutPortLong
+#endif /* OutPortLong */
+
+#ifdef InPortByte
+#undef InPortByte
+#endif /* InPortByte */
+
+#ifdef InPortWord
+#undef InPortWord
+#endif /* InPortWord */
+
+#ifdef InPortLong
+#undef InPortLong
+#endif /* InPortLong */
+
+/**********************************************************************/
+/* TC */
+/**********************************************************************/
+
+#ifdef TC
+#define OutPortByte(p,v) outp((unsigned short)(p),(unsigned char)(v))
+#define OutPortWord(p,v) outp((unsigned short)(p),(unsigned short)(v))
+#define OutPortLong(p,v) outp((unsigned short)(p),(unsigned long)(v))
+#define InPortByte(p) inp((unsigned short)(p))
+#define InPortWord(p) inp((unsigned short)(p))
+#define InPortLong(p) ((inp((unsigned short)(p+2))<<16) | inp((unsigned short)(p)))
+#endif
+
+/**********************************************************************/
+/* LINUX XF86 */
+/**********************************************************************/
+
+#ifdef LINUX_XF86
+#define OutPortByte(p,v) outb((CARD16)(p),(CARD8)(v))
+#define OutPortWord(p,v) outw((CARD16)(p),(CARD16)(v))
+#define OutPortLong(p,v) outl((CARD16)(p),(CARD32)(v))
+#define InPortByte(p) inb((CARD16)(p))
+#define InPortWord(p) inw((CARD16)(p))
+#define InPortLong(p) inl((CARD16)(p))
+#endif
+
+#ifdef LINUX_KERNEL
+#define OutPortByte(p,v) outb((u8)(v),(p))
+#define OutPortWord(p,v) outw((u16)(v),(p))
+#define OutPortLong(p,v) outl((u32)(v),(p))
+#define InPortByte(p) inb(p)
+#define InPortWord(p) inw(p)
+#define InPortLong(p) inl(p)
+#endif
+
+/**********************************************************************/
+/* WIN 2000 */
+/**********************************************************************/
+
+#ifdef WIN2000
+#define OutPortByte(p,v) VideoPortWritePortUchar ((PUCHAR) (p), (UCHAR) (v))
+#define OutPortWord(p,v) VideoPortWritePortUshort((PUSHORT) (p), (USHORT) (v))
+#define OutPortLong(p,v) VideoPortWritePortUlong ((PULONG) (p), (ULONG) (v))
+#define InPortByte(p) VideoPortReadPortUchar ((PUCHAR) (p))
+#define InPortWord(p) VideoPortReadPortUshort ((PUSHORT) (p))
+#define InPortLong(p) VideoPortReadPortUlong ((PULONG) (p))
+#endif
+
+
+/**********************************************************************/
+/* WIN CE */
+/**********************************************************************/
+
+#ifdef WINCE_HEADER
+#define OutPortByte(p,v) WRITE_PORT_UCHAR ((PUCHAR) (p), (UCHAR) (v))
+#define OutPortWord(p,v) WRITE_PORT_USHORT((PUSHORT) (p), (USHORT) (v))
+#define OutPortLong(p,v) WRITE_PORT_ULONG ((PULONG) (p), (ULONG) (v))
+#define InPortByte(p) READ_PORT_UCHAR ((PUCHAR) (p))
+#define InPortWord(p) READ_PORT_USHORT ((PUSHORT) (p))
+#define InPortLong(p) READ_PORT_ULONG ((PULONG) (p))
+#endif
+#endif // _OSDEF_H_
diff --git a/drivers/staging/xgifb/vb_def.h b/drivers/staging/xgifb/vb_def.h
new file mode 100644
index 0000000..17a7ada
--- /dev/null
+++ b/drivers/staging/xgifb/vb_def.h
@@ -0,0 +1,1017 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/xgi/initdef.h,v 1.4 2000/12/02 01:16:17 dawes Exp $ */
+#ifndef _INITDEF_
+#define _INITDEF_
+
+#ifndef NewScratch
+#define NewScratch
+#endif
+/* shampoo */
+#ifdef LINUX_KERNEL
+#define SEQ_ADDRESS_PORT 0x0014
+#define SEQ_DATA_PORT 0x0015
+#define MISC_OUTPUT_REG_READ_PORT 0x001C
+#define MISC_OUTPUT_REG_WRITE_PORT 0x0012
+#define GRAPH_DATA_PORT 0x1F
+#define GRAPH_ADDRESS_PORT 0x1E
+#define XGI_MASK_DUAL_CHIP 0x04 /* SR3A */
+#define CRTC_ADDRESS_PORT_COLOR 0x0024
+#define VIDEO_SUBSYSTEM_ENABLE_PORT 0x0013
+#define PCI_COMMAND 0x04
+#endif
+/* ~shampoo */
+
+
+#define VB_XGI301 0x0001 /*301b*/
+#define VB_XGI301B 0x0002
+#define VB_XGI302B 0x0004
+#define VB_XGI301LV 0x0008 /*301lv*/
+#define VB_XGI302LV 0x0010
+#define VB_XGI301C 0x0020 /* for 301C */
+#define VB_NoLCD 0x8000
+/*end 301b*/
+
+#define VB_YPbPrInfo 0x07 /*301lv*/
+#define VB_YPbPr525i 0x00
+#define VB_YPbPr525p 0x01
+#define VB_YPbPr750p 0x02
+#define VB_YPbPr1080i 0x03
+
+/* #define CRT1Len 17 */
+#define LVDSCRT1Len 15
+#define CHTVRegDataLen 5
+
+/* #define ModeInfoFlag 0x07 */
+/* #define IsTextMode 0x07 */
+/* #define ModeText 0x00 */
+/* #define ModeCGA 0x01 */
+/* #define ModeEGA 0x02 */
+/* #define ModeVGA 0x03 */
+/* #define Mode15Bpp 0x04 */
+/* #define Mode16Bpp 0x05 */
+/* #define Mode24Bpp 0x06 */
+/* #define Mode32Bpp 0x07 */
+
+/* #define DACInfoFlag 0x18 */
+/* #define MemoryInfoFlag 0x1E0 */
+/* #define MemorySizeShift 0x05 */
+
+#define Charx8Dot 0x0200
+#define LineCompareOff 0x0400
+#define CRT2Mode 0x0800
+#define HalfDCLK 0x1000
+#define NoSupportSimuTV 0x2000
+#define DoubleScanMode 0x8000
+
+#define SupportAllCRT2 0x0078
+#define SupportTV 0x0008
+#define SupportHiVisionTV 0x0010
+#define SupportLCD 0x0020
+#define SupportRAMDAC2 0x0040
+#define NoSupportTV 0x0070
+#define NoSupportHiVisionTV 0x0060
+#define NoSupportLCD 0x0058
+#define SupportCHTV 0x0800
+#define SupportCRT2in301C 0x0100 /* for 301C */
+#define SupportTV1024 0x0800 /*301b*/
+#define SupportYPbPr 0x1000 /*301lv*/
+#define InterlaceMode 0x0080
+#define SyncPP 0x0000
+#define SyncPN 0x4000
+#define SyncNP 0x8000
+/* #define SyncNN 0xc000 */
+#define ECLKindex0 0x0000
+#define ECLKindex1 0x0100
+#define ECLKindex2 0x0200
+#define ECLKindex3 0x0300
+#define ECLKindex4 0x0400
+
+#define SetSimuScanMode 0x0001
+#define SwitchToCRT2 0x0002
+/* #define SetCRT2ToTV 0x009C */
+#define SetCRT2ToAVIDEO 0x0004
+#define SetCRT2ToSVIDEO 0x0008
+#define SetCRT2ToSCART 0x0010
+#define SetCRT2ToLCD 0x0020
+#define SetCRT2ToRAMDAC 0x0040
+#define SetCRT2ToHiVisionTV 0x0080
+#define SetNTSCTV 0x0000
+/* #define SetPALTV 0x0100 */
+#define SetInSlaveMode 0x0200
+#define SetNotSimuMode 0x0400
+#define SetNotSimuTVMode 0x0400
+#define SetDispDevSwitch 0x0800
+#define LoadDACFlag 0x1000
+#define DisableCRT2Display 0x2000
+#define DriverMode 0x4000
+#define HotKeySwitch 0x8000
+#define SetCHTVOverScan 0x8000
+/* #define SetCRT2ToLCDA 0x8000 301b */
+#define PanelRGB18Bit 0x0100
+#define PanelRGB24Bit 0x0000
+
+#define TVOverScan 0x10
+#define TVOverScanShift 4
+#define ClearBufferFlag 0x20
+#define EnableDualEdge 0x01 /*301b*/
+#define SetToLCDA 0x02
+
+#define YPbPrModeInfo 0x38
+/* #define YPbPrMode525i 0x00 */
+/* #define YPbPrMode525p 0x08 */
+/* #define YPbPrMode750p 0x10 */
+/* #define YPbPrMode1080i 0x18 */
+
+#define SetSCARTOutput 0x01
+#define BoardTVType 0x02
+#define EnablePALMN 0x40
+/* #define ProgrammingCRT2 0x01 */
+/* #define TVSimuMode 0x02 */
+/* #define RPLLDIV2XO 0x04 */
+/* #define LCDVESATiming 0x08 */
+/* #define EnableLVDSDDA 0x10 */
+#define SetDispDevSwitchFlag 0x20
+#define CheckWinDos 0x40
+#define SetJDOSMode 0x80
+
+#define Panel320x480 0x07/*fstn*/
+/* [ycchen] 02/12/03 Modify for Multi-Sync. LCD Support */
+#define PanelResInfo 0x1F /* CR36 Panel Type/LCDResInfo */
+#define PanelRefInfo 0x60
+#define Panel800x600 0x01
+#define Panel1024x768 0x02
+#define Panel1024x768x75 0x22
+#define Panel1280x1024 0x03
+#define Panel1280x1024x75 0x23
+#define Panel640x480 0x04
+#define Panel1024x600 0x05
+#define Panel1152x864 0x06
+#define Panel1280x960 0x07
+#define Panel1152x768 0x08
+#define Panel1400x1050 0x09
+#define Panel1280x768 0x0A
+#define Panel1600x1200 0x0B
+
+#define PanelRef60Hz 0x00
+#define PanelRef75Hz 0x20
+#define LCDRGB18Bit 0x01
+
+#define ExtChipTrumpion 0x06
+#define ExtChipCH7005 0x08
+#define ExtChipMitacTV 0x0a
+#define LCDNonExpanding 0x10
+#define LCDNonExpandingShift 4
+#define LCDSync 0x20
+#define LCDSyncBit 0xe0
+#define LCDSyncShift 6
+
+/* #define DDC2DelayTime 300 */
+
+#define CRT2DisplayFlag 0x2000
+/* #define LCDDataLen 8 */
+/* #define HiTVDataLen 12 */
+/* #define TVDataLen 16 */
+/* #define SetPALTV 0x0100 */
+#define HalfDCLK 0x1000
+#define NTSCHT 1716
+#define NTSCVT 525
+#define PALHT 1728
+#define PALVT 625
+#define StHiTVHT 892
+#define StHiTVVT 1126
+#define StHiTextTVHT 1000
+#define StHiTextTVVT 1126
+#define ExtHiTVHT 2100
+#define ExtHiTVVT 1125
+
+#define St750pTVHT 1716
+#define St750pTVVT 525
+#define Ext750pTVHT 1716
+#define Ext750pTVVT 525
+#define St525pTVHT 1716
+#define St525pTVVT 525
+#define Ext525pTVHT 1716
+#define Ext525pTVVT 525
+#define St525iTVHT 1716
+#define St525iTVVT 525
+#define Ext525iTVHT 1716
+#define Ext525iTVVT 525
+
+#define VCLKStartFreq 25
+#define SoftDramType 0x80
+#define VCLK40 0x04
+
+#define VCLK162 0x21
+
+#define LCDRGB18Bit 0x01
+#define LoadDACFlag 0x1000
+#define AfterLockCRT2 0x4000
+#define SetCRT2ToAVIDEO 0x0004
+#define SetCRT2ToSCART 0x0010
+#define Ext2StructSize 5
+
+
+#define YPbPr525iVCLK 0x03B
+#define YPbPr525iVCLK_2 0x03A
+
+#define SwitchToCRT2 0x0002
+/* #define LCDVESATiming 0x08 */
+#define SetSCARTOutput 0x01
+#define AVIDEOSense 0x01
+#define SVIDEOSense 0x02
+#define SCARTSense 0x04
+#define LCDSense 0x08
+#define Monitor1Sense 0x20
+#define Monitor2Sense 0x10
+#define HiTVSense 0x40
+#define BoardTVType 0x02
+#define HotPlugFunction 0x08
+#define StStructSize 0x06
+
+
+#define XGI_CRT2_PORT_00 0x00 - 0x030
+#define XGI_CRT2_PORT_04 0x04 - 0x030
+#define XGI_CRT2_PORT_10 0x10 - 0x30
+#define XGI_CRT2_PORT_12 0x12 - 0x30
+#define XGI_CRT2_PORT_14 0x14 - 0x30
+
+
+#define LCDNonExpanding 0x10
+#define ADR_CRT2PtrData 0x20E
+#define offset_Zurac 0x210
+#define ADR_LVDSDesPtrData 0x212
+#define ADR_LVDSCRT1DataPtr 0x214
+#define ADR_CHTVVCLKPtr 0x216
+#define ADR_CHTVRegDataPtr 0x218
+
+#define LVDSDataLen 6
+/* #define EnableLVDSDDA 0x10 */
+/* #define LVDSDesDataLen 3 */
+#define ActiveNonExpanding 0x40
+#define ActiveNonExpandingShift 6
+/* #define ActivePAL 0x20 */
+#define ActivePALShift 5
+/* #define ModeSwitchStatus 0x0F */
+#define SoftTVType 0x40
+#define SoftSettingAddr 0x52
+#define ModeSettingAddr 0x53
+
+/* #define SelectCRT1Rate 0x4 */
+
+#define _PanelType00 0x00
+#define _PanelType01 0x08
+#define _PanelType02 0x10
+#define _PanelType03 0x18
+#define _PanelType04 0x20
+#define _PanelType05 0x28
+#define _PanelType06 0x30
+#define _PanelType07 0x38
+#define _PanelType08 0x40
+#define _PanelType09 0x48
+#define _PanelType0A 0x50
+#define _PanelType0B 0x58
+#define _PanelType0C 0x60
+#define _PanelType0D 0x68
+#define _PanelType0E 0x70
+#define _PanelType0F 0x78
+
+
+#define PRIMARY_VGA 0 /* 1: XGI is primary vga 0:XGI is secondary vga */
+#define BIOSIDCodeAddr 0x235
+#define OEMUtilIDCodeAddr 0x237
+#define VBModeIDTableAddr 0x239
+#define OEMTVPtrAddr 0x241
+#define PhaseTableAddr 0x243
+#define NTSCFilterTableAddr 0x245
+#define PALFilterTableAddr 0x247
+#define OEMLCDPtr_1Addr 0x249
+#define OEMLCDPtr_2Addr 0x24B
+#define LCDHPosTable_1Addr 0x24D
+#define LCDHPosTable_2Addr 0x24F
+#define LCDVPosTable_1Addr 0x251
+#define LCDVPosTable_2Addr 0x253
+#define OEMLCDPIDTableAddr 0x255
+
+#define VBModeStructSize 5
+#define PhaseTableSize 4
+#define FilterTableSize 4
+#define LCDHPosTableSize 7
+#define LCDVPosTableSize 5
+#define OEMLVDSPIDTableSize 4
+#define LVDSHPosTableSize 4
+#define LVDSVPosTableSize 6
+
+#define VB_ModeID 0
+#define VB_TVTableIndex 1
+#define VB_LCDTableIndex 2
+#define VB_LCDHIndex 3
+#define VB_LCDVIndex 4
+
+#define OEMLCDEnable 0x0001
+#define OEMLCDDelayEnable 0x0002
+#define OEMLCDPOSEnable 0x0004
+#define OEMTVEnable 0x0100
+#define OEMTVDelayEnable 0x0200
+#define OEMTVFlickerEnable 0x0400
+#define OEMTVPhaseEnable 0x0800
+#define OEMTVFilterEnable 0x1000
+
+#define OEMLCDPanelIDSupport 0x0080
+
+/* #define LCDVESATiming 0x0001 //LCD Info CR37 */
+/* #define EnableLVDSDDA 0x0002 */
+#define EnableScalingLCD 0x0008
+#define SetPWDEnable 0x0004
+#define SetLCDtoNonExpanding 0x0010
+/* #define SetLCDPolarity 0x00E0 */
+#define SetLCDDualLink 0x0100
+#define SetLCDLowResolution 0x0200
+#define SetLCDStdMode 0x0400
+#define SetTVStdMode 0x0200
+#define SetTVLowResolution 0x0400
+/* =============================================================
+ for 310
+============================================================== */
+#define SoftDRAMType 0x80
+#define SoftSetting_OFFSET 0x52
+#define SR07_OFFSET 0x7C
+#define SR15_OFFSET 0x7D
+#define SR16_OFFSET 0x81
+#define SR17_OFFSET 0x85
+#define SR19_OFFSET 0x8D
+#define SR1F_OFFSET 0x99
+#define SR21_OFFSET 0x9A
+#define SR22_OFFSET 0x9B
+#define SR23_OFFSET 0x9C
+#define SR24_OFFSET 0x9D
+#define SR25_OFFSET 0x9E
+#define SR31_OFFSET 0x9F
+#define SR32_OFFSET 0xA0
+#define SR33_OFFSET 0xA1
+
+#define CR40_OFFSET 0xA2
+#define SR25_1_OFFSET 0xF6
+#define CR49_OFFSET 0xF7
+
+#define VB310Data_1_2_Offset 0xB6
+#define VB310Data_4_D_Offset 0xB7
+#define VB310Data_4_E_Offset 0xB8
+#define VB310Data_4_10_Offset 0xBB
+
+#define RGBSenseDataOffset 0xBD
+#define YCSenseDataOffset 0xBF
+#define VideoSenseDataOffset 0xC1
+#define OutputSelectOffset 0xF3
+
+#define ECLK_MCLK_DISTANCE 0x14
+#define VBIOSTablePointerStart 0x200
+#define StandTablePtrOffset VBIOSTablePointerStart+0x02
+#define EModeIDTablePtrOffset VBIOSTablePointerStart+0x04
+#define CRT1TablePtrOffset VBIOSTablePointerStart+0x06
+#define ScreenOffsetPtrOffset VBIOSTablePointerStart+0x08
+#define VCLKDataPtrOffset VBIOSTablePointerStart+0x0A
+#define MCLKDataPtrOffset VBIOSTablePointerStart+0x0E
+#define CRT2PtrDataPtrOffset VBIOSTablePointerStart+0x10
+#define TVAntiFlickPtrOffset VBIOSTablePointerStart+0x12
+#define TVDelayPtr1Offset VBIOSTablePointerStart+0x14
+#define TVPhaseIncrPtr1Offset VBIOSTablePointerStart+0x16
+#define TVYFilterPtr1Offset VBIOSTablePointerStart+0x18
+#define LCDDelayPtr1Offset VBIOSTablePointerStart+0x20
+#define TVEdgePtr1Offset VBIOSTablePointerStart+0x24
+#define CRT2Delay1Offset VBIOSTablePointerStart+0x28
+#define LCDDataDesOffset VBIOSTablePointerStart-0x02
+#define LCDDataPtrOffset VBIOSTablePointerStart+0x2A
+#define LCDDesDataPtrOffset VBIOSTablePointerStart+0x2C
+#define LCDDataList VBIOSTablePointerStart+0x22 /* add for GetLCDPtr */
+#define TVDataList VBIOSTablePointerStart+0x36 /* add for GetTVPtr */
+/* */
+/* Modify from 310.inc */
+/* */
+/* */
+
+
+#define ShowMsgFlag 0x20 /* SoftSetting */
+#define ShowVESAFlag 0x10
+#define HotPlugFunction 0x08
+#define ModeSoftSetting 0x04
+#define TVSoftSetting 0x02
+#define LCDSoftSetting 0x01
+
+#define GatingCRTinLCDA 0x10
+#define SetHiTVOutput 0x08
+#define SetYPbPrOutput 0x04
+#define BoardTVType 0x02
+#define SetSCARTOutput 0x01
+
+#define ModeSettingYPbPr 0x02 /* TVModeSetting, Others as same as CR30 */
+
+/* TVModeSetting same as CR35 */
+
+/* LCDModeSetting same as CR37 */
+
+#define EnableNewTVFont 0x10 /* MiscCapability */
+
+#define EnableLCDOutput 0x80 /* LCDCfgSetting */
+
+#define SoftDRAMType 0x80 /* DRAMSetting */
+#define SoftDRAMConfig 0x40
+#define MosSelDRAMType 0x20
+#define SDRAM 000h
+#define SGRAM 0x01
+#define ESDRAM 0x02
+
+#define EnableAGPCfgSetting 0x01 /* AGPCfgSetting */
+
+/* ---------------- SetMode Stack */
+#define CRT1Len 15
+#define VCLKLen 4
+#define DefThreshold 0x0100
+#define ExtRegsSize (57+8+37+70+63+28+768+1)/64+1
+
+#define VGA_XGI315 0x0001 /* VGA Type Info */
+#define VGA_SNewis315e 0x0002 /* 315 series */
+#define VGA_XGI550 0x0004
+#define VGA_XGI640 0x0008
+#define VGA_XGI740 0x0010
+#define VGA_XGI650 0x0020
+#define VGA_XGI650M 0x0040
+#define VGA_XGI651 0x0080
+#define VGA_XGI340 0x0001 /* 340 series */
+#define VGA_XGI330 0x0001 /* 330 series */
+#define VGA_XGI660 0x0001 /* 660 series */
+
+#define VB_XGI301 0x0001 /* VB Type Info */
+#define VB_XGI301B 0x0002 /* 301 series */
+#define VB_XGI302B 0x0004
+#define VB_NoLCD 0x8000
+#define VB_XGI301LV 0x0008
+#define VB_XGI302LV 0x0010
+#define VB_LVDS_NS 0x0001 /* 3rd party chip */
+#define VB_CH7017 0x0002
+#define VB_CH7007 0x0080 /* [Billy] 07/05/03 */
+/* #define VB_LVDS_SI 0x0004 */
+
+#define ModeInfoFlag 0x0007
+#define IsTextMode 0x0007
+#define ModeText 0x0000
+#define ModeCGA 0x0001
+#define ModeEGA 0x0002 /* 16 colors mode */
+#define ModeVGA 0x0003 /* 256 colors mode */
+#define Mode15Bpp 0x0004 /* 15 Bpp Color Mode */
+#define Mode16Bpp 0x0005 /* 16 Bpp Color Mode */
+#define Mode24Bpp 0x0006 /* 24 Bpp Color Mode */
+#define Mode32Bpp 0x0007 /* 32 Bpp Color Mode */
+
+#define DACInfoFlag 0x0018
+#define MONODAC 0x0000
+#define CGADAC 0x0008
+#define EGADAC 0x0010
+#define VGADAC 0x0018
+
+#define MemoryInfoFlag 0x01e0
+#define MemorySizeShift 5
+#define Need1MSize 0x0000
+#define Need2MSize 0x0020
+#define Need4MSize 0x0060
+#define Need8MSize 0x00e0
+#define Need16MSize 0x01e0
+
+#define Charx8Dot 0x0200
+#define LineCompareOff 0x0400
+#define CRT2Mode 0x0800
+#define HalfDCLK 0x1000
+#define NoSupportSimuTV 0x2000
+#define DoubleScanMode 0x8000
+
+/* -------------- Ext_InfoFlag */
+#define SupportModeInfo 0x0007
+#define Support256 0x0003
+#define Support15Bpp 0x0004
+#define Support16Bpp 0x0005
+#define Support24Bpp 0x0006
+#define Support32Bpp 0x0007
+
+#define SupportAllCRT2 0x0078
+#define SupportTV 0x0008
+#define SupportHiVisionTV 0x0010
+#define SupportLCD 0x0020
+#define SupportRAMDAC2 0x0040
+#define NoSupportTV 0x0070
+#define NoSupportHiVisionTV 0x0060
+#define NoSupportLCD 0x0058
+#define SupportTV1024 0x0800 /* 301btest */
+#define SupportYPbPr 0x1000 /* 301lv */
+#define InterlaceMode 0x0080
+#define SyncPP 0x0000
+#define SyncPN 0x4000
+#define SyncNP 0x8000
+#define SyncNN 0xC000
+
+/* -------------- SetMode Stack/Scratch */
+#define SetSimuScanMode 0x0001 /* VBInfo/CR30 & CR31 */
+#define SwitchToCRT2 0x0002
+#define SetCRT2ToTV1 0x009C
+#define SetCRT2ToTV 0x089C
+#define SetCRT2ToAVIDEO 0x0004
+#define SetCRT2ToSVIDEO 0x0008
+#define SetCRT2ToSCART 0x0010
+#define SetCRT2ToLCD 0x0020
+#define SetCRT2ToRAMDAC 0x0040
+#define SetCRT2ToHiVisionTV 0x0080
+#define SetCRT2ToLCDA 0x0100
+#define SetInSlaveMode 0x0200
+#define SetNotSimuMode 0x0400
+#define HKEventMode 0x0800
+#define SetCRT2ToYPbPr 0x0800
+#define LoadDACFlag 0x1000
+#define DisableCRT2Display 0x2000
+#define DriverMode 0x4000
+#define SetCRT2ToDualEdge 0x8000
+#define HotKeySwitch 0x8000
+
+#define ProgrammingCRT2 0x0001 /* Set Flag */
+#define EnableVCMode 0x0002
+#define SetHKEventMode 0x0004
+#define ReserveTVOption 0x0008
+#define DisableRelocateIO 0x0010
+#define Win9xDOSMode 0x0020
+#define JDOSMode 0x0040
+/* #define SetWin9xforJap 0x0080 // not used now */
+/* #define SetWin9xforKorea 0x0100 // not used now */
+#define GatingCRT 0x0800
+#define DisableChB 0x1000
+#define EnableChB 0x2000
+#define DisableChA 0x4000
+#define EnableChA 0x8000
+
+#define SetNTSCTV 0x0000 /* TV Info */
+#define SetPALTV 0x0001
+#define SetNTSCJ 0x0002
+#define SetPALMTV 0x0004
+#define SetPALNTV 0x0008
+#define SetCHTVUnderScan 0x0000
+/* #define SetCHTVOverScan 0x0010 */
+#define SetYPbPrMode525i 0x0020
+#define SetYPbPrMode525p 0x0040
+#define SetYPbPrMode750p 0x0080
+#define SetYPbPrMode1080i 0x0100
+#define SetTVStdMode 0x0200
+#define SetTVLowResolution 0x0400
+#define SetTVSimuMode 0x0800
+#define TVSimuMode 0x0800
+#define RPLLDIV2XO 0x1000
+#define NTSC1024x768 0x2000
+#define SetTVLockMode 0x4000
+
+#define LCDVESATiming 0x0001 /* LCD Info/CR37 */
+#define EnableLVDSDDA 0x0002
+#define EnableScalingLCD 0x0008
+#define SetPWDEnable 0x0004
+#define SetLCDtoNonExpanding 0x0010
+#define SetLCDPolarity 0x00e0
+#define SetLCDDualLink 0x0100
+#define SetLCDLowResolution 0x0200
+#define SetLCDStdMode 0x0400
+
+#define DefaultLCDCap 0x80ea /* LCD Capability shampoo */
+#define RLVDSDHL00 0x0000
+#define RLVDSDHL01 0x0001
+#define RLVDSDHL10 0x0002 /* default */
+#define RLVDSDHL11 0x0003
+#define EnableLCD24bpp 0x0004 /* default */
+#define DisableLCD24bpp 0x0000
+#define RLVDSClkSFT0 0x0000
+#define RLVDSClkSFT1 0x0008 /* default */
+#define EnableLVDSDCBal 0x0010
+#define DisableLVDSDCBal 0x0000 /* default */
+#define SinglePolarity 0x0020 /* default */
+#define MultiPolarity 0x0000
+#define LCDPolarity 0x00c0 /* default: SyncNN */
+#define LCDSingleLink 0x0000 /* default */
+#define LCDDualLink 0x0100
+#define EnableSpectrum 0x0200
+#define DisableSpectrum 0x0000 /* default */
+#define PWDEnable 0x0400
+#define PWDDisable 0x0000 /* default */
+#define PWMEnable 0x0800
+#define PWMDisable 0x0000 /* default */
+#define EnableVBCLKDRVLOW 0x4000
+#define EnableVBCLKDRVHigh 0x0000 /* default */
+#define EnablePLLSPLOW 0x8000
+#define EnablePLLSPHigh 0x0000 /* default */
+
+#define LCDBToA 0x20 /* LCD SetFlag */
+#define StLCDBToA 0x40
+#define LockLCDBToA 0x80
+#define LCDToFull 0x10
+#define AVIDEOSense 0x01 /* CR32 */
+#define SVIDEOSense 0x02
+#define SCARTSense 0x04
+#define LCDSense 0x08
+#define Monitor2Sense 0x10
+#define Monitor1Sense 0x20
+#define HiTVSense 0x40
+
+#ifdef NewScratch
+#define YPbPrSense 0x80 /* NEW SCRATCH */
+#endif
+
+#define TVSense 0xc7
+
+#define TVOverScan 0x10 /* CR35 */
+#define TVOverScanShift 4
+
+#ifdef NewScratch
+#define NTSCMode 0x00
+#define PALMode 0x00
+#define NTSCJMode 0x02
+#define PALMNMode 0x0c
+#define YPbPrMode 0xe0
+#define YPbPrMode525i 0x00
+#define YPbPrMode525p 0x20
+#define YPbPrMode750p 0x40
+#define YPbPrMode1080i 0x60
+#else /* Old Scratch */
+#define ClearBufferFlag 0x20
+#endif
+
+
+#define LCDRGB18Bit 0x01 /* CR37 */
+#define LCDNonExpanding 0x10
+#define LCDNonExpandingShift 4
+#define LCDSync 0x20
+#define LCDSyncBit 0xe0 /* H/V polarity & sync ID */
+#define LCDSyncShift 6
+
+#ifdef NewScratch
+#define ScalingLCD 0x08
+#else /* Old Scratch */
+#define ExtChipType 0x0e
+#define ExtChip301 0x02
+#define ExtChipLVDS 0x04
+#define ExtChipCH7019 0x06
+#define ScalingLCD 0x10
+#endif
+
+#define EnableDualEdge 0x01 /* CR38 */
+#define SetToLCDA 0x02
+#ifdef NewScratch
+#define SetYPbPr 0x04
+#define DisableChannelA 0x08
+#define DisableChannelB 0x10
+#define ExtChipType 0xe0
+#define ExtChip301 0x20
+#define ExtChipLVDS 0x40
+#define ExtChipCH7019 0x60
+#else /* Old Scratch */
+#define YPbPrSense 0x04
+#define SetYPbPr 0x08
+#define YPbPrMode 0x30
+#define YPbPrMode525i 0x00
+#define YPbPrMode525p 0x10
+#define YPbPrMode750p 0x20
+#define YPbPrMode1080i 0x30
+#define PALMNMode 0xc0
+#endif
+
+#define BacklightControlBit 0x01 /* CR3A */
+#define Win9xforJap 0x40
+#define Win9xforKorea 0x80
+
+#define ForceMDBits 0x07 /* CR3B */
+#define ForceMD_JDOS 0x00
+#define ForceMD_640x400T 0x01
+#define ForceMD_640x350T 0x02
+#define ForceMD_720x400T 0x03
+#define ForceMD_640x480E 0x04
+#define ForceMD_640x400E 0x05
+#define ForceP1Bit 0x10
+#define ForceP2Bit 0x20
+#define EnableForceMDinBIOS 0x40
+#define EnableForceMDinDrv 0x80
+
+#ifdef NewScratch /* New Scratch */
+/* ---------------------- VUMA Information */
+#define LCDSettingFromCMOS 0x04 /* CR3C */
+#define TVSettingFromCMOS 0x08
+#define DisplayDeviceFromCMOS 0x10
+#define HKSupportInSBIOS 0x20
+#define OSDSupportInSBIOS 0x40
+#define DisableLogo 0x80
+
+/* ---------------------- HK Evnet Definition */
+#define HKEvent 0x0f /* CR3D */
+#define HK_ModeSwitch 0x01
+#define HK_Expanding 0x02
+#define HK_OverScan 0x03
+#define HK_Brightness 0x04
+#define HK_Contrast 0x05
+#define HK_Mute 0x06
+#define HK_Volume 0x07
+#define ModeSwitchStatus 0xf0
+#define ActiveCRT1 0x10
+#define ActiveLCD 0x0020
+#define ActiveTV 0x40
+#define ActiveCRT2 0x80
+
+#define TVSwitchStatus 0x1f /* CR3E */
+#define ActiveAVideo 0x01
+#define ActiveSVideo 0x02
+#define ActiveSCART 0x04
+#define ActiveHiTV 0x08
+#define ActiveYPbPr 0x10
+
+#define EnableHKEvent 0x01 /* CR3F */
+#define EnableOSDEvent 0x02
+#define StartOSDEvent 0x04
+#define IgnoreHKEvent 0x08
+#define IgnoreOSDEvent 0x10
+#else /* Old Scratch */
+#define OSD_SBIOS 0x02 /* SR17 */
+#define DisableLogo 0x04
+#define SelectKDOS 0x08
+#define KorWinMode 0x10
+#define KorMode3Bit 0x0020
+#define PSCCtrlBit 0x40
+#define NPSCCtrlBitShift 6
+#define BlueScreenBit 0x80
+
+#define HKEvent 0x0f /* CR79 */
+#define HK_ModeSwitch 0x01
+#define HK_Expanding 0x02
+#define HK_OverScan 0x03
+#define HK_Brightness 0x04
+#define HK_Contrast 0x05
+#define HK_Mute 0x06
+#define HK_Volume 0x07
+#define ActivePAL 0x0020
+#define ActivePALShift 5
+#define ActiveNonExpanding 0x40
+#define ActiveNonExpandingShift 6
+#define ActiveOverScan 0x80
+#define ActiveOverScanShift 7
+
+#define ModeSwitchStatus 0x0b /* SR15 */
+#define ActiveCRT1 0x01
+#define ActiveLCD 0x02
+#define ActiveCRT2 0x08
+
+#define TVSwitchStatus 0xf0 /* SR16 */
+#define TVConfigShift 3
+#define ActiveTV 0x01
+#define ActiveYPbPr 0x04
+#define ActiveAVideo 0x10
+#define ActiveSVideo 0x0020
+#define ActiveSCART 0x40
+#define ActiveHiTV 0x80
+
+#define EnableHKEvent 0x01 /* CR7A */
+#define EnableOSDEvent 0x02
+#define StartOSDEvent 0x04
+#define CMOSSupport 0x08
+#define HotKeySupport 0x10
+#define IngoreHKOSDEvent 0x20
+#endif
+
+/* //------------- Misc. Definition */
+#define SelectCRT1Rate 00h
+/* #define SelectCRT2Rate 04h */
+
+#define DDC1DelayTime 1000
+#ifdef TRUMPION
+#define DDC2DelayTime 15
+#else
+#define DDC2DelayTime 150
+#endif
+
+#define R_FACTOR 04Dh
+#define G_FACTOR 097h
+#define B_FACTOR 01Ch
+/* --------------------------------------------------------- */
+/* translated from asm code 301def.h */
+/* */
+/* --------------------------------------------------------- */
+#define LCDDataLen 8
+#define HiTVDataLen 12
+#define TVDataLen 12
+#define LVDSCRT1Len_H 8
+#define LVDSCRT1Len_V 7
+#define LVDSDataLen 6
+#define LVDSDesDataLen 6
+#define LCDDesDataLen 6
+#define LVDSDesDataLen2 8
+#define LCDDesDataLen2 8
+#define CHTVRegLen 16
+#define CHLVRegLen 12
+
+#define StHiTVHT 892
+#define StHiTVVT 1126
+#define StHiTextTVHT 1000
+#define StHiTextTVVT 1126
+#define ExtHiTVHT 2100
+#define ExtHiTVVT 1125
+#define NTSCHT 1716
+#define NTSCVT 525
+#define NTSC1024x768HT 1908
+#define NTSC1024x768VT 525
+#define PALHT 1728
+#define PALVT 625
+
+#define YPbPrTV525iHT 1716 /* YPbPr */
+#define YPbPrTV525iVT 525
+#define YPbPrTV525pHT 1716
+#define YPbPrTV525pVT 525
+#define YPbPrTV750pHT 1650
+#define YPbPrTV750pVT 750
+
+#define CRT2VCLKSel 0xc0
+
+#define CRT2Delay1 0x04 /* XGI301 */
+#define CRT2Delay2 0x0A /* 301B,302 */
+
+
+#define VCLK25_175 0x00
+#define VCLK28_322 0x01
+#define VCLK31_5 0x02
+#define VCLK36 0x03
+#define VCLK40 0x04
+#define VCLK43_163 0x05
+#define VCLK44_9 0x06
+#define VCLK49_5 0x07
+#define VCLK50 0x08
+#define VCLK52_406 0x09
+#define VCLK56_25 0x0A
+#define VCLK65 0x0B
+#define VCLK67_765 0x0C
+#define VCLK68_179 0x0D
+#define VCLK72_852 0x0E
+#define VCLK75 0x0F
+#define VCLK75_8 0x10
+#define VCLK78_75 0x11
+#define VCLK79_411 0x12
+#define VCLK83_95 0x13
+#define VCLK84_8 0x14
+#define VCLK86_6 0x15
+#define VCLK94_5 0x16
+#define VCLK104_998 0x17
+#define VCLK105_882 0x18
+#define VCLK108_2 0x19
+#define VCLK109_175 0x1A
+#define VCLK113_309 0x1B
+#define VCLK116_406 0x1C
+#define VCLK132_258 0x1D
+#define VCLK135_5 0x1E
+#define VCLK139_054 0x1F
+#define VCLK157_5 0x20
+#define VCLK162 0x21
+#define VCLK175 0x22
+#define VCLK189 0x23
+#define VCLK194_4 0x24
+#define VCLK202_5 0x25
+#define VCLK229_5 0x26
+#define VCLK234 0x27
+#define VCLK252_699 0x28
+#define VCLK254_817 0x29
+#define VCLK265_728 0x2A
+#define VCLK266_952 0x2B
+#define VCLK269_655 0x2C
+#define VCLK272_042 0x2D
+#define VCLK277_015 0x2E
+#define VCLK286_359 0x2F
+#define VCLK291_132 0x30
+#define VCLK291_766 0x31
+#define VCLK309_789 0x32
+#define VCLK315_195 0x33
+#define VCLK323_586 0x34
+#define VCLK330_615 0x35
+#define VCLK332_177 0x36
+#define VCLK340_477 0x37
+#define VCLK375_847 0x38
+#define VCLK388_631 0x39
+#define VCLK125_999 0x51
+#define VCLK148_5 0x52
+#define VCLK178_992 0x54
+#define VCLK217_325 0x55
+#define VCLK299_505 0x56
+#define YPbPr750pVCLK 0x57
+
+#define TVVCLKDIV2 0x3A
+#define TVVCLK 0x3B
+#define HiTVVCLKDIV2 0x3C
+#define HiTVVCLK 0x3D
+#define HiTVSimuVCLK 0x3E
+#define HiTVTextVCLK 0x3F
+#define VCLK39_77 0x40
+/* #define YPbPr750pVCLK 0x0F */
+#define YPbPr525pVCLK 0x3A
+/* #define ;;YPbPr525iVCLK 0x3B */
+/* #define ;;YPbPr525iVCLK_2 0x3A */
+#define NTSC1024VCLK 0x41
+#define VCLK25_175_41 0x42 /* ; ScaleLCD */
+#define VCLK25_175_42 0x43
+#define VCLK28_322_43 0x44
+#define VCLK40_44 0x45
+#define VCLKQVGA_1 0x46 /* ; QVGA */
+#define VCLKQVGA_2 0x47
+#define VCLKQVGA_3 0x48
+#define VCLK35_2 0x49 /* ; 800x480 */
+#define VCLK122_61 0x4A
+#define VCLK80_350 0x4B
+#define VCLK107_385 0x4C
+
+#define CHTVVCLK30_2 0x50 /* ;;CHTV */
+#define CHTVVCLK28_1 0x51
+#define CHTVVCLK43_6 0x52
+#define CHTVVCLK26_4 0x53
+#define CHTVVCLK24_6 0x54
+#define CHTVVCLK47_8 0x55
+#define CHTVVCLK31_5 0x56
+#define CHTVVCLK26_2 0x57
+#define CHTVVCLK39 0x58
+#define CHTVVCLK36 0x59
+
+#define CH7007TVVCLK30_2 0x00 /* [Billy] 2007/05/18 For CH7007 */
+#define CH7007TVVCLK28_1 0x01
+#define CH7007TVVCLK43_6 0x02
+#define CH7007TVVCLK26_4 0x03
+#define CH7007TVVCLK24_6 0x04
+#define CH7007TVVCLK47_8 0x05
+#define CH7007TVVCLK31_5 0x06
+#define CH7007TVVCLK26_2 0x07
+#define CH7007TVVCLK39 0x08
+#define CH7007TVVCLK36 0x09
+
+#define RES320x200 0x00
+#define RES320x240 0x01
+#define RES400x300 0x02
+#define RES512x384 0x03
+#define RES640x400 0x04
+#define RES640x480x60 0x05
+#define RES640x480x72 0x06
+#define RES640x480x75 0x07
+#define RES640x480x85 0x08
+#define RES640x480x100 0x09
+#define RES640x480x120 0x0A
+#define RES640x480x160 0x0B
+#define RES640x480x200 0x0C
+#define RES800x600x56 0x0D
+#define RES800x600x60 0x0E
+#define RES800x600x72 0x0F
+#define RES800x600x75 0x10
+#define RES800x600x85 0x11
+#define RES800x600x100 0x12
+#define RES800x600x120 0x13
+#define RES800x600x160 0x14
+#define RES1024x768x43 0x15
+#define RES1024x768x60 0x16
+#define RES1024x768x70 0x17
+#define RES1024x768x75 0x18
+#define RES1024x768x85 0x19
+#define RES1024x768x100 0x1A
+#define RES1024x768x120 0x1B
+#define RES1280x1024x43 0x1C
+#define RES1280x1024x60 0x1D
+#define RES1280x1024x75 0x1E
+#define RES1280x1024x85 0x1F
+#define RES1600x1200x60 0x20
+#define RES1600x1200x65 0x21
+#define RES1600x1200x70 0x22
+#define RES1600x1200x75 0x23
+#define RES1600x1200x85 0x24
+#define RES1600x1200x100 0x25
+#define RES1600x1200x120 0x26
+#define RES1920x1440x60 0x27
+#define RES1920x1440x65 0x28
+#define RES1920x1440x70 0x29
+#define RES1920x1440x75 0x2A
+#define RES1920x1440x85 0x2B
+#define RES1920x1440x100 0x2C
+#define RES2048x1536x60 0x2D
+#define RES2048x1536x65 0x2E
+#define RES2048x1536x70 0x2F
+#define RES2048x1536x75 0x30
+#define RES2048x1536x85 0x31
+#define RES800x480x60 0x32
+#define RES800x480x75 0x33
+#define RES800x480x85 0x34
+#define RES1024x576x60 0x35
+#define RES1024x576x75 0x36
+#define RES1024x576x85 0x37
+#define RES1280x720x60 0x38
+#define RES1280x720x75 0x39
+#define RES1280x720x85 0x3A
+#define RES1280x960x60 0x3B
+#define RES720x480x60 0x3C
+#define RES720x576x56 0x3D
+#define RES856x480x79I 0x3E
+#define RES856x480x60 0x3F
+#define RES1280x768x60 0x40
+#define RES1400x1050x60 0x41
+#define RES1152x864x60 0x42
+#define RES1152x864x75 0x43
+#define RES1024x768x160 0x44
+#define RES1280x960x75 0x45
+#define RES1280x960x85 0x46
+#define RES1280x960x120 0x47
+
+#define LFBDRAMTrap 0x30
+#endif
diff --git a/drivers/staging/xgifb/vb_ext.c b/drivers/staging/xgifb/vb_ext.c
new file mode 100644
index 0000000..49b39ee
--- /dev/null
+++ b/drivers/staging/xgifb/vb_ext.c
@@ -0,0 +1,1370 @@
+#include "osdef.h"
+
+
+
+
+#ifdef WIN2000
+
+#include <dderror.h>
+#include <devioctl.h>
+#include <miniport.h>
+#include <ntddvdeo.h>
+#include <video.h>
+#include "xgiv.h"
+#include "dd_i2c.h"
+#include "tools.h"
+#endif /* WIN2000 */
+
+#ifdef LINUX_XF86
+#include "xf86.h"
+#include "xf86PciInfo.h"
+#include "xgi.h"
+#include "xgi_regs.h"
+#endif
+
+#ifdef LINUX_KERNEL
+#include <linux/version.h>
+#include <asm/io.h>
+#include <linux/types.h>
+#include "XGIfb.h"
+/*#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#include <video/XGIfb.h>
+#else
+#include <linux/XGIfb.h>
+#endif*/
+#endif
+
+
+
+#include "vb_def.h"
+#include "vgatypes.h"
+#include "vb_struct.h"
+#include "vb_util.h"
+#include "vb_setmode.h"
+#include "vb_ext.h"
+extern UCHAR XGI330_SoftSetting;
+extern UCHAR XGI330_OutputSelect;
+extern USHORT XGI330_RGBSenseData2;
+extern USHORT XGI330_YCSenseData2;
+extern USHORT XGI330_VideoSenseData2;
+#ifdef WIN2000
+extern UCHAR SenseCHTV(PHW_DEVICE_EXTENSION pHWDE); /* 2007/05/17 Billy */
+#endif
+void XGI_GetSenseStatus( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo );
+BOOLEAN XGINew_GetPanelID(PVB_DEVICE_INFO pVBInfo);
+USHORT XGINew_SenseLCD(PXGI_HW_DEVICE_INFO,PVB_DEVICE_INFO pVBInfo);
+BOOLEAN XGINew_GetLCDDDCInfo(PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
+void XGISetDPMS( PXGI_HW_DEVICE_INFO pXGIHWDE , ULONG VESA_POWER_STATE ) ;
+BOOLEAN XGINew_BridgeIsEnable(PXGI_HW_DEVICE_INFO,PVB_DEVICE_INFO pVBInfo );
+BOOLEAN XGINew_Sense(USHORT tempbx,USHORT tempcx, PVB_DEVICE_INFO pVBInfo);
+BOOLEAN XGINew_SenseHiTV( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ;
+
+/**************************************************************
+ Dynamic Sense
+*************************************************************/
+
+void XGI_WaitDisplay(void);
+BOOLEAN XGI_Is301C(PVB_DEVICE_INFO);
+BOOLEAN XGI_Is301LV(PVB_DEVICE_INFO);
+
+#ifdef WIN2000
+UCHAR XGI_SenseLCD(PHW_DEVICE_EXTENSION, PVB_DEVICE_INFO);
+UCHAR XGI_GetLCDDDCInfo(PHW_DEVICE_EXTENSION,PVB_DEVICE_INFO);
+
+extern BOOL bGetDdcInfo(
+PHW_DEVICE_EXTENSION pHWDE,
+ULONG ulWhichOne,
+PUCHAR pjQueryBuffer,
+ULONG ulBufferSize
+ );
+
+#endif
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_Is301B */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGINew_Is301B( PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT flag ;
+
+ flag = XGINew_GetReg1( pVBInfo->Part4Port , 0x01 ) ;
+
+ if ( flag > 0x0B0 )
+ return( 0 ) ; /* 301b */
+ else
+ return( 1 ) ;
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_Is301C */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_Is301C( PVB_DEVICE_INFO pVBInfo )
+{
+ if ( ( XGINew_GetReg1( pVBInfo->Part4Port , 0x01 ) & 0xF0 ) == 0xC0 )
+ return( 1 ) ;
+
+ if ( XGINew_GetReg1( pVBInfo->Part4Port , 0x01 ) >= 0xD0 )
+ {
+ if ( XGINew_GetReg1( pVBInfo->Part4Port , 0x39 ) == 0xE0 )
+ return( 1 ) ;
+ }
+
+ return( 0 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_Is301LV */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_Is301LV( PVB_DEVICE_INFO pVBInfo )
+{
+ if ( XGINew_GetReg1( pVBInfo->Part4Port , 0x01 ) >= 0xD0 )
+ {
+ if ( XGINew_GetReg1( pVBInfo->Part4Port , 0x39 ) == 0xFF )
+ {
+ return( 1 ) ;
+ }
+ }
+ return( 0 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_Sense */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGINew_Sense( USHORT tempbx , USHORT tempcx, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT temp , i , tempch ;
+
+ temp = tempbx & 0xFF ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x11 , temp ) ;
+ temp = ( tempbx & 0xFF00 ) >> 8 ;
+ temp |= ( tempcx & 0x00FF ) ;
+ XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x10 , ~0x1F , temp ) ;
+
+ for( i = 0 ; i < 10 ; i++ )
+ XGI_LongWait( pVBInfo) ;
+
+ tempch = ( tempcx & 0x7F00 ) >> 8 ;
+ temp = XGINew_GetReg1( pVBInfo->Part4Port , 0x03 ) ;
+ temp = temp ^ ( 0x0E ) ;
+ temp &= tempch ;
+
+ if ( temp > 0 )
+ return( 1 ) ;
+ else
+ return( 0 ) ;
+}
+
+#ifdef WIN2000
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SenseLCD */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+UCHAR XGI_SenseLCD( PHW_DEVICE_EXTENSION pHWDE, PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT tempax , tempbx , tempcx ;
+ UCHAR SoftSetting = XGI330_SoftSetting ;
+
+ if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV ) )
+ return( 1 ) ;
+
+
+ if ( SoftSetting & HotPlugFunction ) /* Hot Plug Detection */
+ {
+ XGINew_SetRegAND( pVBInfo->Part4Port , 0x0F , 0x3F ) ;
+ tempbx = 0 ;
+ tempcx = 0x9010 ;
+ if ( XGINew_Sense( tempbx , tempcx, pVBInfo ) )
+ return( 1 ) ;
+
+ return( 0 ) ;
+ }
+ else /* Get LCD Info from EDID */
+ return(XGI_GetLCDDDCInfo(pHWDE, pVBInfo));
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetLCDDDCInfo */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+UCHAR XGI_GetLCDDDCInfo( PHW_DEVICE_EXTENSION pHWDE , PVB_DEVICE_INFO pVBInfo)
+{
+ UCHAR tempah , tempbl , tempbh ;
+ USHORT tempbx , temp ;
+ UCHAR pjEDIDBuf[ 256 ] ;
+ ULONG ulBufferSize = 256 ;
+ UCHAR bMASK_OUTPUTSTATE_CRT2LCD = 2 ; /* 0423 shampoo */
+
+ bGetDdcInfo( pHWDE , MASK_OUTPUTSTATE_CRT2LCD , pjEDIDBuf , ulBufferSize ) ;
+ if ( ( *( ( PULONG )pjEDIDBuf ) == 0xFFFFFF00 ) && ( *( ( PULONG )( pjEDIDBuf + 4 ) ) == 0x00FFFFFF ) )
+ {
+ tempah = Panel1024x768 ;
+ tempbl=( *( pjEDIDBuf + 0x3A ) ) & 0xf0 ;
+
+ if ( tempbl != 0x40 )
+ {
+ tempah = Panel1600x1200 ;
+ if ( tempbl != 0x60 )
+ {
+ tempah = Panel1280x1024 ;
+ tempbh = ( *( pjEDIDBuf + 0x3B ) ) ;
+ if ( tempbh != 0x00 )
+ {
+ tempah = Panel1280x960 ;
+ if ( tempbh != 0x0C0 )
+ {
+ tempbx = ( ( *( pjEDIDBuf + 0x24 ) ) << 8 ) | ( *( pjEDIDBuf + 0x23 ) ) ;
+ tempah = Panel1280x1024 ;
+ if ( !( tempbx & 0x0100 ) )
+ {
+ tempah = Panel1024x768 ;
+ if ( !( tempbx & 0x0E00 ) )
+ {
+ tempah = Panel1280x1024 ;
+ }
+ }
+ }
+
+ if ( tempbx & 0x00FF )
+ {
+ temp = ScalingLCD ;
+ XGINew_SetRegOR( pVBInfo->P3d4 , 0x37 , temp ) ;
+ }
+ }
+ }
+ }
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x36 , ( ~0x07 ) , tempah ) ;
+ tempah = ( ( *( pjEDIDBuf + 0x47 ) ) & 0x06 ) ; /* Polarity */
+ tempah = ( tempah ^ 0x06 ) << 4 ;
+ tempah |= LCDSync ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x37 , ( ~LCDSyncBit ) , tempah ) ;
+ tempbh= XGINew_GetReg1( pVBInfo->P3d4 , 0x36 ) ;
+ tempbh &= 0x07 ;
+ if ( tempbh == Panel1280x960 )
+ XGINew_SetRegAND( pVBInfo->P3d4 , 0x37 , 0x0E ) ;
+ }
+ else if ( *pjEDIDBuf == 0x20 )
+ {
+ tempah = Panel1024x768 ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x36 , ( ~0x07 ) , tempah ) ;
+ }
+ else
+ {
+ return( 0 ) ;
+ }
+
+ return( 1 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_DySense */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_DySense( PHW_DEVICE_EXTENSION pHWDE , PUCHAR ujConnectStatus)
+{
+ UCHAR pre_CRD,pre_SR1E , pre_Part2_0 , pre_Part4_D ;
+ USHORT tempax , tempbx , tempcx , pushax , temp ;
+ VB_DEVICE_INFO VBINF;
+ PVB_DEVICE_INFO pVBInfo = &VBINF;
+ UCHAR OutputSelect = XGI330_OutputSelect ;
+ PXGI_HW_DEVICE_INFO HwDeviceExtension= pHWDE->pXGIHWDE ;
+ UCHAR bConnectStatus = 0 ;
+ pVBInfo->BaseAddr = HwDeviceExtension->pjIOAddress ;
+ pVBInfo->ROMAddr = pHWDE->pjVirtualRomBase ;
+
+ pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
+ pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
+ pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
+ pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
+ pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
+ pushax = XGINew_GetReg1( pVBInfo->P3d4 , 0x17 ) ; /* 0512 Fix Dysense hanged */
+ temp = ( pushax & 0x00FF ) | 0x80 ;
+ XGINew_SetRegOR( pVBInfo->P3d4 , 0x17 , temp ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x05 , 0x86 ) ;
+ /* beginning of dynamic sense CRT1 */
+
+ pVBInfo->IF_DEF_CH7007 = 0;
+ if (pHWDE->bCH7007)
+ {
+ InitTo330Pointer( pHWDE->pXGIHWDE->jChipType, pVBInfo ) ;
+ HwDeviceExtension->pDevice = (PVOID)pHWDE;
+ pVBInfo->IF_DEF_CH7007 = 1;
+ /* [Billy] 2007/05/14 For CH7007 */
+ if ( pVBInfo->IF_DEF_CH7007 == 1 )
+ {
+ bConnectStatus = SenseCHTV(HwDeviceExtension->pDevice) ; /* 07/05/28 */
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , ~0x03 , (UCHAR)bConnectStatus ) ;
+ }
+ }
+ if(( pHWDE->jChipID >= XG40 ) || ( pHWDE->jChipID >= XG20 ))
+ {
+
+ if ( pHWDE->jChipID >= XG40 )
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x57 , 0x4A ) ; /* write sense pattern 30->4a */
+ else
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x57 , 0x5F ) ; /* write sense pattern */
+
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x53 , 0xFF , 0x02 ) ; /* enable sense DAC */
+ XGI_WaitDisply(pVBInfo) ;
+
+ if(XGINew_GetReg2( pVBInfo->P3c2 ) & 0x10 )
+ bConnectStatus |= Monitor1Sense ;
+
+ XGINew_SetRegAND( pVBInfo->P3d4 , 0x53 , 0xFD ) ; /* disable sense DAC */
+ XGINew_SetRegAND( pVBInfo->P3d4 , 0x57 , 0x00 ) ; /* clear sense pattern */
+
+
+ /* ---------- End of dynamic sense CRT1 ----------- */
+
+ /* ---------- beginning of dynamic sense VB ------------ */
+ pre_SR1E = XGINew_GetReg1( pVBInfo->P3c4 , 0x1E ) ;
+ XGINew_SetRegOR( pVBInfo->P3c4 , 0x1E , 0x20 ) ; /* Enable CRT2,work-a-round for 301B/301LV/302LV */
+ pre_Part2_0 = XGINew_GetReg1( pVBInfo->Part2Port , 0x00 ) ;
+ pre_Part4_D = XGINew_GetReg1( pVBInfo->Part4Port , 0x0D ) ;
+
+ if ( XGI_Is301C( pVBInfo ) ) /* 301C only */
+ XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x0D , ~0x07 , 0x01 ) ; /* Set Part4 0x0D D[2:0] to 001b */
+
+ /* tempax = 0 ; */
+ if ( !XGI_Is301LV( pVBInfo ) )
+ {
+ tempbx = XGI330_RGBSenseData2 ;
+ tempcx = 0x0E08 ;
+ if(XGINew_Sense( tempbx , tempcx, pVBInfo ) )
+ {
+ bConnectStatus |= Monitor2Sense ;
+ if ( OutputSelect & SetSCARTOutput )
+ {
+ bConnectStatus ^= ( Monitor2Sense | SCARTSense ) ;
+ }
+ }
+ }
+ if ( XGI_Is301C( pVBInfo ) ) /* 301C only */
+ XGINew_SetRegOR( pVBInfo->Part4Port , 0x0D , 0x04 ) ; /* Set Part4 0x0D D[2]=1 for dynamic sense */
+
+ if ( ( XGINew_Is301B( pVBInfo ) ) )
+ XGINew_SetRegOR( pVBInfo->Part2Port , 0x00 , 0x0C ) ; /* ????????? */
+
+ if ( XGINew_SenseHiTV( HwDeviceExtension , pVBInfo) ) /* add by kuku for Dysense HiTV //start */
+ {
+ bConnectStatus|= YPbPrSense ;
+ }
+ else
+ {
+ tempbx = XGI330_YCSenseData2 ; /* Y/C Sense Data Ptr */
+ tempcx = 0x0604 ;
+ if ( XGINew_Sense( tempbx , tempcx , pVBInfo) )
+ bConnectStatus |= SVIDEOSense ;
+
+ if ( OutputSelect & BoardTVType )
+ {
+ tempbx = XGI330_VideoSenseData2 ;
+ tempcx = 0x0804 ;
+ if ( XGINew_Sense(tempbx , tempcx, pVBInfo) )
+ bConnectStatus|= AVIDEOSense ;
+ }
+ else
+ {
+ if ( !( bConnectStatus & SVIDEOSense ) )
+ {
+ tempbx = XGI330_VideoSenseData2 ;
+ tempcx = 0x0804 ;
+ if ( XGINew_Sense( tempbx , tempcx, pVBInfo ) )
+ bConnectStatus |= AVIDEOSense ;
+ }
+ }
+ } /* end */
+ /* DySenseVBCnt */
+
+ tempbx = 0 ;
+ tempcx = 0 ;
+ XGINew_Sense(tempbx , tempcx, pVBInfo ) ;
+
+ if ( !( bConnectStatus & Monitor2Sense ) )
+ {
+ if ( XGI_SenseLCD( pHWDE , pVBInfo ) )
+ bConnectStatus |= LCDSense ;
+ }
+
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , ~( AVIDEOSense | SVIDEOSense | LCDSense | Monitor2Sense | Monitor1Sense ) , bConnectStatus ) ;
+
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x0D , pre_Part4_D ) ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x00 , pre_Part2_0 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x1E , pre_SR1E ) ;
+
+ if ( XGI_Is301C( pVBInfo ) ) /* 301C only */
+ {
+ tempax = XGINew_GetReg1( pVBInfo->Part2Port , 0x00 ) ;
+ if ( tempax & 0x20 )
+ {
+ /* Reset VBPro */
+ for( tempcx = 2 ; tempcx > 0 ; tempcx-- )
+ {
+ tempax ^= 0x20 ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x00 , tempax ) ;
+ }
+ }
+ }
+ /* End of dynamic sense VB */
+ }
+ else
+ {
+ XGI_SenseCRT1(pVBInfo) ;
+ XGI_GetSenseStatus( HwDeviceExtension, pVBInfo ) ; /* sense CRT2 */
+ bConnectStatus = XGINew_GetReg1( pVBInfo->P3d4 , 0x32 ) ;
+ }
+ temp = pushax & 0x00FF ; /* 0512 Fix Dysense hanged */
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x17 , temp ) ;
+ if ( bConnectStatus )
+ {
+ *ujConnectStatus = bConnectStatus ;
+ return( 1 ) ;
+ }
+ else
+ return( 0 ) ;
+}
+
+#endif /* WIN2000 */
+
+/* --------------------------------------------------------------------- */
+/* Function : XGISetDPMS */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+VOID XGISetDPMS( PXGI_HW_DEVICE_INFO pXGIHWDE , ULONG VESA_POWER_STATE )
+{
+ USHORT ModeNo, ModeIdIndex ;
+ UCHAR temp ;
+ VB_DEVICE_INFO VBINF;
+ PVB_DEVICE_INFO pVBInfo = &VBINF;
+ pVBInfo->BaseAddr = (ULONG)pXGIHWDE->pjIOAddress ;
+ pVBInfo->ROMAddr = pXGIHWDE->pjVirtualRomBase ;
+
+
+ pVBInfo->IF_DEF_LVDS = 0 ;
+ pVBInfo->IF_DEF_CH7005 = 0 ;
+ pVBInfo->IF_DEF_HiVision = 1 ;
+ pVBInfo->IF_DEF_LCDA = 1 ;
+ pVBInfo->IF_DEF_CH7017 = 0 ;
+ pVBInfo->IF_DEF_YPbPr = 1 ;
+ pVBInfo->IF_DEF_CRT2Monitor = 0 ;
+ pVBInfo->IF_DEF_VideoCapture = 0 ;
+ pVBInfo->IF_DEF_ScaleLCD = 0 ;
+ pVBInfo->IF_DEF_OEMUtil = 0 ;
+ pVBInfo->IF_DEF_PWD = 0 ;
+
+ InitTo330Pointer( pXGIHWDE->jChipType, pVBInfo ) ;
+ ReadVBIOSTablData( pXGIHWDE->jChipType , pVBInfo) ;
+
+ pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
+ pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
+ pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
+ pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
+ pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
+ pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
+ pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
+ pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
+ pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
+ pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
+ pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
+ pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
+ pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
+ pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
+ pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
+ pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
+ pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
+
+ if ( pXGIHWDE->jChipType == XG27 )
+ {
+ if ( ( XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) & 0xE0 ) == 0xC0 )
+ {
+ if ( XGINew_GetReg1( pVBInfo->P3d4 , 0x30 ) & 0x20 )
+ {
+ pVBInfo->IF_DEF_LVDS = 1 ;
+ }
+ }
+ }
+
+ if ( pVBInfo->IF_DEF_CH7007 == 0 )
+ {
+ XGINew_SetModeScratch ( pXGIHWDE , pVBInfo ) ;
+ }
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x05 , 0x86 ) ; /* 1.Openkey */
+ XGI_UnLockCRT2( pXGIHWDE , pVBInfo) ;
+ ModeNo = XGINew_GetReg1( pVBInfo->P3d4 , 0x34 ) ;
+ XGI_SearchModeID( ModeNo , &ModeIdIndex, pVBInfo ) ;
+ XGI_GetVGAType( pXGIHWDE , pVBInfo ) ;
+
+ if ( ( pXGIHWDE->ujVBChipID == VB_CHIP_301 ) || ( pXGIHWDE->ujVBChipID == VB_CHIP_302 ) || ( pVBInfo->IF_DEF_CH7007 == 1 ))
+ {
+ XGI_GetVBType( pVBInfo ) ;
+ XGI_GetVBInfo( ModeNo , ModeIdIndex , pXGIHWDE, pVBInfo ) ;
+ XGI_GetTVInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
+ XGI_GetLCDInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
+ }
+
+ if ( VESA_POWER_STATE == 0x00000400 )
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x31 , ( UCHAR )( XGINew_GetReg1( pVBInfo->Part4Port , 0x31 ) & 0xFE ) ) ;
+ else
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x31 , ( UCHAR )( XGINew_GetReg1( pVBInfo->Part4Port , 0x31 ) | 0x01 ) ) ;
+
+ temp = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x1f ) ;
+ temp &= 0x3f ;
+ switch ( VESA_POWER_STATE )
+ {
+ case 0x00000000: /* on */
+ if ( ( pXGIHWDE->ujVBChipID == VB_CHIP_301 ) || ( pXGIHWDE->ujVBChipID == VB_CHIP_302 ) )
+ {
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x1f , ( UCHAR )( temp | 0x00 ) ) ;
+ XGI_EnableBridge( pXGIHWDE, pVBInfo ) ;
+ }
+ else
+ {
+ if ( pXGIHWDE->jChipType == XG21 )
+ {
+ if ( pVBInfo->IF_DEF_LVDS == 1 )
+ {
+ XGI_XG21BLSignalVDD( 0x01 , 0x01, pVBInfo ) ; /* LVDS VDD on */
+ XGI_XG21SetPanelDelay( 2,pVBInfo ) ;
+ }
+ }
+ if ( pXGIHWDE->jChipType == XG27 )
+ {
+ if ( pVBInfo->IF_DEF_LVDS == 1 )
+ {
+ XGI_XG27BLSignalVDD( 0x01 , 0x01, pVBInfo ) ; /* LVDS VDD on */
+ XGI_XG21SetPanelDelay( 2,pVBInfo ) ;
+ }
+ }
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x1F , ~0xC0 , 0x00 ) ;
+ XGINew_SetRegAND( pVBInfo->P3c4 , 0x01 , ~0x20 ) ; /* CRT on */
+
+ if ( pXGIHWDE->jChipType == XG21 )
+ {
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ;
+ if ( temp & 0xE0 )
+ {
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x09 , ~0x80 , 0x80 ) ; /* DVO ON */
+ XGI_SetXG21FPBits( pVBInfo );
+ XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x20 ) ; /* Enable write GPIOF */
+ /*XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x48 , ~0x20 , 0x20 ) ;*/ /* LCD Display ON */
+ }
+ XGI_XG21BLSignalVDD( 0x20 , 0x20, pVBInfo ) ; /* LVDS signal on */
+ XGI_DisplayOn( pXGIHWDE, pVBInfo );
+ }
+ if ( pXGIHWDE->jChipType == XG27 )
+ {
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ;
+ if ( temp & 0xE0 )
+ {
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x09 , ~0x80 , 0x80 ) ; /* DVO ON */
+ XGI_SetXG27FPBits( pVBInfo );
+ XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x20 ) ; /* Enable write GPIOF */
+ /*XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x48 , ~0x20 , 0x20 ) ;*/ /* LCD Display ON */
+ }
+ XGI_XG27BLSignalVDD( 0x20 , 0x20, pVBInfo ) ; /* LVDS signal on */
+ XGI_DisplayOn( pXGIHWDE, pVBInfo );
+ }
+ }
+ break ;
+ case 0x00000100: /* standby */
+ if ( pXGIHWDE->jChipType >= XG21 )
+ {
+ XGI_DisplayOff( pXGIHWDE, pVBInfo );
+ }
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x1f , ( UCHAR )( temp | 0x40 ) ) ;
+ break ;
+ case 0x00000200: /* suspend */
+ if ( pXGIHWDE->jChipType == XG21 )
+ {
+ XGI_DisplayOff( pXGIHWDE, pVBInfo );
+ XGI_XG21BLSignalVDD( 0x20 , 0x00, pVBInfo ) ; /* LVDS signal off */
+ }
+ if ( pXGIHWDE->jChipType == XG27 )
+ {
+ XGI_DisplayOff( pXGIHWDE, pVBInfo );
+ XGI_XG27BLSignalVDD( 0x20 , 0x00, pVBInfo ) ; /* LVDS signal off */
+ }
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x1f , ( UCHAR )( temp | 0x80 ) ) ;
+ break ;
+ case 0x00000400: /* off */
+ if ( (pXGIHWDE->ujVBChipID == VB_CHIP_301 ) || ( pXGIHWDE->ujVBChipID == VB_CHIP_302 ) )
+ {
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x1f , ( UCHAR )( temp | 0xc0 ) ) ;
+ XGI_DisableBridge( pXGIHWDE, pVBInfo ) ;
+ }
+ else
+ {
+ if ( pXGIHWDE->jChipType == XG21 )
+ {
+ XGI_DisplayOff( pXGIHWDE, pVBInfo );
+
+ XGI_XG21BLSignalVDD( 0x20 , 0x00, pVBInfo ) ; /* LVDS signal off */
+
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ;
+ if ( temp & 0xE0 )
+ {
+ XGINew_SetRegAND( pVBInfo->P3c4 , 0x09 , ~0x80 ) ; /* DVO Off */
+ XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x20 ) ; /* Enable write GPIOF */
+ /*XGINew_SetRegAND( pVBInfo->P3d4 , 0x48 , ~0x20 ) ;*/ /* LCD Display OFF */
+ }
+ }
+ if ( pXGIHWDE->jChipType == XG27 )
+ {
+ XGI_DisplayOff( pXGIHWDE, pVBInfo );
+
+ XGI_XG27BLSignalVDD( 0x20 , 0x00, pVBInfo ) ; /* LVDS signal off */
+
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ;
+ if ( temp & 0xE0 )
+ {
+ XGINew_SetRegAND( pVBInfo->P3c4 , 0x09 , ~0x80 ) ; /* DVO Off */
+ }
+ }
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x1F , ~0xC0 , 0xC0 ) ;
+ XGINew_SetRegOR( pVBInfo->P3c4 , 0x01 , 0x20 ) ; /* CRT Off */
+
+ if ( ( pXGIHWDE->jChipType == XG21 ) && ( pVBInfo->IF_DEF_LVDS == 1 ) )
+ {
+ XGI_XG21SetPanelDelay( 4,pVBInfo ) ;
+ XGI_XG21BLSignalVDD( 0x01 , 0x00, pVBInfo ) ; /* LVDS VDD off */
+ XGI_XG21SetPanelDelay( 5,pVBInfo ) ;
+ }
+ if ( ( pXGIHWDE->jChipType == XG27 ) && ( pVBInfo->IF_DEF_LVDS == 1 ) )
+ {
+ XGI_XG21SetPanelDelay( 4,pVBInfo ) ;
+ XGI_XG27BLSignalVDD( 0x01 , 0x00, pVBInfo ) ; /* LVDS VDD off */
+ XGI_XG21SetPanelDelay( 5,pVBInfo ) ;
+ }
+ }
+ break ;
+
+ default:
+ break ;
+ }
+ XGI_LockCRT2( pXGIHWDE , pVBInfo ) ;
+}
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetSenseStatus */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetSenseStatus( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT tempax = 0 , tempbx , tempcx , temp ,
+ P2reg0 = 0 , SenseModeNo = 0 , OutputSelect = *pVBInfo->pOutputSelect ,
+ ModeIdIndex , i ;
+ pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
+
+ if ( pVBInfo->IF_DEF_LVDS == 1 )
+ {
+ tempax = XGINew_GetReg1( pVBInfo->P3c4 , 0x1A ) ; /* ynlai 02/27/2002 */
+ tempbx = XGINew_GetReg1( pVBInfo->P3c4 , 0x1B ) ;
+ tempax = ( ( tempax & 0xFE ) >> 1 ) | ( tempbx << 8 ) ;
+ if ( tempax == 0x00 )
+ { /* Get Panel id from DDC */
+ temp = XGINew_GetLCDDDCInfo( HwDeviceExtension, pVBInfo ) ;
+ if ( temp == 1 )
+ { /* LCD connect */
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x39 , 0xFF , 0x01 ) ; /* set CR39 bit0="1" */
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x37 , 0xEF , 0x00 ) ; /* clean CR37 bit4="0" */
+ temp = LCDSense ;
+ }
+ else
+ { /* LCD don't connect */
+ temp = 0 ;
+ }
+ }
+ else
+ {
+ XGINew_GetPanelID(pVBInfo) ;
+ temp = LCDSense ;
+ }
+
+ tempbx = ~( LCDSense | AVIDEOSense | SVIDEOSense ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , tempbx , temp ) ;
+ }
+ else
+ { /* for 301 */
+ if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+ { /* for HiVision */
+ tempax = XGINew_GetReg1( pVBInfo->P3c4 , 0x38 ) ;
+ temp = tempax & 0x01 ;
+ tempax = XGINew_GetReg1( pVBInfo->P3c4 , 0x3A ) ;
+ temp = temp | ( tempax & 0x02 ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , 0xA0 , temp ) ;
+ }
+ else
+ {
+ if ( XGI_BridgeIsOn( pVBInfo ) )
+ {
+ P2reg0 = XGINew_GetReg1( pVBInfo->Part2Port , 0x00 ) ;
+ if ( !XGINew_BridgeIsEnable( HwDeviceExtension, pVBInfo ) )
+ {
+ SenseModeNo = 0x2e ;
+ /* XGINew_SetReg1( pVBInfo->P3d4 , 0x30 , 0x41 ) ; */
+ /* XGISetModeNew( HwDeviceExtension , 0x2e ) ; // ynlai InitMode */
+
+ temp = XGI_SearchModeID( SenseModeNo , &ModeIdIndex, pVBInfo ) ;
+ XGI_GetVGAType( HwDeviceExtension , pVBInfo) ;
+ XGI_GetVBType( pVBInfo ) ;
+ pVBInfo->SetFlag = 0x00 ;
+ pVBInfo->ModeType = ModeVGA ;
+ pVBInfo->VBInfo = SetCRT2ToRAMDAC | LoadDACFlag | SetInSlaveMode ;
+ XGI_GetLCDInfo( 0x2e , ModeIdIndex, pVBInfo ) ;
+ XGI_GetTVInfo( 0x2e , ModeIdIndex, pVBInfo ) ;
+ XGI_EnableBridge( HwDeviceExtension, pVBInfo ) ;
+ XGI_SetCRT2Group301( SenseModeNo , HwDeviceExtension, pVBInfo ) ;
+ XGI_SetCRT2ModeRegs( 0x2e , HwDeviceExtension, pVBInfo ) ;
+ /* XGI_DisableBridge( HwDeviceExtension, pVBInfo ) ; */
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x01 , 0xDF , 0x20 ) ; /* Display Off 0212 */
+ for( i = 0 ; i < 20 ; i++ )
+ {
+ XGI_LongWait(pVBInfo) ;
+ }
+ }
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x00 , 0x1c ) ;
+ tempax = 0 ;
+ tempbx = *pVBInfo->pRGBSenseData ;
+
+ if ( !( XGINew_Is301B( pVBInfo ) ) )
+ {
+ tempbx = *pVBInfo->pRGBSenseData2 ;
+ }
+
+ tempcx = 0x0E08 ;
+ if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) )
+ {
+ if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) )
+ {
+ tempax |= Monitor2Sense ;
+ }
+ }
+
+ if ( pVBInfo->VBType & VB_XGI301C)
+ {
+ XGINew_SetRegOR( pVBInfo->Part4Port , 0x0d , 0x04 ) ;
+ }
+
+ if ( XGINew_SenseHiTV( HwDeviceExtension , pVBInfo) ) /* add by kuku for Multi-adapter sense HiTV */
+ {
+ tempax |= HiTVSense ;
+ if ( ( pVBInfo->VBType & VB_XGI301C ) )
+ {
+ tempax ^= ( HiTVSense | YPbPrSense ) ;
+ }
+ }
+
+ if ( !( tempax & ( HiTVSense | YPbPrSense ) ) ) /* start */
+ {
+
+ tempbx = *pVBInfo->pYCSenseData ;
+
+ if ( !( XGINew_Is301B( pVBInfo ) ) )
+ {
+ tempbx=*pVBInfo->pYCSenseData2;
+ }
+
+ tempcx = 0x0604 ;
+ if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) )
+ {
+ if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) )
+ {
+ tempax |= SVIDEOSense ;
+ }
+ }
+
+ if ( OutputSelect & BoardTVType )
+ {
+ tempbx = *pVBInfo->pVideoSenseData ;
+
+ if ( !( XGINew_Is301B( pVBInfo ) ) )
+ {
+ tempbx = *pVBInfo->pVideoSenseData2 ;
+ }
+
+ tempcx = 0x0804 ;
+ if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) )
+ {
+ if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) )
+ {
+ tempax |= AVIDEOSense ;
+ }
+ }
+ }
+ else
+ {
+ if ( !( tempax & SVIDEOSense ) )
+ {
+ tempbx = *pVBInfo->pVideoSenseData ;
+
+ if ( !( XGINew_Is301B( pVBInfo ) ) )
+ {
+ tempbx=*pVBInfo->pVideoSenseData2;
+ }
+
+ tempcx = 0x0804 ;
+ if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) )
+ {
+ if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) )
+ {
+ tempax |= AVIDEOSense ;
+ }
+ }
+ }
+ }
+ }
+ } /* end */
+ if ( !( tempax & Monitor2Sense ) )
+ {
+ if ( XGINew_SenseLCD( HwDeviceExtension, pVBInfo ) )
+ {
+ tempax |= LCDSense ;
+ }
+ }
+ tempbx = 0 ;
+ tempcx = 0 ;
+ XGINew_Sense(tempbx , tempcx, pVBInfo ) ;
+
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , ~0xDF , tempax ) ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x00 , P2reg0 ) ;
+
+ if ( !( P2reg0 & 0x20 ) )
+ {
+ pVBInfo->VBInfo = DisableCRT2Display ;
+ /* XGI_SetCRT2Group301( SenseModeNo , HwDeviceExtension, pVBInfo ) ; */
+ }
+ }
+ }
+ XGI_DisableBridge( HwDeviceExtension, pVBInfo ) ; /* shampoo 0226 */
+
+}
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SenseLCD */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+USHORT XGINew_SenseLCD( PXGI_HW_DEVICE_INFO HwDeviceExtension ,PVB_DEVICE_INFO pVBInfo)
+{
+ /* USHORT SoftSetting ; */
+ USHORT temp ;
+
+ if ( ( HwDeviceExtension->jChipType >= XG20 ) || ( HwDeviceExtension->jChipType >= XG40 ) )
+ temp = 0 ;
+ else
+ temp=XGINew_GetPanelID(pVBInfo) ;
+
+ if( !temp )
+ temp = XGINew_GetLCDDDCInfo( HwDeviceExtension, pVBInfo ) ;
+
+ return( temp ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_GetLCDDDCInfo */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGINew_GetLCDDDCInfo( PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT temp ;
+
+ /* add lcd sense */
+ if ( HwDeviceExtension->ulCRT2LCDType == LCD_UNKNOWN )
+ {
+ return( 0 ) ;
+ }
+ else
+ {
+ temp = ( USHORT )HwDeviceExtension->ulCRT2LCDType ;
+ switch( HwDeviceExtension->ulCRT2LCDType )
+ {
+ case LCD_INVALID:
+ case LCD_800x600:
+ case LCD_1024x768:
+ case LCD_1280x1024:
+ break ;
+
+ case LCD_640x480:
+ case LCD_1024x600:
+ case LCD_1152x864:
+ case LCD_1280x960:
+ case LCD_1152x768:
+ temp = 0 ;
+ break ;
+
+ case LCD_1400x1050:
+ case LCD_1280x768:
+ case LCD_1600x1200:
+ break ;
+
+ case LCD_1920x1440:
+ case LCD_2048x1536:
+ temp = 0 ;
+ break ;
+
+ default:
+ break ;
+ }
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x36 , 0xF0 , temp ) ;
+ return( 1 ) ;
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGINew_GetPanelID(PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT PanelTypeTable[ 16 ] = { SyncNN | PanelRGB18Bit | Panel800x600 | _PanelType00 ,
+ SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType01 ,
+ SyncNN | PanelRGB18Bit | Panel800x600 | _PanelType02 ,
+ SyncNN | PanelRGB18Bit | Panel640x480 | _PanelType03 ,
+ SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType04 ,
+ SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType05 ,
+ SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType06 ,
+ SyncNN | PanelRGB24Bit | Panel1024x768 | _PanelType07 ,
+ SyncNN | PanelRGB18Bit | Panel800x600 | _PanelType08 ,
+ SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType09 ,
+ SyncNN | PanelRGB18Bit | Panel800x600 | _PanelType0A ,
+ SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0B ,
+ SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0C ,
+ SyncNN | PanelRGB24Bit | Panel1024x768 | _PanelType0D ,
+ SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0E ,
+ SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0F } ;
+ USHORT tempax , tempbx , temp ;
+ /* USHORT return_flag ; */
+
+ tempax = XGINew_GetReg1( pVBInfo->P3c4 , 0x1A ) ;
+ tempbx = tempax & 0x1E ;
+
+ if ( tempax == 0 )
+ return( 0 ) ;
+ else
+ {
+/*
+ if ( !( tempax & 0x10 ) )
+ {
+ if ( pVBInfo->IF_DEF_LVDS == 1 )
+ {
+ tempbx = 0 ;
+ temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x38 ) ;
+ if ( temp & 0x40 )
+ tempbx |= 0x08 ;
+ if ( temp & 0x20 )
+ tempbx |= 0x02 ;
+ if ( temp & 0x01 )
+ tempbx |= 0x01 ;
+
+ temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x39 ) ;
+ if ( temp & 0x80 )
+ tempbx |= 0x04 ;
+ }
+ else
+ {
+ return( 0 ) ;
+ }
+ }
+*/
+
+ tempbx = tempbx >> 1 ;
+ temp = tempbx & 0x00F ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x36 , temp ) ;
+ tempbx-- ;
+ tempbx = PanelTypeTable[ tempbx ] ;
+
+ temp = ( tempbx & 0xFF00 ) >> 8 ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x37 , ~( LCDSyncBit | LCDRGB18Bit ) , temp ) ;
+ return( 1 ) ;
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_BridgeIsEnable */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGINew_BridgeIsEnable( PXGI_HW_DEVICE_INFO HwDeviceExtension ,PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT flag ;
+
+ if ( XGI_BridgeIsOn( pVBInfo ) == 0 )
+ {
+ flag = XGINew_GetReg1( pVBInfo->Part1Port , 0x0 ) ;
+
+ if ( flag & 0x050 )
+ {
+ return( 1 ) ;
+ }
+ else
+ {
+ return( 0 ) ;
+ }
+
+ }
+ return( 0 ) ;
+}
+
+/* ------------------------------------------------------ */
+/* Function : XGINew_SenseHiTV */
+/* Input : */
+/* Output : */
+/* Description : */
+/* ------------------------------------------------------ */
+BOOLEAN XGINew_SenseHiTV( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT tempbx , tempcx , temp , i , tempch;
+
+ tempbx = *pVBInfo->pYCSenseData2 ;
+
+ tempcx = 0x0604 ;
+
+ temp = tempbx & 0xFF ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x11 , temp ) ;
+ temp = ( tempbx & 0xFF00 ) >> 8 ;
+ temp |= ( tempcx & 0x00FF ) ;
+ XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x10 , ~0x1F , temp ) ;
+
+ for( i = 0 ; i < 10 ; i++ )
+ XGI_LongWait(pVBInfo) ;
+
+ tempch = ( tempcx & 0xFF00 ) >> 8;
+ temp = XGINew_GetReg1( pVBInfo->Part4Port , 0x03 ) ;
+ temp = temp ^ ( 0x0E ) ;
+ temp &= tempch ;
+
+ if ( temp != tempch )
+ return( 0 ) ;
+
+ tempbx = *pVBInfo->pVideoSenseData2 ;
+
+ tempcx = 0x0804 ;
+ temp = tempbx & 0xFF ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x11 , temp ) ;
+ temp = ( tempbx & 0xFF00 ) >> 8 ;
+ temp |= ( tempcx & 0x00FF ) ;
+ XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x10 , ~0x1F , temp ) ;
+
+ for( i = 0 ; i < 10 ; i++ )
+ XGI_LongWait(pVBInfo) ;
+
+ tempch = ( tempcx & 0xFF00 ) >> 8;
+ temp = XGINew_GetReg1( pVBInfo->Part4Port , 0x03 ) ;
+ temp = temp ^ ( 0x0E ) ;
+ temp &= tempch ;
+
+ if ( temp != tempch )
+ return( 0 ) ;
+ else
+ {
+ tempbx = 0x3FF ;
+ tempcx = 0x0804 ;
+ temp = tempbx & 0xFF ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x11 , temp ) ;
+ temp = ( tempbx & 0xFF00 ) >> 8 ;
+ temp |= ( tempcx & 0x00FF ) ;
+ XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x10 , ~0x1F , temp ) ;
+
+ for( i = 0 ; i < 10 ; i++ )
+ XGI_LongWait(pVBInfo) ;
+
+ tempch = ( tempcx & 0xFF00 ) >> 8;
+ temp = XGINew_GetReg1( pVBInfo->Part4Port , 0x03 ) ;
+ temp = temp ^ ( 0x0E ) ;
+ temp &= tempch ;
+
+ if ( temp != tempch )
+ return( 1 ) ;
+ else
+ return( 0 ) ;
+ }
+}
+
+
+
+/*
+;-----------------------------------------------------------------------------
+; Description: Get Panel support
+; O/P :
+; BL: Panel ID=81h for no scaler LVDS
+; BH: Panel enhanced Mode Count
+; CX: Panel H. resolution
+; DX: PAnel V. resolution
+;-----------------------------------------------------------------------------
+*/
+void XGI_XG21Fun14Sub70( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
+{
+
+ USHORT ModeIdIndex;
+ USHORT ModeNo;
+
+ USHORT EModeCount;
+ USHORT lvdstableindex;
+
+ lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo );
+ pBiosArguments->h.bl = 0x81;
+ pBiosArguments->x.cx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE;
+ pBiosArguments->x.dx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE;
+ EModeCount = 0;
+
+ pBiosArguments->x.ax = 0x0014;
+ for( ModeIdIndex = 0 ; ; ModeIdIndex ++ )
+ {
+ ModeNo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeID;
+ if ( pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeID == 0xFF )
+ {
+ pBiosArguments->h.bh = (UCHAR) EModeCount;
+ return;
+ }
+ if ( !XGI_XG21CheckLVDSMode( ModeNo , ModeIdIndex, pVBInfo) )
+ {
+ continue;
+ }
+ EModeCount++ ;
+ }
+}
+/*(
+;-----------------------------------------------------------------------------
+;
+; Description: Get Panel mode ID for enhanced mode
+; I/P : BH: EModeIndex ( which < Panel enhanced Mode Count )
+; O/P :
+; BL: Mode ID
+; CX: H. resolution of the assigned by the index
+; DX: V. resolution of the assigned by the index
+;
+;-----------------------------------------------------------------------------
+*/
+void XGI_XG21Fun14Sub71( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
+{
+
+ USHORT EModeCount;
+ USHORT ModeIdIndex,resindex;
+ USHORT ModeNo;
+ USHORT EModeIndex = pBiosArguments->h.bh;
+
+ EModeCount = 0;
+ for( ModeIdIndex = 0 ; ; ModeIdIndex ++ )
+ {
+ ModeNo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeID;
+ if ( pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeID == 0xFF )
+ {
+ pBiosArguments->x.ax = 0x0114;
+ return;
+ }
+ if ( !XGI_XG21CheckLVDSMode( ModeNo , ModeIdIndex, pVBInfo) )
+ {
+ continue;
+ }
+ if (EModeCount == EModeIndex)
+ {
+ resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
+ pBiosArguments->h.bl = (UCHAR) ModeNo;
+ pBiosArguments->x.cx = pVBInfo->ModeResInfo[ resindex ].HTotal ; /* xres->ax */
+ pBiosArguments->x.dx = pVBInfo->ModeResInfo[ resindex ].VTotal ; /* yres->bx */
+ pBiosArguments->x.ax = 0x0014;
+ }
+ EModeCount++ ;
+
+ }
+
+}
+/*
+;-----------------------------------------------------------------------------
+;
+; Description: Validate Panel modes ID support
+; I/P :
+; BL: ModeID
+; O/P :
+; CX: H. resolution of the assigned by the index
+; DX: V. resolution of the assigned by the index
+;
+;-----------------------------------------------------------------------------
+*/
+void XGI_XG21Fun14Sub72( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
+{
+ USHORT ModeIdIndex,resindex;
+ USHORT ModeNo;
+
+
+ ModeNo = pBiosArguments->h.bl ;
+ XGI_SearchModeID( ModeNo, &ModeIdIndex, pVBInfo);
+ if ( !XGI_XG21CheckLVDSMode( ModeNo , ModeIdIndex, pVBInfo) )
+ {
+ pBiosArguments->x.cx = 0;
+ pBiosArguments->x.dx = 0;
+ pBiosArguments->x.ax = 0x0114;
+ return;
+ }
+ resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
+ if ( ModeNo <= 0x13 )
+ {
+ pBiosArguments->x.cx = pVBInfo->StResInfo[ resindex ].HTotal ;
+ pBiosArguments->x.dx = pVBInfo->StResInfo[ resindex ].VTotal ;
+ }
+ else
+ {
+ pBiosArguments->x.cx = pVBInfo->ModeResInfo[ resindex ].HTotal ; /* xres->ax */
+ pBiosArguments->x.dx = pVBInfo->ModeResInfo[ resindex ].VTotal ; /* yres->bx */
+ }
+
+ pBiosArguments->x.ax = 0x0014;
+
+}
+
+/*
+;-----------------------------------------------------------------------------
+; Description: Get Customized Panel misc. information support
+; I/P : Select
+; to get panel horizontal timing
+; to get panel vertical timing
+; to get channel clock parameter
+; to get panel misc information
+;
+; O/P :
+; BL: for input Select = 0 ;
+; BX: *Value1 = Horizontal total
+; CX: *Value2 = Horizontal front porch
+; DX: *Value2 = Horizontal sync width
+; BL: for input Select = 1 ;
+; BX: *Value1 = Vertical total
+; CX: *Value2 = Vertical front porch
+; DX: *Value2 = Vertical sync width
+; BL: for input Select = 2 ;
+; BX: Value1 = The first CLK parameter
+; CX: Value2 = The second CLK parameter
+; BL: for input Select = 4 ;
+; BX[15]: *Value1 D[15] VESA V. Polarity
+; BX[14]: *Value1 D[14] VESA H. Polarity
+; BX[7]: *Value1 D[7] Panel V. Polarity
+; BX[6]: *Value1 D[6] Panel H. Polarity
+;-----------------------------------------------------------------------------
+*/
+void XGI_XG21Fun14Sub73( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
+{
+ UCHAR Select;
+
+ USHORT lvdstableindex;
+
+ lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo );
+ Select = pBiosArguments->h.bl;
+
+ switch (Select)
+ {
+ case 0:
+ pBiosArguments->x.bx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHT;
+ pBiosArguments->x.cx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHFP;
+ pBiosArguments->x.dx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHSYNC;
+ break;
+ case 1:
+ pBiosArguments->x.bx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVT;
+ pBiosArguments->x.cx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVFP;
+ pBiosArguments->x.dx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVSYNC;
+ break;
+ case 2:
+ pBiosArguments->x.bx = pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData1;
+ pBiosArguments->x.cx = pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData2;
+ break;
+ case 4:
+ pBiosArguments->x.bx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability;
+ break;
+ }
+
+ pBiosArguments->x.ax = 0x0014;
+}
+
+
+void XGI_XG21Fun14( PXGI_HW_DEVICE_INFO pXGIHWDE, PX86_REGS pBiosArguments)
+{
+ VB_DEVICE_INFO VBINF;
+ PVB_DEVICE_INFO pVBInfo = &VBINF;
+
+ pVBInfo->IF_DEF_LVDS = 0 ;
+ pVBInfo->IF_DEF_CH7005 = 0 ;
+ pVBInfo->IF_DEF_HiVision = 1 ;
+ pVBInfo->IF_DEF_LCDA = 1 ;
+ pVBInfo->IF_DEF_CH7017 = 0 ;
+ pVBInfo->IF_DEF_YPbPr = 1 ;
+ pVBInfo->IF_DEF_CRT2Monitor = 0 ;
+ pVBInfo->IF_DEF_VideoCapture = 0 ;
+ pVBInfo->IF_DEF_ScaleLCD = 0 ;
+ pVBInfo->IF_DEF_OEMUtil = 0 ;
+ pVBInfo->IF_DEF_PWD = 0 ;
+
+ InitTo330Pointer( pXGIHWDE->jChipType, pVBInfo ) ;
+ ReadVBIOSTablData( pXGIHWDE->jChipType , pVBInfo) ;
+
+ pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
+ pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
+ pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
+ pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
+ pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
+ pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
+ pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
+ pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
+ pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
+ pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
+ pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
+ pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
+ pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
+ pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
+ pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
+ pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
+ pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
+
+ switch(pBiosArguments->x.ax)
+ {
+ case 0x1470:
+ XGI_XG21Fun14Sub70( pVBInfo , pBiosArguments ) ;
+ break;
+ case 0x1471:
+ XGI_XG21Fun14Sub71( pVBInfo , pBiosArguments ) ;
+ break;
+ case 0x1472:
+ XGI_XG21Fun14Sub72( pVBInfo , pBiosArguments ) ;
+ break;
+ case 0x1473:
+ XGI_XG21Fun14Sub73( pVBInfo , pBiosArguments ) ;
+ break;
+ }
+}
diff --git a/drivers/staging/xgifb/vb_ext.h b/drivers/staging/xgifb/vb_ext.h
new file mode 100644
index 0000000..9a72f5e
--- /dev/null
+++ b/drivers/staging/xgifb/vb_ext.h
@@ -0,0 +1,32 @@
+#ifndef _VBEXT_
+#define _VBEXT_
+
+struct DWORDREGS {
+ ULONG Eax, Ebx, Ecx, Edx, Esi, Edi, Ebp;
+};
+
+struct WORDREGS {
+ USHORT ax, hi_ax, bx, hi_bx, cx, hi_cx, dx, hi_dx, si, hi_si, di ,hi_di, bp, hi_bp;
+};
+
+struct BYTEREGS {
+ UCHAR al, ah, hi_al, hi_ah, bl, bh, hi_bl, hi_bh, cl, ch, hi_cl, hi_ch, dl, dh, hi_dl, hi_dh;
+};
+
+typedef union _X86_REGS {
+ struct DWORDREGS e;
+ struct WORDREGS x;
+ struct BYTEREGS h;
+} X86_REGS, *PX86_REGS;
+
+extern void XGI_XG21Fun14( PXGI_HW_DEVICE_INFO pXGIHWDE, PX86_REGS pBiosArguments);
+extern void XGISetDPMS( PXGI_HW_DEVICE_INFO pXGIHWDE , ULONG VESA_POWER_STATE ) ;
+extern void XGI_GetSenseStatus( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo );
+extern void XGINew_SetModeScratch ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ;
+extern void ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo);
+extern USHORT XGINew_SenseLCD(PXGI_HW_DEVICE_INFO,PVB_DEVICE_INFO pVBInfo);
+#ifdef WIN2000
+extern BOOLEAN XGI_DySense( PHW_DEVICE_EXTENSION pHWDE , PUCHAR ujConnectStatus );
+#endif /* WIN2000 */
+
+#endif
diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
new file mode 100644
index 0000000..b85ca9b
--- /dev/null
+++ b/drivers/staging/xgifb/vb_init.c
@@ -0,0 +1,3444 @@
+#include "osdef.h"
+#include "vgatypes.h"
+
+
+#ifdef LINUX_KERNEL
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/delay.h> /* udelay */
+#include "XGIfb.h"
+/*#if LINUX_VERSxION_CODE >= KERNEL_VERSION(2,5,0)
+#include <video/XGIfb.h>
+#else
+#include <linux/XGIfb.h>
+#endif */
+#endif
+
+#ifdef WIN2000
+#include <dderror.h>
+#include <devioctl.h>
+#include <miniport.h>
+#include <ntddvdeo.h>
+#include <video.h>
+#include "xgiv.h"
+#include "dd_i2c.h"
+#include "tools.h"
+#endif
+
+#include "vb_def.h"
+#include "vb_struct.h"
+#include "vb_util.h"
+#include "vb_setmode.h"
+#include "vb_init.h"
+#include "vb_ext.h"
+
+#ifdef LINUX_XF86
+#include "xf86.h"
+#include "xf86PciInfo.h"
+#include "xgi.h"
+#include "xgi_regs.h"
+#endif
+
+#ifdef LINUX_KERNEL
+#include <asm/io.h>
+#include <linux/types.h>
+#endif
+
+
+
+
+UCHAR XGINew_ChannelAB,XGINew_DataBusWidth;
+
+USHORT XGINew_DRAMType[17][5]={{0x0C,0x0A,0x02,0x40,0x39},{0x0D,0x0A,0x01,0x40,0x48},
+ {0x0C,0x09,0x02,0x20,0x35},{0x0D,0x09,0x01,0x20,0x44},
+ {0x0C,0x08,0x02,0x10,0x31},{0x0D,0x08,0x01,0x10,0x40},
+ {0x0C,0x0A,0x01,0x20,0x34},{0x0C,0x09,0x01,0x08,0x32},
+ {0x0B,0x08,0x02,0x08,0x21},{0x0C,0x08,0x01,0x08,0x30},
+ {0x0A,0x08,0x02,0x04,0x11},{0x0B,0x0A,0x01,0x10,0x28},
+ {0x09,0x08,0x02,0x02,0x01},{0x0B,0x09,0x01,0x08,0x24},
+ {0x0B,0x08,0x01,0x04,0x20},{0x0A,0x08,0x01,0x02,0x10},
+ {0x09,0x08,0x01,0x01,0x00}};
+
+USHORT XGINew_SDRDRAM_TYPE[13][5]=
+{
+{ 2,12, 9,64,0x35},
+{ 1,13, 9,64,0x44},
+{ 2,12, 8,32,0x31},
+{ 2,11, 9,32,0x25},
+{ 1,12, 9,32,0x34},
+{ 1,13, 8,32,0x40},
+{ 2,11, 8,16,0x21},
+{ 1,12, 8,16,0x30},
+{ 1,11, 9,16,0x24},
+{ 1,11, 8, 8,0x20},
+{ 2, 9, 8, 4,0x01},
+{ 1,10, 8, 4,0x10},
+{ 1, 9, 8, 2,0x00}
+};
+
+USHORT XGINew_DDRDRAM_TYPE[4][5]=
+{
+{ 2,12, 9,64,0x35},
+{ 2,12, 8,32,0x31},
+{ 2,11, 8,16,0x21},
+{ 2, 9, 8, 4,0x01}
+};
+USHORT XGINew_DDRDRAM_TYPE340[4][5]=
+{
+{ 2,13, 9,64,0x45},
+{ 2,12, 9,32,0x35},
+{ 2,12, 8,16,0x31},
+{ 2,11, 8, 8,0x21}
+};
+USHORT XGINew_DDRDRAM_TYPE20[12][5]=
+{
+{ 2,14,11,128,0x5D},
+{ 2,14,10,64,0x59},
+{ 2,13,11,64,0x4D},
+{ 2,14, 9,32,0x55},
+{ 2,13,10,32,0x49},
+{ 2,12,11,32,0x3D},
+{ 2,14, 8,16,0x51},
+{ 2,13, 9,16,0x45},
+{ 2,12,10,16,0x39},
+{ 2,13, 8, 8,0x41},
+{ 2,12, 9, 8,0x35},
+{ 2,12, 8, 4,0x31}
+};
+
+void XGINew_SetDRAMSize_340(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO);
+void XGINew_SetDRAMSize_310(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO);
+void XGINew_SetMemoryClock(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+void XGINew_SetDRAMModeRegister(PVB_DEVICE_INFO );
+void XGINew_SetDRAMModeRegister340( PXGI_HW_DEVICE_INFO HwDeviceExtension );
+void XGINew_SetDRAMDefaultRegister340(PXGI_HW_DEVICE_INFO HwDeviceExtension, ULONG, PVB_DEVICE_INFO );
+UCHAR XGINew_GetXG20DRAMType( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo);
+BOOLEAN XGIInitNew( PXGI_HW_DEVICE_INFO HwDeviceExtension) ;
+
+int XGINew_DDRSizing340( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO );
+void XGINew_DisableRefresh( PXGI_HW_DEVICE_INFO ,PVB_DEVICE_INFO) ;
+void XGINew_CheckBusWidth_310( PVB_DEVICE_INFO) ;
+int XGINew_SDRSizing(PVB_DEVICE_INFO);
+int XGINew_DDRSizing( PVB_DEVICE_INFO );
+void XGINew_EnableRefresh( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO);
+int XGINew_RAMType; /*int ModeIDOffset,StandTable,CRT1Table,ScreenOffset,REFIndex;*/
+ULONG UNIROM; /* UNIROM */
+BOOLEAN ChkLFB( PVB_DEVICE_INFO );
+void XGINew_Delay15us(ULONG);
+void SetPowerConsume (PXGI_HW_DEVICE_INFO HwDeviceExtension,ULONG XGI_P3d4Port);
+void ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo);
+void XGINew_DDR1x_MRS_XG20( ULONG P3c4 , PVB_DEVICE_INFO pVBInfo);
+void XGINew_SetDRAMModeRegister_XG20( PXGI_HW_DEVICE_INFO HwDeviceExtension );
+void XGINew_SetDRAMModeRegister_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension );
+void XGINew_ChkSenseStatus ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ;
+void XGINew_SetModeScratch ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ;
+void XGINew_GetXG21Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) ;
+UCHAR GetXG21FPBits(PVB_DEVICE_INFO pVBInfo);
+void XGINew_GetXG27Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) ;
+UCHAR GetXG27FPBits(PVB_DEVICE_INFO pVBInfo);
+
+#ifdef WIN2000
+/* [Billy] 2007/05/20 For CH7007 */
+extern UCHAR CH7007TVReg_UNTSC[][8],CH7007TVReg_ONTSC[][8],CH7007TVReg_UPAL[][8],CH7007TVReg_OPAL[][8];
+extern UCHAR XGI7007_CHTVVCLKUNTSC[],XGI7007_CHTVVCLKONTSC[],XGI7007_CHTVVCLKUPAL[],XGI7007_CHTVVCLKOPAL[];
+#endif
+
+#ifdef LINUX_KERNEL
+void DelayUS(ULONG MicroSeconds)
+{
+ udelay(MicroSeconds);
+}
+#endif
+
+/* --------------------------------------------------------------------- */
+/* Function : XGIInitNew */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGIInitNew( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+{
+
+ VB_DEVICE_INFO VBINF;
+ PVB_DEVICE_INFO pVBInfo = &VBINF;
+ UCHAR i , temp = 0 , temp1 ;
+ // VBIOSVersion[ 5 ] ;
+ PUCHAR volatile pVideoMemory;
+
+ /* ULONG j, k ; */
+
+ PXGI_DSReg pSR ;
+
+ ULONG Temp ;
+
+ pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+
+ pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+
+ pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
+
+ pVideoMemory = ( PUCHAR )pVBInfo->ROMAddr;
+
+
+// Newdebugcode( 0x99 ) ;
+
+
+ /* if ( pVBInfo->ROMAddr == 0 ) */
+ /* return( FALSE ) ; */
+
+ if ( pVBInfo->FBAddr == 0 )
+{
+ printk("\n pVBInfo->FBAddr == 0 ");
+ return( FALSE ) ;
+}
+printk("1");
+ if ( pVBInfo->BaseAddr == 0 )
+{
+ printk("\npVBInfo->BaseAddr == 0 ");
+ return( FALSE ) ;
+}
+printk("2");
+
+ XGINew_SetReg3( ( pVBInfo->BaseAddr + 0x12 ) , 0x67 ) ; /* 3c2 <- 67 ,ynlai */
+
+ pVBInfo->ISXPDOS = 0 ;
+printk("3");
+
+if ( !HwDeviceExtension->bIntegratedMMEnabled )
+{
+ return( FALSE ) ; /* alan */
+}
+printk("4");
+
+// XGI_MemoryCopy( VBIOSVersion , HwDeviceExtension->szVBIOSVer , 4 ) ;
+
+ // VBIOSVersion[ 4 ] = 0x0 ;
+
+ /* 09/07/99 modify by domao */
+
+ pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
+ pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
+ pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
+ pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
+ pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
+ pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
+ pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
+ pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
+ pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
+ pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
+ pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
+ pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
+ pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
+ pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
+ pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
+ pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
+ pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
+printk("5");
+
+ if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */
+ XGI_GetVBType( pVBInfo ) ; /* Run XGI_GetVBType before InitTo330Pointer */
+
+ InitTo330Pointer( HwDeviceExtension->jChipType, pVBInfo ) ;
+
+ /* ReadVBIOSData */
+ ReadVBIOSTablData( HwDeviceExtension->jChipType , pVBInfo) ;
+
+ /* 1.Openkey */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x05 , 0x86 ) ;
+printk("6");
+
+ /* GetXG21Sense (GPIO) */
+ if ( HwDeviceExtension->jChipType == XG21 )
+ {
+ XGINew_GetXG21Sense(HwDeviceExtension, pVBInfo) ;
+ }
+ if ( HwDeviceExtension->jChipType == XG27 )
+ {
+ XGINew_GetXG27Sense(HwDeviceExtension, pVBInfo) ;
+ }
+printk("7");
+
+ /* 2.Reset Extended register */
+
+ for( i = 0x06 ; i < 0x20 ; i++ )
+ XGINew_SetReg1( pVBInfo->P3c4 , i , 0 ) ;
+
+ for( i = 0x21 ; i <= 0x27 ; i++ )
+ XGINew_SetReg1( pVBInfo->P3c4 , i , 0 ) ;
+
+ /* for( i = 0x06 ; i <= 0x27 ; i++ ) */
+ /* XGINew_SetReg1( pVBInfo->P3c4 , i , 0 ) ; */
+
+printk("8");
+
+ if(( HwDeviceExtension->jChipType >= XG20 ) || ( HwDeviceExtension->jChipType >= XG40))
+ {
+ for( i = 0x31 ; i <= 0x3B ; i++ )
+ XGINew_SetReg1( pVBInfo->P3c4 , i , 0 ) ;
+ }
+ else
+ {
+ for( i = 0x31 ; i <= 0x3D ; i++ )
+ XGINew_SetReg1( pVBInfo->P3c4 , i , 0 ) ;
+ }
+printk("9");
+
+ if ( HwDeviceExtension->jChipType == XG42 ) /* [Hsuan] 2004/08/20 Auto over driver for XG42 */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x3B , 0xC0 ) ;
+
+ /* for( i = 0x30 ; i <= 0x3F ; i++ ) */
+ /* XGINew_SetReg1( pVBInfo->P3d4 , i , 0 ) ; */
+
+ for( i = 0x79 ; i <= 0x7C ; i++ )
+ XGINew_SetReg1( pVBInfo->P3d4 , i , 0 ) ; /* shampoo 0208 */
+
+printk("10");
+
+ if ( HwDeviceExtension->jChipType >= XG20 )
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x97 , *pVBInfo->pXGINew_CR97 ) ;
+
+ /* 3.SetMemoryClock
+
+ if ( HwDeviceExtension->jChipType >= XG40 )
+ XGINew_RAMType = ( int )XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo) ;
+
+ if ( HwDeviceExtension->jChipType < XG40 )
+ XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ; */
+
+printk("11");
+
+ /* 4.SetDefExt1Regs begin */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x07 , *pVBInfo->pSR07 ) ;
+ if ( HwDeviceExtension->jChipType == XG27 )
+ {
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x40 , *pVBInfo->pSR40 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x41 , *pVBInfo->pSR41 ) ;
+ }
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x11 , 0x0F ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x1F , *pVBInfo->pSR1F ) ;
+ /* XGINew_SetReg1( pVBInfo->P3c4 , 0x20 , 0x20 ) ; */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x20 , 0xA0 ) ; /* alan, 2001/6/26 Frame buffer can read/write SR20 */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x36 , 0x70 ) ; /* Hsuan, 2006/01/01 H/W request for slow corner chip */
+ if ( HwDeviceExtension->jChipType == XG27 ) /* Alan 12/07/2006 */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x36 , *pVBInfo->pSR36 ) ;
+
+ /* SR11 = 0x0F ; */
+ /* XGINew_SetReg1( pVBInfo->P3c4 , 0x11 , SR11 ) ; */
+
+printk("12");
+
+ if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */
+ {
+// /* Set AGP Rate */
+// temp1 = XGINew_GetReg1( pVBInfo->P3c4 , 0x3B ) ;
+// temp1 &= 0x02 ;
+// if ( temp1 == 0x02 )
+// {
+// XGINew_SetReg4( 0xcf8 , 0x80000000 ) ;
+// ChipsetID = XGINew_GetReg3( 0x0cfc ) ;
+// XGINew_SetReg4( 0xcf8 , 0x8000002C ) ;
+// VendorID = XGINew_GetReg3( 0x0cfc ) ;
+// VendorID &= 0x0000FFFF ;
+// XGINew_SetReg4( 0xcf8 , 0x8001002C ) ;
+// GraphicVendorID = XGINew_GetReg3( 0x0cfc ) ;
+// GraphicVendorID &= 0x0000FFFF;
+//
+// if ( ChipsetID == 0x7301039 )
+/// XGINew_SetReg1( pVBInfo->P3d4 , 0x5F , 0x09 ) ;
+//
+// ChipsetID &= 0x0000FFFF ;
+///
+// if ( ( ChipsetID == 0x700E ) || ( ChipsetID == 0x1022 ) || ( ChipsetID == 0x1106 ) || ( ChipsetID == 0x10DE ) )
+// {
+// if ( ChipsetID == 0x1106 )
+// {
+// if ( ( VendorID == 0x1019 ) && ( GraphicVendorID == 0x1019 ) )
+// XGINew_SetReg1( pVBInfo->P3d4 , 0x5F , 0x0D ) ;
+// else
+// XGINew_SetReg1( pVBInfo->P3d4 , 0x5F , 0x0B ) ;
+// }
+// else
+// XGINew_SetReg1( pVBInfo->P3d4 , 0x5F , 0x0B ) ;
+// }
+// }
+
+printk("13");
+
+ if ( HwDeviceExtension->jChipType >= XG40 )
+ {
+ /* Set AGP customize registers (in SetDefAGPRegs) Start */
+ for( i = 0x47 ; i <= 0x4C ; i++ )
+ XGINew_SetReg1( pVBInfo->P3d4 , i , pVBInfo->AGPReg[ i - 0x47 ] ) ;
+
+ for( i = 0x70 ; i <= 0x71 ; i++ )
+ XGINew_SetReg1( pVBInfo->P3d4 , i , pVBInfo->AGPReg[ 6 + i - 0x70 ] ) ;
+
+ for( i = 0x74 ; i <= 0x77 ; i++ )
+ XGINew_SetReg1( pVBInfo->P3d4 , i , pVBInfo->AGPReg[ 8 + i - 0x74 ] ) ;
+ /* Set AGP customize registers (in SetDefAGPRegs) End */
+ /*[Hsuan]2004/12/14 AGP Input Delay Adjustment on 850 */
+// XGINew_SetReg4( 0xcf8 , 0x80000000 ) ;
+// ChipsetID = XGINew_GetReg3( 0x0cfc ) ;
+// if ( ChipsetID == 0x25308086 )
+// XGINew_SetReg1( pVBInfo->P3d4 , 0x77 , 0xF0 ) ;
+
+ HwDeviceExtension->pQueryVGAConfigSpace( HwDeviceExtension , 0x50 , 0 , &Temp ) ; /* Get */
+ Temp >>= 20 ;
+ Temp &= 0xF ;
+
+ if ( Temp == 1 )
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x48 , 0x20 ) ; /* CR48 */
+ }
+printk("14");
+
+ if ( HwDeviceExtension->jChipType < XG40 )
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x49 , pVBInfo->CR49[ 0 ] ) ;
+ } /* != XG20 */
+
+ /* Set PCI */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x23 , *pVBInfo->pSR23 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x24 , *pVBInfo->pSR24 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x25 , pVBInfo->SR25[ 0 ] ) ;
+printk("15");
+
+ if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */
+ {
+ /* Set VB */
+ XGI_UnLockCRT2( HwDeviceExtension, pVBInfo) ;
+ XGINew_SetRegANDOR( pVBInfo->Part0Port , 0x3F , 0xEF , 0x00 ) ; /* alan, disable VideoCapture */
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x00 , 0x00 ) ;
+ temp1 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x7B ) ; /* chk if BCLK>=100MHz */
+ temp = ( UCHAR )( ( temp1 >> 4 ) & 0x0F ) ;
+
+
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x02 , ( *pVBInfo->pCRT2Data_1_2 ) ) ;
+
+printk("16");
+
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x2E , 0x08 ) ; /* use VB */
+ } /* != XG20 */
+
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x27 , 0x1F ) ;
+
+ if ( ( HwDeviceExtension->jChipType == XG42 ) && XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo) != 0 ) /* Not DDR */
+ {
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , ( *pVBInfo->pSR31 & 0x3F ) | 0x40 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x32 , ( *pVBInfo->pSR32 & 0xFC ) | 0x01 ) ;
+ }
+ else
+ {
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , *pVBInfo->pSR31 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x32 , *pVBInfo->pSR32 ) ;
+ }
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x33 , *pVBInfo->pSR33 ) ;
+printk("17");
+
+/*
+ if ( HwDeviceExtension->jChipType >= XG40 )
+ SetPowerConsume ( HwDeviceExtension , pVBInfo->P3c4); */
+
+ if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */
+ {
+ if ( XGI_BridgeIsOn( pVBInfo ) == 1 )
+ {
+ if ( pVBInfo->IF_DEF_LVDS == 0 )
+ {
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x00 , 0x1C ) ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x0D , *pVBInfo->pCRT2Data_4_D ) ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x0E , *pVBInfo->pCRT2Data_4_E ) ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x10 , *pVBInfo->pCRT2Data_4_10 ) ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x0F , 0x3F ) ;
+ }
+
+ XGI_LockCRT2( HwDeviceExtension, pVBInfo ) ;
+ }
+ } /* != XG20 */
+printk("18");
+
+ if ( HwDeviceExtension->jChipType < XG40 )
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x83 , 0x00 ) ;
+printk("181");
+
+ if ( HwDeviceExtension->bSkipSense == FALSE )
+ {
+printk("182");
+
+ XGI_SenseCRT1(pVBInfo) ;
+
+printk("183");
+ /* XGINew_DetectMonitor( HwDeviceExtension ) ; */
+pVBInfo->IF_DEF_CH7007 = 0;
+ if ( ( HwDeviceExtension->jChipType == XG21 ) && (pVBInfo->IF_DEF_CH7007) )
+ {
+printk("184");
+ XGI_GetSenseStatus( HwDeviceExtension , pVBInfo ) ; /* sense CRT2 */
+printk("185");
+
+ }
+ if ( HwDeviceExtension->jChipType == XG21 )
+ {
+printk("186");
+
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , ~Monitor1Sense , Monitor1Sense ) ; /* Z9 default has CRT */
+ temp = GetXG21FPBits( pVBInfo ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x37 , ~0x01, temp ) ;
+printk("187");
+
+ }
+ if ( HwDeviceExtension->jChipType == XG27 )
+ {
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , ~Monitor1Sense , Monitor1Sense ) ; /* Z9 default has CRT */
+ temp = GetXG27FPBits( pVBInfo ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x37 , ~0x03, temp ) ;
+ }
+ }
+printk("19");
+
+ if ( HwDeviceExtension->jChipType >= XG40 )
+ {
+ if ( HwDeviceExtension->jChipType >= XG40 )
+ {
+ XGINew_RAMType = ( int )XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo ) ;
+ }
+
+ XGINew_SetDRAMDefaultRegister340( HwDeviceExtension , pVBInfo->P3d4, pVBInfo ) ;
+
+ if ( HwDeviceExtension->bSkipDramSizing == TRUE )
+ {
+ pSR = HwDeviceExtension->pSR ;
+ if ( pSR!=NULL )
+ {
+ while( pSR->jIdx != 0xFF )
+ {
+ XGINew_SetReg1( pVBInfo->P3c4 , pSR->jIdx , pSR->jVal ) ;
+ pSR++ ;
+ }
+ }
+ /* XGINew_SetDRAMModeRegister340( pVBInfo ) ; */
+ } /* SkipDramSizing */
+ else
+ {
+#if 0
+ if ( HwDeviceExtension->jChipType == XG20 )
+ {
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , pVBInfo->SR15[0][XGINew_RAMType] ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , pVBInfo->SR15[1][XGINew_RAMType] ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x20 , 0x20 ) ;
+ }
+ else
+#endif
+{
+printk("20");
+
+ XGINew_SetDRAMSize_340( HwDeviceExtension , pVBInfo) ;
+}
+printk("21");
+
+ }
+ } /* XG40 */
+
+printk("22");
+
+
+ /* SetDefExt2Regs begin */
+/*
+ AGP = 1 ;
+ temp =( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x3A ) ;
+ temp &= 0x30 ;
+ if ( temp == 0x30 )
+ AGP = 0 ;
+
+ if ( AGP == 0 )
+ *pVBInfo->pSR21 &= 0xEF ;
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , *pVBInfo->pSR21 ) ;
+ if ( AGP == 1 )
+ *pVBInfo->pSR22 &= 0x20 ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x22 , *pVBInfo->pSR22 ) ;
+*/
+
+// base = 0x80000000 ;
+// OutPortLong( 0xcf8 , base ) ;
+// Temp = ( InPortLong( 0xcfc ) & 0xFFFF ) ;
+// if ( Temp == 0x1039 )
+// {
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x22 , ( UCHAR )( ( *pVBInfo->pSR22 ) & 0xFE ) ) ;
+// }
+// else
+// {
+// XGINew_SetReg1( pVBInfo->P3c4 , 0x22 , *pVBInfo->pSR22 ) ;
+// }
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , *pVBInfo->pSR21 ) ;
+
+printk("23");
+
+
+ XGINew_ChkSenseStatus ( HwDeviceExtension , pVBInfo ) ;
+ XGINew_SetModeScratch ( HwDeviceExtension , pVBInfo ) ;
+
+printk("24");
+
+
+XGINew_SetReg1( pVBInfo->P3d4 , 0x8c , 0x87);
+XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x31);
+printk("25");
+
+ return( TRUE ) ;
+} /* end of init */
+
+
+
+
+
+/* ============== alan ====================== */
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_GetXG20DRAMType */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+UCHAR XGINew_GetXG20DRAMType( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+{
+ UCHAR data, temp ;
+
+ if ( HwDeviceExtension->jChipType < XG20 )
+ {
+ if ( *pVBInfo->pSoftSetting & SoftDRAMType )
+ {
+ data = *pVBInfo->pSoftSetting & 0x07 ;
+ return( data ) ;
+ }
+ else
+ {
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x39 ) & 0x02 ;
+
+ if ( data == 0 )
+ data = ( XGINew_GetReg1( pVBInfo->P3c4 , 0x3A ) & 0x02 ) >> 1 ;
+
+ return( data ) ;
+ }
+ }
+ else if ( HwDeviceExtension->jChipType == XG27 )
+ {
+ if ( *pVBInfo->pSoftSetting & SoftDRAMType )
+ {
+ data = *pVBInfo->pSoftSetting & 0x07 ;
+ return( data ) ;
+ }
+ temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x3B ) ;
+
+ if (( temp & 0x88 )==0x80) /* SR3B[7][3]MAA15 MAA11 (Power on Trapping) */
+ data = 0 ; /*DDR*/
+ else
+ data = 1 ; /*DDRII*/
+ return( data ) ;
+ }
+ else if ( HwDeviceExtension->jChipType == XG21 )
+ {
+ XGINew_SetRegAND( pVBInfo->P3d4 , 0xB4 , ~0x02 ) ; /* Independent GPIO control */
+ DelayUS(800);
+ XGINew_SetRegOR( pVBInfo->P3d4 , 0x4A , 0x80 ) ; /* Enable GPIOH read */
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) ; /* GPIOF 0:DVI 1:DVO */
+// HOTPLUG_SUPPORT
+// for current XG20 & XG21, GPIOH is floating, driver will fix DDR temporarily
+ if ( temp & 0x01 ) /* DVI read GPIOH */
+ data = 1 ; /*DDRII*/
+ else
+ data = 0 ; /*DDR*/
+//~HOTPLUG_SUPPORT
+ XGINew_SetRegOR( pVBInfo->P3d4 , 0xB4 , 0x02 ) ;
+ return( data ) ;
+ }
+ else
+ {
+ data = XGINew_GetReg1( pVBInfo->P3d4 , 0x97 ) & 0x01 ;
+
+ if ( data == 1 )
+ data ++ ;
+
+ return( data );
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_Get310DRAMType */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+UCHAR XGINew_Get310DRAMType(PVB_DEVICE_INFO pVBInfo)
+{
+ UCHAR data ;
+
+ /* index = XGINew_GetReg1( pVBInfo->P3c4 , 0x1A ) ; */
+ /* index &= 07 ; */
+
+ if ( *pVBInfo->pSoftSetting & SoftDRAMType )
+ data = *pVBInfo->pSoftSetting & 0x03 ;
+ else
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x3a ) & 0x03 ;
+
+ return( data ) ;
+}
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_Delay15us */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+/*
+void XGINew_Delay15us(ULONG ulMicrsoSec)
+{
+}
+*/
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SDR_MRS */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SDR_MRS( PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT data ;
+
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x16 ) ;
+ data &= 0x3F ; /* SR16 D7=0,D6=0 */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ; /* enable mode register set(MRS) low */
+ /* XGINew_Delay15us( 0x100 ) ; */
+ data |= 0x80 ; /* SR16 D7=1,D6=0 */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ; /* enable mode register set(MRS) high */
+ /* XGINew_Delay15us( 0x100 ) ; */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DDR1x_MRS_340 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_DDR1x_MRS_340( ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
+{
+ XGINew_SetReg1( P3c4 , 0x18 , 0x01 ) ;
+ XGINew_SetReg1( P3c4 , 0x19 , 0x20 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
+
+ if ( *pVBInfo->pXGINew_DRAMTypeDefinition != 0x0C ) /* Samsung F Die */
+ {
+ DelayUS( 3000 ) ; /* Delay 67 x 3 Delay15us */
+ XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ;
+ XGINew_SetReg1( P3c4 , 0x19 , 0x20 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
+ }
+
+ DelayUS( 60 ) ;
+ XGINew_SetReg1( P3c4 , 0x18 , pVBInfo->SR15[ 2 ][ XGINew_RAMType ] ) ; /* SR18 */
+ XGINew_SetReg1( P3c4 , 0x19 , 0x01 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , pVBInfo->SR16[ 0 ] ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , pVBInfo->SR16[ 1 ] ) ;
+ DelayUS( 1000 ) ;
+ XGINew_SetReg1( P3c4 , 0x1B , 0x03 ) ;
+ DelayUS( 500 ) ;
+ XGINew_SetReg1( P3c4 , 0x18 , pVBInfo->SR15[ 2 ][ XGINew_RAMType ] ) ; /* SR18 */
+ XGINew_SetReg1( P3c4 , 0x19 , 0x00 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , pVBInfo->SR16[ 2 ] ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , pVBInfo->SR16[ 3 ] ) ;
+ XGINew_SetReg1( P3c4 , 0x1B , 0x00 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DDR2x_MRS_340 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_DDR2x_MRS_340( ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
+{
+ XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ;
+ XGINew_SetReg1( P3c4 , 0x19 , 0x20 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
+ DelayUS( 60 ) ;
+ XGINew_SetReg1( P3c4 , 0x18 , pVBInfo->SR15[ 2 ][ XGINew_RAMType ] ) ; /* SR18 */
+ /* XGINew_SetReg1( P3c4 , 0x18 , 0x31 ) ; */
+ XGINew_SetReg1( P3c4 , 0x19 , 0x01 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ;
+ DelayUS( 1000 ) ;
+ XGINew_SetReg1( P3c4 , 0x1B , 0x03 ) ;
+ DelayUS( 500 ) ;
+ /* XGINew_SetReg1( P3c4 , 0x18 , 0x31 ) ; */
+ XGINew_SetReg1( P3c4 , 0x18 , pVBInfo->SR15[ 2 ][ XGINew_RAMType ] ) ; /* SR18 */
+ XGINew_SetReg1( P3c4 , 0x19 , 0x00 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ;
+ XGINew_SetReg1( P3c4 , 0x1B , 0x00 ) ;
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DDRII_Bootup_XG27 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_DDRII_Bootup_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension , ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
+{
+ ULONG P3d4 = P3c4 + 0x10 ;
+ XGINew_RAMType = ( int )XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo ) ;
+ XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ;
+
+ /* Set Double Frequency */
+ /* XGINew_SetReg1( P3d4 , 0x97 , 0x11 ) ; */ /* CR97 */
+ XGINew_SetReg1( P3d4 , 0x97 , *pVBInfo->pXGINew_CR97 ) ; /* CR97 */
+
+ DelayUS( 200 ) ;
+
+ XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* Set SR18 */ //EMRS2
+ XGINew_SetReg1( P3c4 , 0x19 , 0x80 ) ; /* Set SR19 */
+ XGINew_SetReg1( P3c4 , 0x16 , 0x20 ) ; /* Set SR16 */
+ DelayUS( 15 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0xA0 ) ; /* Set SR16 */
+ DelayUS( 15 ) ;
+
+ XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* Set SR18 */ //EMRS3
+ XGINew_SetReg1( P3c4 , 0x19 , 0xC0 ) ; /* Set SR19 */
+ XGINew_SetReg1( P3c4 , 0x16 , 0x20 ) ; /* Set SR16 */
+ DelayUS( 15 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0xA0 ) ; /* Set SR16 */
+ DelayUS( 15) ;
+
+ XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* Set SR18 */ //EMRS1
+ XGINew_SetReg1( P3c4 , 0x19 , 0x40 ) ; /* Set SR19 */
+ XGINew_SetReg1( P3c4 , 0x16 , 0x20 ) ; /* Set SR16 */
+ DelayUS( 30 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0xA0 ) ; /* Set SR16 */
+ DelayUS( 15 ) ;
+
+ XGINew_SetReg1( P3c4 , 0x18 , 0x42 ) ; /* Set SR18 */ //MRS, DLL Enable
+ XGINew_SetReg1( P3c4 , 0x19 , 0x0A ) ; /* Set SR19 */
+ XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ; /* Set SR16 */
+ DelayUS( 30 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ; /* Set SR16 */
+ XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ; /* Set SR16 */
+ /* DelayUS( 15 ) ; */
+
+ XGINew_SetReg1( P3c4 , 0x1B , 0x04 ) ; /* Set SR1B */
+ DelayUS( 60 ) ;
+ XGINew_SetReg1( P3c4 , 0x1B , 0x00 ) ; /* Set SR1B */
+
+ XGINew_SetReg1( P3c4 , 0x18 , 0x42 ) ; /* Set SR18 */ //MRS, DLL Reset
+ XGINew_SetReg1( P3c4 , 0x19 , 0x08 ) ; /* Set SR19 */
+ XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ; /* Set SR16 */
+
+ DelayUS( 30 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x83 ) ; /* Set SR16 */
+ DelayUS( 15 ) ;
+
+ XGINew_SetReg1( P3c4 , 0x18 , 0x80 ) ; /* Set SR18 */ //MRS, ODT
+ XGINew_SetReg1( P3c4 , 0x19 , 0x46 ) ; /* Set SR19 */
+ XGINew_SetReg1( P3c4 , 0x16 , 0x20 ) ; /* Set SR16 */
+ DelayUS( 30 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0xA0 ) ; /* Set SR16 */
+ DelayUS( 15 ) ;
+
+ XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* Set SR18 */ //EMRS
+ XGINew_SetReg1( P3c4 , 0x19 , 0x40 ) ; /* Set SR19 */
+ XGINew_SetReg1( P3c4 , 0x16 , 0x20 ) ; /* Set SR16 */
+ DelayUS( 30 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0xA0 ) ; /* Set SR16 */
+ DelayUS( 15 ) ;
+
+ XGINew_SetReg1( P3c4 , 0x1B , 0x04 ) ; /* Set SR1B refresh control 000:close; 010:open */
+ DelayUS( 200 ) ;
+
+
+}
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DDR2_MRS_XG20 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_DDR2_MRS_XG20( PXGI_HW_DEVICE_INFO HwDeviceExtension , ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
+{
+ ULONG P3d4 = P3c4 + 0x10 ;
+
+ XGINew_RAMType = ( int )XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo ) ;
+ XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ;
+
+ XGINew_SetReg1( P3d4 , 0x97 , 0x11 ) ; /* CR97 */
+
+ DelayUS( 200 ) ;
+ XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* EMRS2 */
+ XGINew_SetReg1( P3c4 , 0x19 , 0x80 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ;
+
+ XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* EMRS3 */
+ XGINew_SetReg1( P3c4 , 0x19 , 0xC0 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ;
+
+ XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* EMRS1 */
+ XGINew_SetReg1( P3c4 , 0x19 , 0x40 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ;
+
+ // XGINew_SetReg1( P3c4 , 0x18 , 0x52 ) ; /* MRS1 */
+ XGINew_SetReg1( P3c4 , 0x18 , 0x42 ) ; /* MRS1 */
+ XGINew_SetReg1( P3c4 , 0x19 , 0x02 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ;
+
+ DelayUS( 15 ) ;
+ XGINew_SetReg1( P3c4 , 0x1B , 0x04 ) ; /* SR1B */
+ DelayUS( 30 ) ;
+ XGINew_SetReg1( P3c4 , 0x1B , 0x00 ) ; /* SR1B */
+ DelayUS( 100 ) ;
+
+ //XGINew_SetReg1( P3c4 , 0x18 , 0x52 ) ; /* MRS2 */
+ XGINew_SetReg1( P3c4 , 0x18 , 0x42 ) ; /* MRS1 */
+ XGINew_SetReg1( P3c4 , 0x19 , 0x00 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ;
+
+ DelayUS( 200 ) ;
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DDR2_MRS_XG20 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_DDR2_MRS_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension , ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
+{
+ ULONG P3d4 = P3c4 + 0x10 ;
+
+ XGINew_RAMType = ( int )XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo ) ;
+ XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ;
+
+ XGINew_SetReg1( P3d4 , 0x97 , 0x11 ) ; /* CR97 */
+ DelayUS( 200 ) ;
+ XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* EMRS2 */
+ XGINew_SetReg1( P3c4 , 0x19 , 0x80 ) ;
+
+ XGINew_SetReg1( P3c4 , 0x16 , 0x10 ) ;
+ DelayUS( 15 ) ; ////06/11/23 XG27 A0 for CKE enable
+ XGINew_SetReg1( P3c4 , 0x16 , 0x90 ) ;
+
+ XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* EMRS3 */
+ XGINew_SetReg1( P3c4 , 0x19 , 0xC0 ) ;
+
+ XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
+ DelayUS( 15 ) ; ////06/11/22 XG27 A0
+ XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
+
+
+ XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* EMRS1 */
+ XGINew_SetReg1( P3c4 , 0x19 , 0x40 ) ;
+
+ XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
+ DelayUS( 15 ) ; ////06/11/22 XG27 A0
+ XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
+
+ XGINew_SetReg1( P3c4 , 0x18 , 0x42 ) ; /* MRS1 */
+ XGINew_SetReg1( P3c4 , 0x19 , 0x06 ) ; ////[Billy]06/11/22 DLL Reset for XG27 Hynix DRAM
+
+ XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
+ DelayUS( 15 ) ; ////06/11/23 XG27 A0
+ XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
+
+ DelayUS( 30 ) ; ////06/11/23 XG27 A0 Start Auto-PreCharge
+ XGINew_SetReg1( P3c4 , 0x1B , 0x04 ) ; /* SR1B */
+ DelayUS( 60 ) ;
+ XGINew_SetReg1( P3c4 , 0x1B , 0x00 ) ; /* SR1B */
+
+
+ XGINew_SetReg1( P3c4 , 0x18 , 0x42 ) ; /* MRS1 */
+ XGINew_SetReg1( P3c4 , 0x19 , 0x04 ) ; //// DLL without Reset for XG27 Hynix DRAM
+
+ XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
+ DelayUS( 30 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
+
+ XGINew_SetReg1( P3c4 , 0x18 , 0x80 ); ////XG27 OCD ON
+ XGINew_SetReg1( P3c4 , 0x19 , 0x46 );
+
+ XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
+ DelayUS( 30 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
+
+ XGINew_SetReg1( P3c4 , 0x18 , 0x00 );
+ XGINew_SetReg1( P3c4 , 0x19 , 0x40 );
+
+ XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
+ DelayUS( 30 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
+
+ DelayUS( 15 ) ; ////Start Auto-PreCharge
+ XGINew_SetReg1( P3c4 , 0x1B , 0x04 ) ; /* SR1B */
+ DelayUS( 200 ) ;
+ XGINew_SetReg1( P3c4 , 0x1B , 0x03 ) ; /* SR1B */
+
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DDR1x_DefaultRegister */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_DDR1x_DefaultRegister( PXGI_HW_DEVICE_INFO HwDeviceExtension , ULONG Port , PVB_DEVICE_INFO pVBInfo)
+{
+ ULONG P3d4 = Port ,
+ P3c4 = Port - 0x10 ;
+
+ if ( HwDeviceExtension->jChipType >= XG20 )
+ {
+ XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ;
+ XGINew_SetReg1( P3d4 , 0x82 , pVBInfo->CR40[ 11 ][ XGINew_RAMType ] ) ; /* CR82 */
+ XGINew_SetReg1( P3d4 , 0x85 , pVBInfo->CR40[ 12 ][ XGINew_RAMType ] ) ; /* CR85 */
+ XGINew_SetReg1( P3d4 , 0x86 , pVBInfo->CR40[ 13 ][ XGINew_RAMType ] ) ; /* CR86 */
+
+ XGINew_SetReg1( P3d4 , 0x98 , 0x01 ) ;
+ XGINew_SetReg1( P3d4 , 0x9A , 0x02 ) ;
+
+ XGINew_DDR1x_MRS_XG20( P3c4 , pVBInfo) ;
+ }
+ else
+ {
+ XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ;
+
+ switch( HwDeviceExtension->jChipType )
+ {
+ case XG41:
+ case XG42:
+ XGINew_SetReg1( P3d4 , 0x82 , pVBInfo->CR40[ 11 ][ XGINew_RAMType ] ) ; /* CR82 */
+ XGINew_SetReg1( P3d4 , 0x85 , pVBInfo->CR40[ 12 ][ XGINew_RAMType ] ) ; /* CR85 */
+ XGINew_SetReg1( P3d4 , 0x86 , pVBInfo->CR40[ 13 ][ XGINew_RAMType ] ) ; /* CR86 */
+ break ;
+ default:
+ XGINew_SetReg1( P3d4 , 0x82 , 0x88 ) ;
+ XGINew_SetReg1( P3d4 , 0x86 , 0x00 ) ;
+ XGINew_GetReg1( P3d4 , 0x86 ) ; /* Insert read command for delay */
+ XGINew_SetReg1( P3d4 , 0x86 , 0x88 ) ;
+ XGINew_GetReg1( P3d4 , 0x86 ) ;
+ XGINew_SetReg1( P3d4 , 0x86 , pVBInfo->CR40[ 13 ][ XGINew_RAMType ] ) ;
+ XGINew_SetReg1( P3d4 , 0x82 , 0x77 ) ;
+ XGINew_SetReg1( P3d4 , 0x85 , 0x00 ) ;
+ XGINew_GetReg1( P3d4 , 0x85 ) ; /* Insert read command for delay */
+ XGINew_SetReg1( P3d4 , 0x85 , 0x88 ) ;
+ XGINew_GetReg1( P3d4 , 0x85 ) ; /* Insert read command for delay */
+ XGINew_SetReg1( P3d4 , 0x85 , pVBInfo->CR40[ 12 ][ XGINew_RAMType ] ) ; /* CR85 */
+ XGINew_SetReg1( P3d4 , 0x82 , pVBInfo->CR40[ 11 ][ XGINew_RAMType ] ) ; /* CR82 */
+ break ;
+ }
+
+ XGINew_SetReg1( P3d4 , 0x97 , 0x00 ) ;
+ XGINew_SetReg1( P3d4 , 0x98 , 0x01 ) ;
+ XGINew_SetReg1( P3d4 , 0x9A , 0x02 ) ;
+ XGINew_DDR1x_MRS_340( P3c4 , pVBInfo ) ;
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DDR2x_DefaultRegister */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_DDR2x_DefaultRegister( PXGI_HW_DEVICE_INFO HwDeviceExtension , ULONG Port ,PVB_DEVICE_INFO pVBInfo)
+{
+ ULONG P3d4 = Port ,
+ P3c4 = Port - 0x10 ;
+
+ XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ;
+
+ /* 20040906 Hsuan modify CR82, CR85, CR86 for XG42 */
+ switch( HwDeviceExtension->jChipType )
+ {
+ case XG41:
+ case XG42:
+ XGINew_SetReg1( P3d4 , 0x82 , pVBInfo->CR40[ 11 ][ XGINew_RAMType ] ) ; /* CR82 */
+ XGINew_SetReg1( P3d4 , 0x85 , pVBInfo->CR40[ 12 ][ XGINew_RAMType ] ) ; /* CR85 */
+ XGINew_SetReg1( P3d4 , 0x86 , pVBInfo->CR40[ 13 ][ XGINew_RAMType ] ) ; /* CR86 */
+ break ;
+ default:
+ /* keep following setting sequence, each setting in the same reg insert idle */
+ XGINew_SetReg1( P3d4 , 0x82 , 0x88 ) ;
+ XGINew_SetReg1( P3d4 , 0x86 , 0x00 ) ;
+ XGINew_GetReg1( P3d4 , 0x86 ) ; /* Insert read command for delay */
+ XGINew_SetReg1( P3d4 , 0x86 , 0x88 ) ;
+ XGINew_SetReg1( P3d4 , 0x82 , 0x77 ) ;
+ XGINew_SetReg1( P3d4 , 0x85 , 0x00 ) ;
+ XGINew_GetReg1( P3d4 , 0x85 ) ; /* Insert read command for delay */
+ XGINew_SetReg1( P3d4 , 0x85 , 0x88 ) ;
+ XGINew_GetReg1( P3d4 , 0x85 ) ; /* Insert read command for delay */
+ XGINew_SetReg1( P3d4 , 0x85 , pVBInfo->CR40[ 12 ][ XGINew_RAMType ] ) ; /* CR85 */
+ XGINew_SetReg1( P3d4 , 0x82 , pVBInfo->CR40[ 11 ][ XGINew_RAMType ] ) ; /* CR82 */
+ }
+ XGINew_SetReg1( P3d4 , 0x97 , 0x11 ) ;
+ if ( HwDeviceExtension->jChipType == XG42 )
+ {
+ XGINew_SetReg1( P3d4 , 0x98 , 0x01 ) ;
+ }
+ else
+ {
+ XGINew_SetReg1( P3d4 , 0x98 , 0x03 ) ;
+ }
+ XGINew_SetReg1( P3d4 , 0x9A , 0x02 ) ;
+
+ XGINew_DDR2x_MRS_340( P3c4 , pVBInfo ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DDR2_DefaultRegister */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_DDR2_DefaultRegister( PXGI_HW_DEVICE_INFO HwDeviceExtension, ULONG Port , PVB_DEVICE_INFO pVBInfo)
+{
+ ULONG P3d4 = Port ,
+ P3c4 = Port - 0x10 ;
+
+ /* keep following setting sequence, each setting in the same reg insert idle */
+ XGINew_SetReg1( P3d4 , 0x82 , 0x77 ) ;
+ XGINew_SetReg1( P3d4 , 0x86 , 0x00 ) ;
+ XGINew_GetReg1( P3d4 , 0x86 ) ; /* Insert read command for delay */
+ XGINew_SetReg1( P3d4 , 0x86 , 0x88 ) ;
+ XGINew_GetReg1( P3d4 , 0x86 ) ; /* Insert read command for delay */
+ XGINew_SetReg1( P3d4 , 0x86 , pVBInfo->CR40[ 13 ][ XGINew_RAMType ] ) ; /* CR86 */
+ XGINew_SetReg1( P3d4 , 0x82 , 0x77 ) ;
+ XGINew_SetReg1( P3d4 , 0x85 , 0x00 ) ;
+ XGINew_GetReg1( P3d4 , 0x85 ) ; /* Insert read command for delay */
+ XGINew_SetReg1( P3d4 , 0x85 , 0x88 ) ;
+ XGINew_GetReg1( P3d4 , 0x85 ) ; /* Insert read command for delay */
+ XGINew_SetReg1( P3d4 , 0x85 , pVBInfo->CR40[ 12 ][ XGINew_RAMType ] ) ; /* CR85 */
+ if ( HwDeviceExtension->jChipType == XG27 )
+ XGINew_SetReg1( P3d4 , 0x82 , pVBInfo->CR40[ 11 ][ XGINew_RAMType ] ) ; /* CR82 */
+ else
+ XGINew_SetReg1( P3d4 , 0x82 , 0xA8 ) ; /* CR82 */
+
+ XGINew_SetReg1( P3d4 , 0x98 , 0x01 ) ;
+ XGINew_SetReg1( P3d4 , 0x9A , 0x02 ) ;
+ if ( HwDeviceExtension->jChipType == XG27 )
+ XGINew_DDRII_Bootup_XG27( HwDeviceExtension , P3c4 , pVBInfo) ;
+ else
+ XGINew_DDR2_MRS_XG20( HwDeviceExtension , P3c4, pVBInfo ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetDRAMDefaultRegister340 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SetDRAMDefaultRegister340( PXGI_HW_DEVICE_INFO HwDeviceExtension , ULONG Port , PVB_DEVICE_INFO pVBInfo)
+{
+ UCHAR temp , temp1 , temp2 , temp3 ,
+ i , j , k ;
+
+ ULONG P3d4 = Port ,
+ P3c4 = Port - 0x10 ;
+
+ XGINew_SetReg1( P3d4 , 0x6D , pVBInfo->CR40[ 8 ][ XGINew_RAMType ] ) ;
+ XGINew_SetReg1( P3d4 , 0x68 , pVBInfo->CR40[ 5 ][ XGINew_RAMType ] ) ;
+ XGINew_SetReg1( P3d4 , 0x69 , pVBInfo->CR40[ 6 ][ XGINew_RAMType ] ) ;
+ XGINew_SetReg1( P3d4 , 0x6A , pVBInfo->CR40[ 7 ][ XGINew_RAMType ] ) ;
+
+ temp2 = 0 ;
+ for( i = 0 ; i < 4 ; i++ )
+ {
+ temp = pVBInfo->CR6B[ XGINew_RAMType ][ i ] ; /* CR6B DQS fine tune delay */
+ for( j = 0 ; j < 4 ; j++ )
+ {
+ temp1 = ( ( temp >> ( 2 * j ) ) & 0x03 ) << 2 ;
+ temp2 |= temp1 ;
+ XGINew_SetReg1( P3d4 , 0x6B , temp2 ) ;
+ XGINew_GetReg1( P3d4 , 0x6B ) ; /* Insert read command for delay */
+ temp2 &= 0xF0 ;
+ temp2 += 0x10 ;
+ }
+ }
+
+ temp2 = 0 ;
+ for( i = 0 ; i < 4 ; i++ )
+ {
+ temp = pVBInfo->CR6E[ XGINew_RAMType ][ i ] ; /* CR6E DQM fine tune delay */
+ for( j = 0 ; j < 4 ; j++ )
+ {
+ temp1 = ( ( temp >> ( 2 * j ) ) & 0x03 ) << 2 ;
+ temp2 |= temp1 ;
+ XGINew_SetReg1( P3d4 , 0x6E , temp2 ) ;
+ XGINew_GetReg1( P3d4 , 0x6E ) ; /* Insert read command for delay */
+ temp2 &= 0xF0 ;
+ temp2 += 0x10 ;
+ }
+ }
+
+ temp3 = 0 ;
+ for( k = 0 ; k < 4 ; k++ )
+ {
+ XGINew_SetRegANDOR( P3d4 , 0x6E , 0xFC , temp3 ) ; /* CR6E_D[1:0] select channel */
+ temp2 = 0 ;
+ for( i = 0 ; i < 8 ; i++ )
+ {
+ temp = pVBInfo->CR6F[ XGINew_RAMType ][ 8 * k + i ] ; /* CR6F DQ fine tune delay */
+ for( j = 0 ; j < 4 ; j++ )
+ {
+ temp1 = ( temp >> ( 2 * j ) ) & 0x03 ;
+ temp2 |= temp1 ;
+ XGINew_SetReg1( P3d4 , 0x6F , temp2 ) ;
+ XGINew_GetReg1( P3d4 , 0x6F ) ; /* Insert read command for delay */
+ temp2 &= 0xF8 ;
+ temp2 += 0x08 ;
+ }
+ }
+ temp3 += 0x01 ;
+ }
+
+ XGINew_SetReg1( P3d4 , 0x80 , pVBInfo->CR40[ 9 ][ XGINew_RAMType ] ) ; /* CR80 */
+ XGINew_SetReg1( P3d4 , 0x81 , pVBInfo->CR40[ 10 ][ XGINew_RAMType ] ) ; /* CR81 */
+
+ temp2 = 0x80 ;
+ temp = pVBInfo->CR89[ XGINew_RAMType ][ 0 ] ; /* CR89 terminator type select */
+ for( j = 0 ; j < 4 ; j++ )
+ {
+ temp1 = ( temp >> ( 2 * j ) ) & 0x03 ;
+ temp2 |= temp1 ;
+ XGINew_SetReg1( P3d4 , 0x89 , temp2 ) ;
+ XGINew_GetReg1( P3d4 , 0x89 ) ; /* Insert read command for delay */
+ temp2 &= 0xF0 ;
+ temp2 += 0x10 ;
+ }
+
+ temp = pVBInfo->CR89[ XGINew_RAMType ][ 1 ] ;
+ temp1 = temp & 0x03 ;
+ temp2 |= temp1 ;
+ XGINew_SetReg1( P3d4 , 0x89 , temp2 ) ;
+
+ temp = pVBInfo->CR40[ 3 ][ XGINew_RAMType ] ;
+ temp1 = temp & 0x0F ;
+ temp2 = ( temp >> 4 ) & 0x07 ;
+ temp3 = temp & 0x80 ;
+ XGINew_SetReg1( P3d4 , 0x45 , temp1 ) ; /* CR45 */
+ XGINew_SetReg1( P3d4 , 0x99 , temp2 ) ; /* CR99 */
+ XGINew_SetRegOR( P3d4 , 0x40 , temp3 ) ; /* CR40_D[7] */
+ XGINew_SetReg1( P3d4 , 0x41 , pVBInfo->CR40[ 0 ][ XGINew_RAMType ] ) ; /* CR41 */
+
+ if ( HwDeviceExtension->jChipType == XG27 )
+ XGINew_SetReg1( P3d4 , 0x8F , *pVBInfo->pCR8F ) ; /* CR8F */
+
+ for( j = 0 ; j <= 6 ; j++ )
+ XGINew_SetReg1( P3d4 , ( 0x90 + j ) , pVBInfo->CR40[ 14 + j ][ XGINew_RAMType ] ) ; /* CR90 - CR96 */
+
+ for( j = 0 ; j <= 2 ; j++ )
+ XGINew_SetReg1( P3d4 , ( 0xC3 + j ) , pVBInfo->CR40[ 21 + j ][ XGINew_RAMType ] ) ; /* CRC3 - CRC5 */
+
+ for( j = 0 ; j < 2 ; j++ )
+ XGINew_SetReg1( P3d4 , ( 0x8A + j ) , pVBInfo->CR40[ 1 + j ][ XGINew_RAMType ] ) ; /* CR8A - CR8B */
+
+ if ( ( HwDeviceExtension->jChipType == XG41 ) || ( HwDeviceExtension->jChipType == XG42 ) )
+ XGINew_SetReg1( P3d4 , 0x8C , 0x87 ) ;
+
+ XGINew_SetReg1( P3d4 , 0x59 , pVBInfo->CR40[ 4 ][ XGINew_RAMType ] ) ; /* CR59 */
+
+ XGINew_SetReg1( P3d4 , 0x83 , 0x09 ) ; /* CR83 */
+ XGINew_SetReg1( P3d4 , 0x87 , 0x00 ) ; /* CR87 */
+ XGINew_SetReg1( P3d4 , 0xCF , *pVBInfo->pCRCF ) ; /* CRCF */
+ if ( XGINew_RAMType )
+ {
+ //XGINew_SetReg1( P3c4 , 0x17 , 0xC0 ) ; /* SR17 DDRII */
+ XGINew_SetReg1( P3c4 , 0x17 , 0x80 ) ; /* SR17 DDRII */
+ if ( HwDeviceExtension->jChipType == XG27 )
+ XGINew_SetReg1( P3c4 , 0x17 , 0x02 ) ; /* SR17 DDRII */
+
+ }
+ else
+ XGINew_SetReg1( P3c4 , 0x17 , 0x00 ) ; /* SR17 DDR */
+ XGINew_SetReg1( P3c4 , 0x1A , 0x87 ) ; /* SR1A */
+
+ temp = XGINew_GetXG20DRAMType( HwDeviceExtension, pVBInfo) ;
+ if( temp == 0 )
+ XGINew_DDR1x_DefaultRegister( HwDeviceExtension, P3d4, pVBInfo ) ;
+ else
+ {
+ XGINew_SetReg1( P3d4 , 0xB0 , 0x80 ) ; /* DDRII Dual frequency mode */
+ XGINew_DDR2_DefaultRegister( HwDeviceExtension, P3d4, pVBInfo ) ;
+ }
+ XGINew_SetReg1( P3c4 , 0x1B , pVBInfo->SR15[ 3 ][ XGINew_RAMType ] ) ; /* SR1B */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DDR_MRS */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_DDR_MRS(PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT data ;
+
+ PUCHAR volatile pVideoMemory = ( PUCHAR )pVBInfo->ROMAddr ;
+
+ /* SR16 <- 1F,DF,2F,AF */
+ /* yriver modified SR16 <- 0F,DF,0F,AF */
+ /* enable DLL of DDR SD/SGRAM , SR16 D4=1 */
+ data = pVideoMemory[ 0xFB ] ;
+ /* data = XGINew_GetReg1( pVBInfo->P3c4 , 0x16 ) ; */
+
+ data &= 0x0F ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;
+ data |= 0xC0 ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;
+ data &= 0x0F ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;
+ data |= 0x80 ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;
+ data &= 0x0F ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;
+ data |= 0xD0 ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;
+ data &= 0x0F ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;
+ data |= 0xA0 ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;
+/*
+ else {
+ data &= 0x0F;
+ data |= 0x10;
+ XGINew_SetReg1(pVBInfo->P3c4,0x16,data);
+
+ if (!(pVBInfo->SR15[1][XGINew_RAMType] & 0x10))
+ {
+ data &= 0x0F;
+ }
+
+ data |= 0xC0;
+ XGINew_SetReg1(pVBInfo->P3c4,0x16,data);
+
+
+ data &= 0x0F;
+ data |= 0x20;
+ XGINew_SetReg1(pVBInfo->P3c4,0x16,data);
+ if (!(pVBInfo->SR15[1][XGINew_RAMType] & 0x10))
+ {
+ data &= 0x0F;
+ }
+
+ data |= 0x80;
+ XGINew_SetReg1(pVBInfo->P3c4,0x16,data);
+ }
+*/
+}
+
+
+/* check if read cache pointer is correct */
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_VerifyMclk */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_VerifyMclk( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+{
+ PUCHAR pVideoMemory = pVBInfo->FBAddr ;
+ UCHAR i , j ;
+ USHORT Temp , SR21 ;
+
+ pVideoMemory[ 0 ] = 0xaa ; /* alan */
+ pVideoMemory[ 16 ] = 0x55 ; /* note: PCI read cache is off */
+
+ if ( ( pVideoMemory[ 0 ] != 0xaa ) || ( pVideoMemory[ 16 ] != 0x55 ) )
+ {
+ for( i = 0 , j = 16 ; i < 2 ; i++ , j += 16 )
+ {
+ SR21 = XGINew_GetReg1( pVBInfo->P3c4 , 0x21 ) ;
+ Temp = SR21 & 0xFB ; /* disable PCI post write buffer empty gating */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , Temp ) ;
+
+ Temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x3C ) ;
+ Temp |= 0x01 ; /* MCLK reset */
+
+
+ Temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x3C ) ;
+ Temp &= 0xFE ; /* MCLK normal operation */
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , SR21 ) ;
+
+ pVideoMemory[ 16 + j ] = j ;
+ if ( pVideoMemory[ 16 + j ] == j )
+ {
+ pVideoMemory[ j ] = j ;
+ break ;
+ }
+ }
+ }
+}
+
+
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetDRAMSize_340 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SetDRAMSize_340( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT data ;
+
+ pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+ pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+
+ XGISetModeNew( HwDeviceExtension , 0x2e ) ;
+
+
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x21 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , ( USHORT )( data & 0xDF ) ) ; /* disable read cache */
+ XGI_DisplayOff( HwDeviceExtension, pVBInfo );
+
+ /*data = XGINew_GetReg1( pVBInfo->P3c4 , 0x1 ) ;*/
+ /*data |= 0x20 ;*/
+ /*XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , data ) ;*/ /* Turn OFF Display */
+ XGINew_DDRSizing340( HwDeviceExtension, pVBInfo ) ;
+ data=XGINew_GetReg1( pVBInfo->P3c4 , 0x21 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , ( USHORT )( data | 0x20 ) ) ; /* enable read cache */
+
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SetDRAMSize_310( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT data ;
+ pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ,
+ pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+#ifdef XGI301
+ /* XGINew_SetReg1( pVBInfo->P3d4 , 0x30 , 0x40 ) ; */
+#endif
+
+#ifdef XGI302 /* alan,should change value */
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x30 , 0x4D ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x31 , 0xc0 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x34 , 0x3F ) ;
+#endif
+
+ XGISetModeNew( HwDeviceExtension , 0x2e ) ;
+
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x21 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , ( USHORT )( data & 0xDF ) ) ; /* disable read cache */
+
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x1 ) ;
+ data |= 0x20 ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , data ) ; /* Turn OFF Display */
+
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x16 ) ;
+
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , ( USHORT )( data | 0x0F ) ) ; /* assume lowest speed DRAM */
+
+ XGINew_SetDRAMModeRegister( pVBInfo ) ;
+ XGINew_DisableRefresh( HwDeviceExtension, pVBInfo ) ;
+ XGINew_CheckBusWidth_310( pVBInfo) ;
+ XGINew_VerifyMclk( HwDeviceExtension, pVBInfo ) ; /* alan 2000/7/3 */
+
+
+
+ if ( XGINew_Get310DRAMType( pVBInfo ) < 2 )
+ {
+ XGINew_SDRSizing( pVBInfo ) ;
+ }
+ else
+ {
+ XGINew_DDRSizing( pVBInfo) ;
+ }
+
+
+
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , pVBInfo->SR15[ 1 ][ XGINew_RAMType ] ) ; /* restore SR16 */
+
+ XGINew_EnableRefresh( HwDeviceExtension, pVBInfo ) ;
+ data=XGINew_GetReg1( pVBInfo->P3c4 ,0x21 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , ( USHORT )( data | 0x20 ) ) ; /* enable read cache */
+}
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetDRAMModeRegister340 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+
+void XGINew_SetDRAMModeRegister340( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+{
+ UCHAR data ;
+ VB_DEVICE_INFO VBINF;
+ PVB_DEVICE_INFO pVBInfo = &VBINF;
+ pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+ pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+ pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
+ pVBInfo->ISXPDOS = 0 ;
+
+ pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
+ pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
+ pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
+ pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
+ pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
+ pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
+ pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
+ pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
+ pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
+ pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
+ pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
+ pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
+ pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
+ pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
+ pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
+ pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
+ pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
+ if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */
+ XGI_GetVBType( pVBInfo ) ; /* Run XGI_GetVBType before InitTo330Pointer */
+
+ InitTo330Pointer(HwDeviceExtension->jChipType,pVBInfo);
+
+ ReadVBIOSTablData( HwDeviceExtension->jChipType , pVBInfo) ;
+
+ if ( XGINew_GetXG20DRAMType( HwDeviceExtension, pVBInfo) == 0 )
+ {
+ data = ( XGINew_GetReg1( pVBInfo->P3c4 , 0x39 ) & 0x02 ) >> 1 ;
+ if ( data == 0x01 )
+ XGINew_DDR2x_MRS_340( pVBInfo->P3c4, pVBInfo ) ;
+ else
+ XGINew_DDR1x_MRS_340( pVBInfo->P3c4, pVBInfo ) ;
+ }
+ else
+ XGINew_DDR2_MRS_XG20( HwDeviceExtension, pVBInfo->P3c4, pVBInfo);
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , 0x03 ) ;
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetDRAMModeRegister */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SetDRAMModeRegister( PVB_DEVICE_INFO pVBInfo)
+{
+ if ( XGINew_Get310DRAMType( pVBInfo ) < 2 )
+ {
+ XGINew_SDR_MRS(pVBInfo ) ;
+ }
+ else
+ {
+ /* SR16 <- 0F,CF,0F,8F */
+ XGINew_DDR_MRS( pVBInfo ) ;
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DisableRefresh */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_DisableRefresh( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT data ;
+
+
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x1B ) ;
+ data &= 0xF8 ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , data ) ;
+
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_EnableRefresh */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_EnableRefresh( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+{
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , pVBInfo->SR15[ 3 ][ XGINew_RAMType ] ) ; /* SR1B */
+
+
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DisableChannelInterleaving */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_DisableChannelInterleaving( int index , USHORT XGINew_DDRDRAM_TYPE[][ 5 ] , PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT data ;
+
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x15 ) ;
+ data &= 0x1F ;
+
+ switch( XGINew_DDRDRAM_TYPE[ index ][ 3 ] )
+ {
+ case 64:
+ data |= 0 ;
+ break ;
+ case 32:
+ data |= 0x20 ;
+ break ;
+ case 16:
+ data |= 0x40 ;
+ break ;
+ case 4:
+ data |= 0x60 ;
+ break ;
+ default:
+ break ;
+ }
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x15 , data ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetDRAMSizingType */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SetDRAMSizingType( int index , USHORT DRAMTYPE_TABLE[][ 5 ] ,PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT data ;
+
+ data = DRAMTYPE_TABLE[ index ][ 4 ] ;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x13 , 0x80 , data ) ;
+ DelayUS( 15 ) ;
+ /* should delay 50 ns */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_CheckBusWidth_310 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_CheckBusWidth_310( PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT data ;
+ PULONG volatile pVideoMemory ;
+
+ pVideoMemory = (PULONG) pVBInfo->FBAddr;
+
+ if ( XGINew_Get310DRAMType( pVBInfo ) < 2 )
+ {
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x00 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x12 ) ;
+ /* should delay */
+ XGINew_SDR_MRS( pVBInfo ) ;
+
+ XGINew_ChannelAB = 0 ;
+ XGINew_DataBusWidth = 128 ;
+ pVideoMemory[ 0 ] = 0x01234567L ;
+ pVideoMemory[ 1 ] = 0x456789ABL ;
+ pVideoMemory[ 2 ] = 0x89ABCDEFL ;
+ pVideoMemory[ 3 ] = 0xCDEF0123L ;
+ pVideoMemory[ 4 ] = 0x55555555L ;
+ pVideoMemory[ 5 ] = 0x55555555L ;
+ pVideoMemory[ 6 ] = 0xFFFFFFFFL ;
+ pVideoMemory[ 7 ] = 0xFFFFFFFFL ;
+
+ if ( ( pVideoMemory[ 3 ] != 0xCDEF0123L ) || ( pVideoMemory[ 2 ] != 0x89ABCDEFL ) )
+ {
+ /* ChannelA64Bit */
+ XGINew_DataBusWidth = 64 ;
+ XGINew_ChannelAB = 0 ;
+ data=XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , ( USHORT )( data & 0xFD ) ) ;
+ }
+
+ if ( ( pVideoMemory[ 1 ] != 0x456789ABL ) || ( pVideoMemory[ 0 ] != 0x01234567L ) )
+ {
+ /* ChannelB64Bit */
+ XGINew_DataBusWidth = 64 ;
+ XGINew_ChannelAB = 1 ;
+ data=XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , ( USHORT )( ( data & 0xFD ) | 0x01 ) ) ;
+ }
+
+ return ;
+ }
+ else
+ {
+ /* DDR Dual channel */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x00 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x02 ) ; /* Channel A, 64bit */
+ /* should delay */
+ XGINew_DDR_MRS( pVBInfo ) ;
+
+ XGINew_ChannelAB = 0 ;
+ XGINew_DataBusWidth = 64 ;
+ pVideoMemory[ 0 ] = 0x01234567L ;
+ pVideoMemory[ 1 ] = 0x456789ABL ;
+ pVideoMemory[ 2 ] = 0x89ABCDEFL ;
+ pVideoMemory[ 3 ] = 0xCDEF0123L ;
+ pVideoMemory[ 4 ] = 0x55555555L ;
+ pVideoMemory[ 5 ] = 0x55555555L ;
+ pVideoMemory[ 6 ] = 0xAAAAAAAAL ;
+ pVideoMemory[ 7 ] = 0xAAAAAAAAL ;
+
+ if ( pVideoMemory[ 1 ] == 0x456789ABL )
+ {
+ if ( pVideoMemory[ 0 ] == 0x01234567L )
+ {
+ /* Channel A 64bit */
+ return ;
+ }
+ }
+ else
+ {
+ if ( pVideoMemory[ 0 ] == 0x01234567L )
+ {
+ /* Channel A 32bit */
+ XGINew_DataBusWidth = 32 ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x00 ) ;
+ return ;
+ }
+ }
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x03 ) ; /* Channel B, 64bit */
+ XGINew_DDR_MRS( pVBInfo);
+
+ XGINew_ChannelAB = 1 ;
+ XGINew_DataBusWidth = 64 ;
+ pVideoMemory[ 0 ] = 0x01234567L ;
+ pVideoMemory[ 1 ] = 0x456789ABL ;
+ pVideoMemory[ 2 ] = 0x89ABCDEFL ;
+ pVideoMemory[ 3 ] = 0xCDEF0123L ;
+ pVideoMemory[ 4 ] = 0x55555555L ;
+ pVideoMemory[ 5 ] = 0x55555555L ;
+ pVideoMemory[ 6 ] = 0xAAAAAAAAL ;
+ pVideoMemory[ 7 ] = 0xAAAAAAAAL ;
+
+ if ( pVideoMemory[ 1 ] == 0x456789ABL )
+ {
+ /* Channel B 64 */
+ if ( pVideoMemory[ 0 ] == 0x01234567L )
+ {
+ /* Channel B 64bit */
+ return ;
+ }
+ else
+ {
+ /* error */
+ }
+ }
+ else
+ {
+ if ( pVideoMemory[ 0 ] == 0x01234567L )
+ {
+ /* Channel B 32 */
+ XGINew_DataBusWidth = 32 ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x01 ) ;
+ }
+ else
+ {
+ /* error */
+ }
+ }
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetRank */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int XGINew_SetRank( int index , UCHAR RankNo , UCHAR XGINew_ChannelAB , USHORT DRAMTYPE_TABLE[][ 5 ] , PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT data ;
+ int RankSize ;
+
+ if ( ( RankNo == 2 ) && ( DRAMTYPE_TABLE[ index ][ 0 ] == 2 ) )
+ return 0 ;
+
+ RankSize = DRAMTYPE_TABLE[ index ][ 3 ] / 2 * XGINew_DataBusWidth / 32 ;
+
+ if ( ( RankNo * RankSize ) <= 128 )
+ {
+ data = 0 ;
+
+ while( ( RankSize >>= 1 ) > 0 )
+ {
+ data += 0x10 ;
+ }
+ data |= ( RankNo - 1 ) << 2 ;
+ data |= ( XGINew_DataBusWidth / 64 ) & 2 ;
+ data |= XGINew_ChannelAB ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , data ) ;
+ /* should delay */
+ XGINew_SDR_MRS( pVBInfo ) ;
+ return( 1 ) ;
+ }
+ else
+ return( 0 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetDDRChannel */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int XGINew_SetDDRChannel( int index , UCHAR ChannelNo , UCHAR XGINew_ChannelAB , USHORT DRAMTYPE_TABLE[][ 5 ] , PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT data ;
+ int RankSize ;
+
+ RankSize = DRAMTYPE_TABLE[index][3]/2 * XGINew_DataBusWidth/32;
+ /* RankSize = DRAMTYPE_TABLE[ index ][ 3 ] ; */
+ if ( ChannelNo * RankSize <= 128 )
+ {
+ data = 0 ;
+ while( ( RankSize >>= 1 ) > 0 )
+ {
+ data += 0x10 ;
+ }
+
+ if ( ChannelNo == 2 )
+ data |= 0x0C ;
+
+ data |= ( XGINew_DataBusWidth / 32 ) & 2 ;
+ data |= XGINew_ChannelAB ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , data ) ;
+ /* should delay */
+ XGINew_DDR_MRS( pVBInfo ) ;
+ return( 1 ) ;
+ }
+ else
+ return( 0 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_CheckColumn */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int XGINew_CheckColumn( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
+{
+ int i ;
+ ULONG Increment , Position ;
+
+ /* Increment = 1 << ( DRAMTYPE_TABLE[ index ][ 2 ] + XGINew_DataBusWidth / 64 + 1 ) ; */
+ Increment = 1 << ( 10 + XGINew_DataBusWidth / 64 ) ;
+
+ for( i = 0 , Position = 0 ; i < 2 ; i++ )
+ {
+ *( ( PULONG )( pVBInfo->FBAddr + Position ) ) = Position ;
+ Position += Increment ;
+ }
+
+#ifdef WIN2000 /* chiawen for linux solution */
+ DelayUS( 100 ) ;
+#endif
+
+ for( i = 0 , Position = 0 ; i < 2 ; i++ )
+ {
+ /* if ( pVBInfo->FBAddr[ Position ] != Position ) */
+ if ( ( *( PULONG )( pVBInfo->FBAddr + Position ) ) != Position )
+ return( 0 ) ;
+ Position += Increment ;
+ }
+ return( 1 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_CheckBanks */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int XGINew_CheckBanks( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
+{
+ int i ;
+ ULONG Increment , Position ;
+
+ Increment = 1 << ( DRAMTYPE_TABLE[ index ][ 2 ] + XGINew_DataBusWidth / 64 + 2 ) ;
+
+ for( i = 0 , Position = 0 ; i < 4 ; i++ )
+ {
+ /* pVBInfo->FBAddr[ Position ] = Position ; */
+ *( ( PULONG )( pVBInfo->FBAddr + Position ) ) = Position ;
+ Position += Increment ;
+ }
+
+ for( i = 0 , Position = 0 ; i < 4 ; i++ )
+ {
+ /* if (pVBInfo->FBAddr[ Position ] != Position ) */
+ if ( ( *( PULONG )( pVBInfo->FBAddr + Position ) ) != Position )
+ return( 0 ) ;
+ Position += Increment ;
+ }
+ return( 1 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_CheckRank */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int XGINew_CheckRank( int RankNo , int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
+{
+ int i ;
+ ULONG Increment , Position ;
+
+ Increment = 1 << ( DRAMTYPE_TABLE[ index ][ 2 ] + DRAMTYPE_TABLE[ index ][ 1 ] +
+ DRAMTYPE_TABLE[ index ][ 0 ] + XGINew_DataBusWidth / 64 + RankNo ) ;
+
+ for( i = 0 , Position = 0 ; i < 2 ; i++ )
+ {
+ /* pVBInfo->FBAddr[ Position ] = Position ; */
+ /* *( ( PULONG )( pVBInfo->FBAddr ) ) = Position ; */
+ *( ( PULONG )( pVBInfo->FBAddr + Position ) ) = Position ;
+ Position += Increment ;
+ }
+
+ for( i = 0 , Position = 0 ; i < 2 ; i++ )
+ {
+ /* if ( pVBInfo->FBAddr[ Position ] != Position ) */
+ /* if ( ( *( PULONG )( pVBInfo->FBAddr ) ) != Position ) */
+ if ( ( *( PULONG )( pVBInfo->FBAddr + Position ) ) != Position )
+ return( 0 ) ;
+ Position += Increment ;
+ }
+ return( 1 );
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_CheckDDRRank */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int XGINew_CheckDDRRank( int RankNo , int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
+{
+ ULONG Increment , Position ;
+ USHORT data ;
+
+ Increment = 1 << ( DRAMTYPE_TABLE[ index ][ 2 ] + DRAMTYPE_TABLE[ index ][ 1 ] +
+ DRAMTYPE_TABLE[ index ][ 0 ] + XGINew_DataBusWidth / 64 + RankNo ) ;
+
+ Increment += Increment / 2 ;
+
+ Position = 0;
+ *( ( PULONG )( pVBInfo->FBAddr + Position + 0 ) ) = 0x01234567 ;
+ *( ( PULONG )( pVBInfo->FBAddr + Position + 1 ) ) = 0x456789AB ;
+ *( ( PULONG )( pVBInfo->FBAddr + Position + 2 ) ) = 0x55555555 ;
+ *( ( PULONG )( pVBInfo->FBAddr + Position + 3 ) ) = 0x55555555 ;
+ *( ( PULONG )( pVBInfo->FBAddr + Position + 4 ) ) = 0xAAAAAAAA ;
+ *( ( PULONG )( pVBInfo->FBAddr + Position + 5 ) ) = 0xAAAAAAAA ;
+
+ if ( ( *( PULONG )( pVBInfo->FBAddr + 1 ) ) == 0x456789AB )
+ return( 1 ) ;
+
+ if ( ( *( PULONG )( pVBInfo->FBAddr + 0 ) ) == 0x01234567 )
+ return( 0 ) ;
+
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) ;
+ data &= 0xF3 ;
+ data |= 0x0E ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , data ) ;
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x15 ) ;
+ data += 0x20 ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x15 , data ) ;
+
+ return( 1 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_CheckRanks */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int XGINew_CheckRanks( int RankNo , int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
+{
+ int r ;
+
+ for( r = RankNo ; r >= 1 ; r-- )
+ {
+ if ( !XGINew_CheckRank( r , index , DRAMTYPE_TABLE, pVBInfo ) )
+ return( 0 ) ;
+ }
+
+ if ( !XGINew_CheckBanks( index , DRAMTYPE_TABLE, pVBInfo ) )
+ return( 0 ) ;
+
+ if ( !XGINew_CheckColumn( index , DRAMTYPE_TABLE, pVBInfo ) )
+ return( 0 ) ;
+
+ return( 1 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_CheckDDRRanks */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int XGINew_CheckDDRRanks( int RankNo , int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
+{
+ int r ;
+
+ for( r = RankNo ; r >= 1 ; r-- )
+ {
+ if ( !XGINew_CheckDDRRank( r , index , DRAMTYPE_TABLE, pVBInfo ) )
+ return( 0 ) ;
+ }
+
+ if ( !XGINew_CheckBanks( index , DRAMTYPE_TABLE, pVBInfo ) )
+ return( 0 ) ;
+
+ if ( !XGINew_CheckColumn( index , DRAMTYPE_TABLE, pVBInfo ) )
+ return( 0 ) ;
+
+ return( 1 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int XGINew_SDRSizing(PVB_DEVICE_INFO pVBInfo)
+{
+ int i ;
+ UCHAR j ;
+
+ for( i = 0 ; i < 13 ; i++ )
+ {
+ XGINew_SetDRAMSizingType( i , XGINew_SDRDRAM_TYPE , pVBInfo) ;
+
+ for( j = 2 ; j > 0 ; j-- )
+ {
+ if ( !XGINew_SetRank( i , ( UCHAR )j , XGINew_ChannelAB , XGINew_SDRDRAM_TYPE , pVBInfo) )
+ continue ;
+ else
+ {
+ if ( XGINew_CheckRanks( j , i , XGINew_SDRDRAM_TYPE, pVBInfo) )
+ return( 1 ) ;
+ }
+ }
+ }
+ return( 0 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetDRAMSizeReg */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+USHORT XGINew_SetDRAMSizeReg( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT data = 0 , memsize = 0 ;
+ int RankSize ;
+ UCHAR ChannelNo ;
+
+ RankSize = DRAMTYPE_TABLE[ index ][ 3 ] * XGINew_DataBusWidth / 32 ;
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x13 ) ;
+ data &= 0x80 ;
+
+ if ( data == 0x80 )
+ RankSize *= 2 ;
+
+ data = 0 ;
+
+ if( XGINew_ChannelAB == 3 )
+ ChannelNo = 4 ;
+ else
+ ChannelNo = XGINew_ChannelAB ;
+
+ if ( ChannelNo * RankSize <= 256 )
+ {
+ while( ( RankSize >>= 1 ) > 0 )
+ {
+ data += 0x10 ;
+ }
+
+ memsize = data >> 4 ;
+
+ /* [2004/03/25] Vicent, Fix DRAM Sizing Error */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , ( XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) & 0x0F ) | ( data & 0xF0 ) ) ;
+
+ /* data |= XGINew_ChannelAB << 2 ; */
+ /* data |= ( XGINew_DataBusWidth / 64 ) << 1 ; */
+ /* XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , data ) ; */
+
+ /* should delay */
+ /* XGINew_SetDRAMModeRegister340( pVBInfo ) ; */
+ }
+ return( memsize ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetDRAMSize20Reg */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+USHORT XGINew_SetDRAMSize20Reg( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT data = 0 , memsize = 0 ;
+ int RankSize ;
+ UCHAR ChannelNo ;
+
+ RankSize = DRAMTYPE_TABLE[ index ][ 3 ] * XGINew_DataBusWidth / 8 ;
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x13 ) ;
+ data &= 0x80 ;
+
+ if ( data == 0x80 )
+ RankSize *= 2 ;
+
+ data = 0 ;
+
+ if( XGINew_ChannelAB == 3 )
+ ChannelNo = 4 ;
+ else
+ ChannelNo = XGINew_ChannelAB ;
+
+ if ( ChannelNo * RankSize <= 256 )
+ {
+ while( ( RankSize >>= 1 ) > 0 )
+ {
+ data += 0x10 ;
+ }
+
+ memsize = data >> 4 ;
+
+ /* [2004/03/25] Vicent, Fix DRAM Sizing Error */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , ( XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) & 0x0F ) | ( data & 0xF0 ) ) ;
+ DelayUS( 15 ) ;
+
+ /* data |= XGINew_ChannelAB << 2 ; */
+ /* data |= ( XGINew_DataBusWidth / 64 ) << 1 ; */
+ /* XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , data ) ; */
+
+ /* should delay */
+ /* XGINew_SetDRAMModeRegister340( pVBInfo ) ; */
+ }
+ return( memsize ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_ReadWriteRest */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int XGINew_ReadWriteRest( USHORT StopAddr , USHORT StartAddr, PVB_DEVICE_INFO pVBInfo)
+{
+ int i ;
+ ULONG Position = 0 ;
+
+ *( ( PULONG )( pVBInfo->FBAddr + Position ) ) = Position ;
+
+ for( i = StartAddr ; i <= StopAddr ; i++ )
+ {
+ Position = 1 << i ;
+ *( ( PULONG )( pVBInfo->FBAddr + Position ) ) = Position ;
+ }
+
+ DelayUS( 500 ) ; /* [Vicent] 2004/04/16. Fix #1759 Memory Size error in Multi-Adapter. */
+
+ Position = 0 ;
+
+ if ( ( *( PULONG )( pVBInfo->FBAddr + Position ) ) != Position )
+ return( 0 ) ;
+
+ for( i = StartAddr ; i <= StopAddr ; i++ )
+ {
+ Position = 1 << i ;
+ if ( ( *( PULONG )( pVBInfo->FBAddr + Position ) ) != Position )
+ return( 0 ) ;
+ }
+ return( 1 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_CheckFrequence */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+UCHAR XGINew_CheckFrequence( PVB_DEVICE_INFO pVBInfo )
+{
+ UCHAR data ;
+
+ data = XGINew_GetReg1( pVBInfo->P3d4 , 0x97 ) ;
+
+ if ( ( data & 0x10 ) == 0 )
+ {
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x39 ) ;
+ data = ( data & 0x02 ) >> 1 ;
+ return( data ) ;
+ }
+ else
+ return( data & 0x01 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_CheckChannel */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_CheckChannel( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+{
+ UCHAR data;
+
+ switch( HwDeviceExtension->jChipType )
+ {
+ case XG20:
+ case XG21:
+ data = XGINew_GetReg1( pVBInfo->P3d4 , 0x97 ) ;
+ data = data & 0x01;
+ XGINew_ChannelAB = 1 ; /* XG20 "JUST" one channel */
+
+ if ( data == 0 ) /* Single_32_16 */
+ {
+
+ if (( HwDeviceExtension->ulVideoMemorySize - 1 ) > 0x1000000)
+ {
+
+ XGINew_DataBusWidth = 32 ; /* 32 bits */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xB1 ) ; /* 22bit + 2 rank + 32bit */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x52 ) ;
+ DelayUS( 15 ) ;
+
+ if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
+ return ;
+
+ if (( HwDeviceExtension->ulVideoMemorySize - 1 ) > 0x800000)
+ {
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x31 ) ; /* 22bit + 1 rank + 32bit */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x42 ) ;
+ DelayUS( 15 ) ;
+
+ if ( XGINew_ReadWriteRest( 23 , 23 , pVBInfo ) == 1 )
+ return ;
+ }
+ }
+
+ if (( HwDeviceExtension->ulVideoMemorySize - 1 ) > 0x800000)
+ {
+ XGINew_DataBusWidth = 16 ; /* 16 bits */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xB1 ) ; /* 22bit + 2 rank + 16bit */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x41 ) ;
+ DelayUS( 15 ) ;
+
+ if ( XGINew_ReadWriteRest( 23 , 22 , pVBInfo ) == 1 )
+ return ;
+ else
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x31 ) ;
+ DelayUS( 15 ) ;
+ }
+
+ }
+ else /* Dual_16_8 */
+ {
+ if (( HwDeviceExtension->ulVideoMemorySize - 1 ) > 0x800000)
+ {
+
+ XGINew_DataBusWidth = 16 ; /* 16 bits */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xB1 ) ; /* (0x31:12x8x2) 22bit + 2 rank */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x41 ) ; /* 0x41:16Mx16 bit*/
+ DelayUS( 15 ) ;
+
+ if ( XGINew_ReadWriteRest( 23 , 22 , pVBInfo ) == 1 )
+ return ;
+
+ if (( HwDeviceExtension->ulVideoMemorySize - 1 ) > 0x400000)
+ {
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x31 ) ; /* (0x31:12x8x2) 22bit + 1 rank */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x31 ) ; /* 0x31:8Mx16 bit*/
+ DelayUS( 15 ) ;
+
+ if ( XGINew_ReadWriteRest( 22 , 22 , pVBInfo ) == 1 )
+ return ;
+ }
+ }
+
+
+ if (( HwDeviceExtension->ulVideoMemorySize - 1 ) > 0x400000)
+ {
+ XGINew_DataBusWidth = 8 ; /* 8 bits */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xB1 ) ; /* (0x31:12x8x2) 22bit + 2 rank */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x30 ) ; /* 0x30:8Mx8 bit*/
+ DelayUS( 15 ) ;
+
+ if ( XGINew_ReadWriteRest( 22 , 21 , pVBInfo ) == 1 )
+ return ;
+ else
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x31 ) ; /* (0x31:12x8x2) 22bit + 1 rank */
+ DelayUS( 15 ) ;
+ }
+ }
+ break ;
+
+ case XG27:
+ XGINew_DataBusWidth = 16 ; /* 16 bits */
+ XGINew_ChannelAB = 1 ; /* Single channel */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x51 ) ; /* 32Mx16 bit*/
+ break ;
+ case XG41:
+ if ( XGINew_CheckFrequence(pVBInfo) == 1 )
+ {
+ XGINew_DataBusWidth = 32 ; /* 32 bits */
+ XGINew_ChannelAB = 3 ; /* Quad Channel */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x4C ) ;
+
+ if ( XGINew_ReadWriteRest( 25 , 23 , pVBInfo ) == 1 )
+ return ;
+
+ XGINew_ChannelAB = 2 ; /* Dual channels */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x48 ) ;
+
+ if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
+ return ;
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x49 ) ;
+
+ if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
+ return ;
+
+ XGINew_ChannelAB = 3 ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x3C ) ;
+
+ if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
+ return ;
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x38 ) ;
+
+ if ( XGINew_ReadWriteRest( 8 , 4 , pVBInfo ) == 1 )
+ return ;
+ else
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x39 ) ;
+ }
+ else
+ { /* DDR */
+ XGINew_DataBusWidth = 64 ; /* 64 bits */
+ XGINew_ChannelAB = 2 ; /* Dual channels */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x5A ) ;
+
+ if ( XGINew_ReadWriteRest( 25 , 24 , pVBInfo ) == 1 )
+ return ;
+
+ XGINew_ChannelAB = 1 ; /* Single channels */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x52 ) ;
+
+ if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
+ return ;
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x53 ) ;
+
+ if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
+ return ;
+
+ XGINew_ChannelAB = 2 ; /* Dual channels */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x4A ) ;
+
+ if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
+ return ;
+
+ XGINew_ChannelAB = 1 ; /* Single channels */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x42 ) ;
+
+ if ( XGINew_ReadWriteRest( 8 , 4 , pVBInfo ) == 1 )
+ return ;
+ else
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x43 ) ;
+ }
+
+ break ;
+
+ case XG42:
+/*
+ XG42 SR14 D[3] Reserve
+ D[2] = 1, Dual Channel
+ = 0, Single Channel
+
+ It's Different from Other XG40 Series.
+*/
+ if ( XGINew_CheckFrequence(pVBInfo) == 1 ) /* DDRII, DDR2x */
+ {
+ XGINew_DataBusWidth = 32 ; /* 32 bits */
+ XGINew_ChannelAB = 2 ; /* 2 Channel */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x44 ) ;
+
+ if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
+ return ;
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x34 ) ;
+ if ( XGINew_ReadWriteRest( 23 , 22 , pVBInfo ) == 1 )
+ return ;
+
+ XGINew_ChannelAB = 1 ; /* Single Channel */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x40 ) ;
+
+ if ( XGINew_ReadWriteRest( 23 , 22 , pVBInfo ) == 1 )
+ return ;
+ else
+ {
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x30 ) ;
+ }
+ }
+ else
+ { /* DDR */
+ XGINew_DataBusWidth = 64 ; /* 64 bits */
+ XGINew_ChannelAB = 1 ; /* 1 channels */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x52 ) ;
+
+ if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
+ return ;
+ else
+ {
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x42 ) ;
+ }
+ }
+
+ break ;
+
+ default: /* XG40 */
+
+ if ( XGINew_CheckFrequence(pVBInfo) == 1 ) /* DDRII */
+ {
+ XGINew_DataBusWidth = 32 ; /* 32 bits */
+ XGINew_ChannelAB = 3 ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x4C ) ;
+
+ if ( XGINew_ReadWriteRest( 25 , 23 , pVBInfo ) == 1 )
+ return ;
+
+ XGINew_ChannelAB = 2 ; /* 2 channels */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x48 ) ;
+
+ if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
+ return ;
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x3C ) ;
+
+ if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
+ XGINew_ChannelAB = 3 ; /* 4 channels */
+ else
+ {
+ XGINew_ChannelAB = 2 ; /* 2 channels */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x38 ) ;
+ }
+ }
+ else
+ { /* DDR */
+ XGINew_DataBusWidth = 64 ; /* 64 bits */
+ XGINew_ChannelAB = 2 ; /* 2 channels */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x5A ) ;
+
+ if ( XGINew_ReadWriteRest( 25 , 24 , pVBInfo ) == 1 )
+ return ;
+ else
+ {
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x4A ) ;
+ }
+ }
+ break ;
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DDRSizing340 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int XGINew_DDRSizing340( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+{
+ int i ;
+ USHORT memsize , addr ;
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x15 , 0x00 ) ; /* noninterleaving */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x1C , 0x00 ) ; /* nontiling */
+ XGINew_CheckChannel( HwDeviceExtension, pVBInfo ) ;
+
+
+ if ( HwDeviceExtension->jChipType >= XG20 )
+ {
+ for( i = 0 ; i < 12 ; i++ )
+ {
+ XGINew_SetDRAMSizingType( i , XGINew_DDRDRAM_TYPE20, pVBInfo ) ;
+ memsize = XGINew_SetDRAMSize20Reg( i , XGINew_DDRDRAM_TYPE20, pVBInfo ) ;
+ if ( memsize == 0 )
+ continue ;
+
+ addr = memsize + ( XGINew_ChannelAB - 2 ) + 20 ;
+ if ( ( HwDeviceExtension->ulVideoMemorySize - 1 ) < ( ULONG )( 1 << addr ) )
+ continue ;
+
+ if ( XGINew_ReadWriteRest( addr , 5, pVBInfo ) == 1 )
+ return( 1 ) ;
+ }
+ }
+ else
+ {
+ for( i = 0 ; i < 4 ; i++ )
+ {
+ XGINew_SetDRAMSizingType( i , XGINew_DDRDRAM_TYPE340, pVBInfo ) ;
+ memsize = XGINew_SetDRAMSizeReg( i , XGINew_DDRDRAM_TYPE340, pVBInfo ) ;
+
+ if ( memsize == 0 )
+ continue ;
+
+ addr = memsize + ( XGINew_ChannelAB - 2 ) + 20 ;
+ if ( ( HwDeviceExtension->ulVideoMemorySize - 1 ) < ( ULONG )( 1 << addr ) )
+ continue ;
+
+ if ( XGINew_ReadWriteRest( addr , 9, pVBInfo ) == 1 )
+ return( 1 ) ;
+ }
+ }
+ return( 0 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DDRSizing */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int XGINew_DDRSizing(PVB_DEVICE_INFO pVBInfo)
+{
+ int i ;
+ UCHAR j ;
+
+ for( i = 0 ; i < 4 ; i++ )
+ {
+ XGINew_SetDRAMSizingType( i , XGINew_DDRDRAM_TYPE, pVBInfo ) ;
+ XGINew_DisableChannelInterleaving( i , XGINew_DDRDRAM_TYPE , pVBInfo) ;
+ for( j = 2 ; j > 0 ; j-- )
+ {
+ XGINew_SetDDRChannel( i , j , XGINew_ChannelAB , XGINew_DDRDRAM_TYPE , pVBInfo ) ;
+ if ( !XGINew_SetRank( i , ( UCHAR )j , XGINew_ChannelAB , XGINew_DDRDRAM_TYPE, pVBInfo ) )
+ continue ;
+ else
+ {
+ if ( XGINew_CheckDDRRanks( j , i , XGINew_DDRDRAM_TYPE, pVBInfo ) )
+ return( 1 ) ;
+ }
+ }
+ }
+ return( 0 ) ;
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetMemoryClock */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SetMemoryClock( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+{
+
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x28 , pVBInfo->MCLKData[ XGINew_RAMType ].SR28 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x29 , pVBInfo->MCLKData[ XGINew_RAMType ].SR29 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2A , pVBInfo->MCLKData[ XGINew_RAMType ].SR2A ) ;
+
+
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , pVBInfo->ECLKData[ XGINew_RAMType ].SR2E ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2F , pVBInfo->ECLKData[ XGINew_RAMType ].SR2F ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x30 , pVBInfo->ECLKData[ XGINew_RAMType ].SR30 ) ;
+
+ /* [Vicent] 2004/07/07, When XG42 ECLK = MCLK = 207MHz, Set SR32 D[1:0] = 10b */
+ /* [Hsuan] 2004/08/20, Modify SR32 value, when MCLK=207MHZ, ELCK=250MHz, Set SR32 D[1:0] = 10b */
+ if ( HwDeviceExtension->jChipType == XG42 )
+ {
+ if ( ( pVBInfo->MCLKData[ XGINew_RAMType ].SR28 == 0x1C ) && ( pVBInfo->MCLKData[ XGINew_RAMType ].SR29 == 0x01 )
+ && ( ( ( pVBInfo->ECLKData[ XGINew_RAMType ].SR2E == 0x1C ) && ( pVBInfo->ECLKData[ XGINew_RAMType ].SR2F == 0x01 ) )
+ || ( ( pVBInfo->ECLKData[ XGINew_RAMType ].SR2E == 0x22 ) && ( pVBInfo->ECLKData[ XGINew_RAMType ].SR2F == 0x01 ) ) ) )
+ {
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x32 , ( ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x32 ) & 0xFC ) | 0x02 ) ;
+ }
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : ChkLFB */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN ChkLFB( PVB_DEVICE_INFO pVBInfo )
+{
+ if ( LFBDRAMTrap & XGINew_GetReg1( pVBInfo->P3d4 , 0x78 ) )
+ return( TRUE ) ;
+ else
+ return( FALSE );
+}
+
+
+/* --------------------------------------------------------------------- */
+/* input : dx ,valid value : CR or second chip's CR */
+/* */
+/* SetPowerConsume : */
+/* Description: reduce 40/43 power consumption in first chip or */
+/* in second chip, assume CR A1 D[6]="1" in this case */
+/* output : none */
+/* --------------------------------------------------------------------- */
+void SetPowerConsume ( PXGI_HW_DEVICE_INFO HwDeviceExtension , ULONG XGI_P3d4Port )
+{
+ ULONG lTemp ;
+ UCHAR bTemp;
+
+ HwDeviceExtension->pQueryVGAConfigSpace( HwDeviceExtension , 0x08 , 0 , &lTemp ) ; /* Get */
+ if ((lTemp&0xFF)==0)
+ {
+ /* set CR58 D[5]=0 D[3]=0 */
+ XGINew_SetRegAND( XGI_P3d4Port , 0x58 , 0xD7 ) ;
+ bTemp = (UCHAR) XGINew_GetReg1( XGI_P3d4Port , 0xCB ) ;
+ if (bTemp&0x20)
+ {
+ if (!(bTemp&0x10))
+ {
+ XGINew_SetRegANDOR( XGI_P3d4Port , 0x58 , 0xD7 , 0x20 ) ; /* CR58 D[5]=1 D[3]=0 */
+ }
+ else
+ {
+ XGINew_SetRegANDOR( XGI_P3d4Port , 0x58 , 0xD7 , 0x08 ) ; /* CR58 D[5]=0 D[3]=1 */
+ }
+
+ }
+
+ }
+}
+
+
+
+#if defined(LINUX_XF86)||defined(LINUX_KERNEL)
+void XGINew_InitVBIOSData(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+{
+
+ /* ULONG ROMAddr = (ULONG)HwDeviceExtension->pjVirtualRomBase; */
+ pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+ pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+ pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
+ pVBInfo->ISXPDOS = 0 ;
+
+ pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
+ pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
+ pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
+ pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
+ pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
+ pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
+ pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
+ pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
+ pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
+ pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
+ pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
+ pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
+ pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
+ pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
+ pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
+ pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
+ pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
+ if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */
+ XGI_GetVBType( pVBInfo ) ; /* Run XGI_GetVBType before InitTo330Pointer */
+
+ switch(HwDeviceExtension->jChipType)
+ {
+ case XG40:
+ case XG41:
+ case XG42:
+ case XG20:
+ case XG21:
+ default:
+ InitTo330Pointer(HwDeviceExtension->jChipType,pVBInfo);
+ return ;
+ }
+
+}
+#endif /* For Linux */
+
+/* --------------------------------------------------------------------- */
+/* Function : ReadVBIOSTablData */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo)
+{
+ PUCHAR volatile pVideoMemory = ( PUCHAR )pVBInfo->ROMAddr ;
+ ULONG i ;
+ UCHAR j , k ;
+#if 0
+ ULONG ii , jj ;
+ i = pVideoMemory[ 0x1CF ] | ( pVideoMemory[ 0x1D0 ] << 8 ) ; /* UniROM */
+ if ( i != 0 )
+ UNIROM = 1 ;
+
+ ii = 0x90 ;
+ for( jj = 0x00 ; jj < 0x08 ; jj++ )
+ {
+ pVBInfo->MCLKData[ jj ].SR28 = pVideoMemory[ ii ] ;
+ pVBInfo->MCLKData[ jj ].SR29 = pVideoMemory[ ii + 1] ;
+ pVBInfo->MCLKData[ jj ].SR2A = pVideoMemory[ ii + 2] ;
+ pVBInfo->MCLKData[ jj ].CLOCK = pVideoMemory[ ii + 3 ] | ( pVideoMemory[ ii + 4 ] << 8 ) ;
+ ii += 0x05 ;
+ }
+
+ ii = 0xB8 ;
+ for( jj = 0x00 ; jj < 0x08 ; jj++ )
+ {
+ pVBInfo->ECLKData[ jj ].SR2E = pVideoMemory[ ii ] ;
+ pVBInfo->ECLKData[ jj ].SR2F=pVideoMemory[ ii + 1 ] ;
+ pVBInfo->ECLKData[ jj ].SR30= pVideoMemory[ ii + 2 ] ;
+ pVBInfo->ECLKData[ jj ].CLOCK= pVideoMemory[ ii + 3 ] | ( pVideoMemory[ ii + 4 ] << 8 ) ;
+ ii += 0x05 ;
+ }
+
+ /* Volari customize data area start */
+ /* if ( ChipType == XG40 ) */
+ if ( ChipType >= XG40 )
+ {
+ ii = 0xE0 ;
+ for( jj = 0x00 ; jj < 0x03 ; jj++ )
+ {
+ pVBInfo->SR15[ jj ][ 0 ] = pVideoMemory[ ii ] ; /* SR13, SR14, and SR18 */
+ pVBInfo->SR15[ jj ][ 1 ] = pVideoMemory[ ii + 1 ] ;
+ pVBInfo->SR15[ jj ][ 2 ] = pVideoMemory[ ii + 2 ] ;
+ pVBInfo->SR15[ jj ][ 3 ] = pVideoMemory[ ii + 3 ] ;
+ pVBInfo->SR15[ jj ][ 4 ] = pVideoMemory[ ii + 4 ] ;
+ pVBInfo->SR15[ jj ][ 5 ] = pVideoMemory[ ii + 5 ] ;
+ pVBInfo->SR15[ jj ][ 6 ] = pVideoMemory[ ii + 6 ] ;
+ pVBInfo->SR15[ jj ][ 7 ] = pVideoMemory[ ii + 7 ] ;
+ ii += 0x08 ;
+ }
+ ii = 0x110 ;
+ jj = 0x03 ;
+ pVBInfo->SR15[ jj ][ 0 ] = pVideoMemory[ ii ] ; /* SR1B */
+ pVBInfo->SR15[ jj ][ 1 ] = pVideoMemory[ ii + 1 ] ;
+ pVBInfo->SR15[ jj ][ 2 ] = pVideoMemory[ ii + 2 ] ;
+ pVBInfo->SR15[ jj ][ 3 ] = pVideoMemory[ ii + 3 ] ;
+ pVBInfo->SR15[ jj ][ 4 ] = pVideoMemory[ ii + 4 ] ;
+ pVBInfo->SR15[ jj ][ 5 ] = pVideoMemory[ ii + 5 ] ;
+ pVBInfo->SR15[ jj ][ 6 ] = pVideoMemory[ ii + 6 ] ;
+ pVBInfo->SR15[ jj ][ 7 ] = pVideoMemory[ ii + 7 ] ;
+
+ *pVBInfo->pSR07 = pVideoMemory[ 0x74 ] ;
+ *pVBInfo->pSR1F = pVideoMemory[ 0x75 ] ;
+ *pVBInfo->pSR21 = pVideoMemory[ 0x76 ] ;
+ *pVBInfo->pSR22 = pVideoMemory[ 0x77 ] ;
+ *pVBInfo->pSR23 = pVideoMemory[ 0x78 ] ;
+ *pVBInfo->pSR24 = pVideoMemory[ 0x79 ] ;
+ pVBInfo->SR25[ 0 ] = pVideoMemory[ 0x7A ] ;
+ *pVBInfo->pSR31 = pVideoMemory[ 0x7B ] ;
+ *pVBInfo->pSR32 = pVideoMemory[ 0x7C ] ;
+ *pVBInfo->pSR33 = pVideoMemory[ 0x7D ] ;
+ ii = 0xF8 ;
+
+ for( jj = 0 ; jj < 3 ; jj++ )
+ {
+ pVBInfo->CR40[ jj ][ 0 ] = pVideoMemory[ ii ] ;
+ pVBInfo->CR40[ jj ][ 1 ] = pVideoMemory[ ii + 1 ] ;
+ pVBInfo->CR40[ jj ][ 2 ] = pVideoMemory[ ii + 2 ] ;
+ pVBInfo->CR40[ jj ][ 3 ] = pVideoMemory[ ii + 3 ] ;
+ pVBInfo->CR40[ jj ][ 4 ] = pVideoMemory[ ii + 4 ] ;
+ pVBInfo->CR40[ jj ][ 5 ] = pVideoMemory[ ii + 5 ] ;
+ pVBInfo->CR40[ jj ][ 6 ] = pVideoMemory[ ii + 6 ] ;
+ pVBInfo->CR40[ jj ][ 7 ] = pVideoMemory[ ii + 7 ] ;
+ ii += 0x08 ;
+ }
+
+ ii = 0x118 ;
+ for( j = 3 ; j < 24 ; j++ )
+ {
+ pVBInfo->CR40[ j ][ 0 ] = pVideoMemory[ ii ] ;
+ pVBInfo->CR40[ j ][ 1 ] = pVideoMemory[ ii + 1 ] ;
+ pVBInfo->CR40[ j ][ 2 ] = pVideoMemory[ ii + 2 ] ;
+ pVBInfo->CR40[ j ][ 3 ] = pVideoMemory[ ii + 3 ] ;
+ pVBInfo->CR40[ j ][ 4 ] = pVideoMemory[ ii + 4 ] ;
+ pVBInfo->CR40[ j ][ 5 ] = pVideoMemory[ ii + 5 ] ;
+ pVBInfo->CR40[ j ][ 6 ] = pVideoMemory[ ii + 6 ] ;
+ pVBInfo->CR40[ j ][ 7 ] = pVideoMemory[ ii + 7 ] ;
+ ii += 0x08 ;
+ }
+
+ i = pVideoMemory[ 0x1C0 ] | ( pVideoMemory[ 0x1C1 ] << 8 ) ;
+
+ for( j = 0 ; j < 8 ; j++ )
+ {
+ for( k = 0 ; k < 4 ; k++ )
+ pVBInfo->CR6B[ j ][ k ] = pVideoMemory[ i + 4 * j + k ] ;
+ }
+
+ i = pVideoMemory[ 0x1C2 ] | ( pVideoMemory[ 0x1C3 ] << 8 ) ;
+
+ for( j = 0 ; j < 8 ; j++ )
+ {
+ for( k = 0 ; k < 4 ; k++ )
+ pVBInfo->CR6E[ j ][ k ] = pVideoMemory[ i + 4 * j + k ] ;
+ }
+
+ i = pVideoMemory[ 0x1C4 ] | ( pVideoMemory[ 0x1C5 ] << 8 ) ;
+ for( j = 0 ; j < 8 ; j++ )
+ {
+ for( k = 0 ; k < 32 ; k++ )
+ pVBInfo->CR6F[ j ][ k ] = pVideoMemory[ i + 32 * j + k ] ;
+ }
+
+ i = pVideoMemory[ 0x1C6 ] | ( pVideoMemory[ 0x1C7 ] << 8 ) ;
+
+ for( j = 0 ; j < 8 ; j++ )
+ {
+ for( k = 0 ; k < 2 ; k++ )
+ pVBInfo->CR89[ j ][ k ] = pVideoMemory[ i + 2 * j + k ] ;
+ }
+
+ i = pVideoMemory[ 0x1C8 ] | ( pVideoMemory[ 0x1C9 ] << 8 ) ;
+ for( j = 0 ; j < 12 ; j++ )
+ pVBInfo->AGPReg[ j ] = pVideoMemory[ i + j ] ;
+
+ i = pVideoMemory[ 0x1CF ] | ( pVideoMemory[ 0x1D0 ] << 8 ) ;
+ for( j = 0 ; j < 4 ; j++ )
+ pVBInfo->SR16[ j ] = pVideoMemory[ i + j ] ;
+
+ if ( ChipType == XG21 )
+ {
+ if (pVideoMemory[ 0x67 ] & 0x80)
+ {
+ *pVBInfo->pDVOSetting = pVideoMemory[ 0x67 ];
+ }
+ if ( (pVideoMemory[ 0x67 ] & 0xC0) == 0xC0 )
+ {
+ *pVBInfo->pCR2E = pVideoMemory[ i + 4 ] ;
+ *pVBInfo->pCR2F = pVideoMemory[ i + 5 ] ;
+ *pVBInfo->pCR46 = pVideoMemory[ i + 6 ] ;
+ *pVBInfo->pCR47 = pVideoMemory[ i + 7 ] ;
+ }
+ }
+
+ if ( ChipType == XG27 )
+ {
+ jj = i+j;
+ for( i = 0 ; i <= 0xB ; i++,jj++ )
+ pVBInfo->pCRD0[i] = pVideoMemory[ jj ] ;
+ for( i = 0x0 ; i <= 0x1 ; i++,jj++ )
+ pVBInfo->pCRDE[i] = pVideoMemory[ jj ] ;
+
+ *pVBInfo->pSR40 = pVideoMemory[ jj ] ;
+ jj++;
+ *pVBInfo->pSR41 = pVideoMemory[ jj ] ;
+
+ if (pVideoMemory[ 0x67 ] & 0x80)
+ {
+ *pVBInfo->pDVOSetting = pVideoMemory[ 0x67 ];
+ }
+ if ( (pVideoMemory[ 0x67 ] & 0xC0) == 0xC0 )
+ {
+ jj++;
+ *pVBInfo->pCR2E = pVideoMemory[ jj ] ;
+ *pVBInfo->pCR2F = pVideoMemory[ jj + 1 ] ;
+ *pVBInfo->pCR46 = pVideoMemory[ jj + 2 ] ;
+ *pVBInfo->pCR47 = pVideoMemory[ jj + 3 ] ;
+ }
+
+ }
+
+ *pVBInfo->pCRCF = pVideoMemory[ 0x1CA ] ;
+ *pVBInfo->pXGINew_DRAMTypeDefinition = pVideoMemory[ 0x1CB ] ;
+ *pVBInfo->pXGINew_I2CDefinition = pVideoMemory[ 0x1D1 ] ;
+ if ( ChipType >= XG20 )
+ {
+ *pVBInfo->pXGINew_CR97 = pVideoMemory[ 0x1D2 ] ;
+ if ( ChipType == XG27 )
+ {
+ *pVBInfo->pSR36 = pVideoMemory[ 0x1D3 ] ;
+ *pVBInfo->pCR8F = pVideoMemory[ 0x1D5 ] ;
+ }
+ }
+
+ }
+#endif
+ /* Volari customize data area end */
+
+ if ( ChipType == XG21 )
+ {
+ pVBInfo->IF_DEF_LVDS = 0 ;
+ if (pVideoMemory[ 0x65 ] & 0x1)
+ {
+ pVBInfo->IF_DEF_LVDS = 1 ;
+ i = pVideoMemory[ 0x316 ] | ( pVideoMemory[ 0x317 ] << 8 );
+ j = pVideoMemory[ i-1 ] ;
+ if ( j != 0xff )
+ {
+ k = 0;
+ do
+ {
+ pVBInfo->XG21_LVDSCapList[k].LVDS_Capability = pVideoMemory[ i ] | ( pVideoMemory[ i + 1 ] << 8 );
+ pVBInfo->XG21_LVDSCapList[k].LVDSHT = pVideoMemory[ i + 2 ] | ( pVideoMemory[ i + 3 ] << 8 ) ;
+ pVBInfo->XG21_LVDSCapList[k].LVDSVT = pVideoMemory[ i + 4 ] | ( pVideoMemory[ i + 5 ] << 8 );
+ pVBInfo->XG21_LVDSCapList[k].LVDSHDE = pVideoMemory[ i + 6 ] | ( pVideoMemory[ i + 7 ] << 8 );
+ pVBInfo->XG21_LVDSCapList[k].LVDSVDE = pVideoMemory[ i + 8 ] | ( pVideoMemory[ i + 9 ] << 8 );
+ pVBInfo->XG21_LVDSCapList[k].LVDSHFP = pVideoMemory[ i + 10 ] | ( pVideoMemory[ i + 11 ] << 8 );
+ pVBInfo->XG21_LVDSCapList[k].LVDSVFP = pVideoMemory[ i + 12 ] | ( pVideoMemory[ i + 13 ] << 8 );
+ pVBInfo->XG21_LVDSCapList[k].LVDSHSYNC = pVideoMemory[ i + 14 ] | ( pVideoMemory[ i + 15 ] << 8 );
+ pVBInfo->XG21_LVDSCapList[k].LVDSVSYNC = pVideoMemory[ i + 16 ] | ( pVideoMemory[ i + 17 ] << 8 );
+ pVBInfo->XG21_LVDSCapList[k].VCLKData1 = pVideoMemory[ i + 18 ] ;
+ pVBInfo->XG21_LVDSCapList[k].VCLKData2 = pVideoMemory[ i + 19 ] ;
+ pVBInfo->XG21_LVDSCapList[k].PSC_S1 = pVideoMemory[ i + 20 ] ;
+ pVBInfo->XG21_LVDSCapList[k].PSC_S2 = pVideoMemory[ i + 21 ] ;
+ pVBInfo->XG21_LVDSCapList[k].PSC_S3 = pVideoMemory[ i + 22 ] ;
+ pVBInfo->XG21_LVDSCapList[k].PSC_S4 = pVideoMemory[ i + 23 ] ;
+ pVBInfo->XG21_LVDSCapList[k].PSC_S5 = pVideoMemory[ i + 24 ] ;
+ i += 25;
+ j--;
+ k++;
+ } while ( (j>0) && ( k < (sizeof(XGI21_LCDCapList)/sizeof(XGI21_LVDSCapStruct)) ) );
+ }
+ else
+ {
+ pVBInfo->XG21_LVDSCapList[0].LVDS_Capability = pVideoMemory[ i ] | ( pVideoMemory[ i + 1 ] << 8 );
+ pVBInfo->XG21_LVDSCapList[0].LVDSHT = pVideoMemory[ i + 2 ] | ( pVideoMemory[ i + 3 ] << 8 ) ;
+ pVBInfo->XG21_LVDSCapList[0].LVDSVT = pVideoMemory[ i + 4 ] | ( pVideoMemory[ i + 5 ] << 8 );
+ pVBInfo->XG21_LVDSCapList[0].LVDSHDE = pVideoMemory[ i + 6 ] | ( pVideoMemory[ i + 7 ] << 8 );
+ pVBInfo->XG21_LVDSCapList[0].LVDSVDE = pVideoMemory[ i + 8 ] | ( pVideoMemory[ i + 9 ] << 8 );
+ pVBInfo->XG21_LVDSCapList[0].LVDSHFP = pVideoMemory[ i + 10 ] | ( pVideoMemory[ i + 11 ] << 8 );
+ pVBInfo->XG21_LVDSCapList[0].LVDSVFP = pVideoMemory[ i + 12 ] | ( pVideoMemory[ i + 13 ] << 8 );
+ pVBInfo->XG21_LVDSCapList[0].LVDSHSYNC = pVideoMemory[ i + 14 ] | ( pVideoMemory[ i + 15 ] << 8 );
+ pVBInfo->XG21_LVDSCapList[0].LVDSVSYNC = pVideoMemory[ i + 16 ] | ( pVideoMemory[ i + 17 ] << 8 );
+ pVBInfo->XG21_LVDSCapList[0].VCLKData1 = pVideoMemory[ i + 18 ] ;
+ pVBInfo->XG21_LVDSCapList[0].VCLKData2 = pVideoMemory[ i + 19 ] ;
+ pVBInfo->XG21_LVDSCapList[0].PSC_S1 = pVideoMemory[ i + 20 ] ;
+ pVBInfo->XG21_LVDSCapList[0].PSC_S2 = pVideoMemory[ i + 21 ] ;
+ pVBInfo->XG21_LVDSCapList[0].PSC_S3 = pVideoMemory[ i + 22 ] ;
+ pVBInfo->XG21_LVDSCapList[0].PSC_S4 = pVideoMemory[ i + 23 ] ;
+ pVBInfo->XG21_LVDSCapList[0].PSC_S5 = pVideoMemory[ i + 24 ] ;
+ }
+ }
+ }
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_DDR1x_MRS_XG20 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_DDR1x_MRS_XG20( ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
+{
+
+ XGINew_SetReg1( P3c4 , 0x18 , 0x01 ) ;
+ XGINew_SetReg1( P3c4 , 0x19 , 0x40 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
+ DelayUS( 60 ) ;
+
+ XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ;
+ XGINew_SetReg1( P3c4 , 0x19 , 0x40 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
+ DelayUS( 60 ) ;
+ XGINew_SetReg1( P3c4 , 0x18 , pVBInfo->SR15[ 2 ][ XGINew_RAMType ] ) ; /* SR18 */
+ /* XGINew_SetReg1( P3c4 , 0x18 , 0x31 ) ; */
+ XGINew_SetReg1( P3c4 , 0x19 , 0x01 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x03 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x83 ) ;
+ DelayUS( 1000 ) ;
+ XGINew_SetReg1( P3c4 , 0x1B , 0x03 ) ;
+ DelayUS( 500 ) ;
+ /* XGINew_SetReg1( P3c4 , 0x18 , 0x31 ) ; */
+ XGINew_SetReg1( P3c4 , 0x18 , pVBInfo->SR15[ 2 ][ XGINew_RAMType ] ) ; /* SR18 */
+ XGINew_SetReg1( P3c4 , 0x19 , 0x00 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x03 ) ;
+ XGINew_SetReg1( P3c4 , 0x16 , 0x83 ) ;
+ XGINew_SetReg1( P3c4 , 0x1B , 0x00 ) ;
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetDRAMModeRegister_XG20 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SetDRAMModeRegister_XG20( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+{
+ VB_DEVICE_INFO VBINF;
+ PVB_DEVICE_INFO pVBInfo = &VBINF;
+ pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+ pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+ pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
+ pVBInfo->ISXPDOS = 0 ;
+
+ pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
+ pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
+ pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
+ pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
+ pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
+ pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
+ pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
+ pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
+ pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
+ pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
+ pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
+ pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
+ pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
+ pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
+ pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
+ pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
+ pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
+
+ InitTo330Pointer(HwDeviceExtension->jChipType,pVBInfo);
+
+ ReadVBIOSTablData( HwDeviceExtension->jChipType , pVBInfo) ;
+
+ if ( XGINew_GetXG20DRAMType( HwDeviceExtension, pVBInfo) == 0 )
+ XGINew_DDR1x_MRS_XG20( pVBInfo->P3c4, pVBInfo ) ;
+ else
+ XGINew_DDR2_MRS_XG20( HwDeviceExtension , pVBInfo->P3c4 , pVBInfo ) ;
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , 0x03 ) ;
+}
+
+void XGINew_SetDRAMModeRegister_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+{
+ VB_DEVICE_INFO VBINF;
+ PVB_DEVICE_INFO pVBInfo = &VBINF;
+ pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+ pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+ pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
+ pVBInfo->ISXPDOS = 0 ;
+
+ pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
+ pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
+ pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
+ pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
+ pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
+ pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
+ pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
+ pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
+ pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
+ pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
+ pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
+ pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
+ pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
+ pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
+ pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
+ pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
+ pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
+
+ InitTo330Pointer(HwDeviceExtension->jChipType,pVBInfo);
+
+ ReadVBIOSTablData( HwDeviceExtension->jChipType , pVBInfo) ;
+
+ if ( XGINew_GetXG20DRAMType( HwDeviceExtension, pVBInfo) == 0 )
+ XGINew_DDR1x_MRS_XG20( pVBInfo->P3c4, pVBInfo ) ;
+ else
+ //XGINew_DDR2_MRS_XG27( HwDeviceExtension , pVBInfo->P3c4 , pVBInfo ) ;
+ XGINew_DDRII_Bootup_XG27( HwDeviceExtension , pVBInfo->P3c4 , pVBInfo) ;
+
+ //XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , 0x03 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , pVBInfo->SR15[ 3 ][ XGINew_RAMType ] ) ; /* SR1B */
+
+}
+/*
+void XGINew_SetDRAMModeRegister_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension )
+{
+#ifndef LINUX_XF86
+ UCHAR data ;
+#endif
+ VB_DEVICE_INFO VBINF;
+ PVB_DEVICE_INFO pVBInfo = &VBINF;
+ pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+ pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
+ pVBInfo->BaseAddr = HwDeviceExtension->pjIOAddress ;
+ pVBInfo->ISXPDOS = 0 ;
+
+ pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
+ pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
+ pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
+ pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
+ pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
+ pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
+ pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
+ pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
+ pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
+ pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
+ pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
+ pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
+ pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
+ pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
+ pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
+ pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
+ pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
+
+ InitTo330Pointer(HwDeviceExtension->jChipType,pVBInfo);
+
+ ReadVBIOSTablData( HwDeviceExtension->jChipType , pVBInfo) ;
+
+ if ( XGINew_GetXG20DRAMType( HwDeviceExtension, pVBInfo) == 0 )
+ XGINew_DDR1x_MRS_XG20( pVBInfo->P3c4, pVBInfo ) ;
+ else
+ XGINew_DDR2_MRS_XG27( HwDeviceExtension , pVBInfo->P3c4 , pVBInfo ) ;
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , 0x03 ) ;
+}
+*/
+/* -------------------------------------------------------- */
+/* Function : XGINew_ChkSenseStatus */
+/* Input : */
+/* Output : */
+/* Description : */
+/* -------------------------------------------------------- */
+void XGINew_ChkSenseStatus ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT tempbx=0 , temp , tempcx , CR3CData;
+
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x32 ) ;
+
+ if ( temp & Monitor1Sense )
+ tempbx |= ActiveCRT1 ;
+ if ( temp & LCDSense )
+ tempbx |= ActiveLCD ;
+ if ( temp & Monitor2Sense )
+ tempbx |= ActiveCRT2 ;
+ if ( temp & TVSense )
+ {
+ tempbx |= ActiveTV ;
+ if ( temp & AVIDEOSense )
+ tempbx |= ( ActiveAVideo << 8 );
+ if ( temp & SVIDEOSense )
+ tempbx |= ( ActiveSVideo << 8 );
+ if ( temp & SCARTSense )
+ tempbx |= ( ActiveSCART << 8 );
+ if ( temp & HiTVSense )
+ tempbx |= ( ActiveHiTV << 8 );
+ if ( temp & YPbPrSense )
+ tempbx |= ( ActiveYPbPr << 8 );
+ }
+
+ tempcx = XGINew_GetReg1( pVBInfo->P3d4 , 0x3d ) ;
+ tempcx |= ( XGINew_GetReg1( pVBInfo->P3d4 , 0x3e ) << 8 ) ;
+
+ if ( tempbx & tempcx )
+ {
+ CR3CData = XGINew_GetReg1( pVBInfo->P3d4 , 0x3c ) ;
+ if ( !( CR3CData & DisplayDeviceFromCMOS ) )
+ {
+ tempcx = 0x1FF0 ;
+ if ( *pVBInfo->pSoftSetting & ModeSoftSetting )
+ {
+ tempbx = 0x1FF0 ;
+ }
+ }
+ }
+ else
+ {
+ tempcx = 0x1FF0 ;
+ if ( *pVBInfo->pSoftSetting & ModeSoftSetting )
+ {
+ tempbx = 0x1FF0 ;
+ }
+ }
+
+ tempbx &= tempcx ;
+ XGINew_SetReg1( pVBInfo->P3d4, 0x3d , ( tempbx & 0x00FF ) ) ;
+ XGINew_SetReg1( pVBInfo->P3d4, 0x3e , ( ( tempbx & 0xFF00 ) >> 8 )) ;
+}
+/* -------------------------------------------------------- */
+/* Function : XGINew_SetModeScratch */
+/* Input : */
+/* Output : */
+/* Description : */
+/* -------------------------------------------------------- */
+void XGINew_SetModeScratch ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT temp , tempcl = 0 , tempch = 0 , CR31Data , CR38Data;
+
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x3d ) ;
+ temp |= XGINew_GetReg1( pVBInfo->P3d4 , 0x3e ) << 8 ;
+ temp |= ( XGINew_GetReg1( pVBInfo->P3d4 , 0x31 ) & ( DriverMode >> 8) ) << 8 ;
+
+ if ( pVBInfo->IF_DEF_CRT2Monitor == 1)
+ {
+ if ( temp & ActiveCRT2 )
+ tempcl = SetCRT2ToRAMDAC ;
+ }
+
+ if ( temp & ActiveLCD )
+ {
+ tempcl |= SetCRT2ToLCD ;
+ if ( temp & DriverMode )
+ {
+ if ( temp & ActiveTV )
+ {
+ tempch = SetToLCDA | EnableDualEdge ;
+ temp ^= SetCRT2ToLCD ;
+
+ if ( ( temp >> 8 ) & ActiveAVideo )
+ tempcl |= SetCRT2ToAVIDEO ;
+ if ( ( temp >> 8 ) & ActiveSVideo )
+ tempcl |= SetCRT2ToSVIDEO ;
+ if ( ( temp >> 8 ) & ActiveSCART )
+ tempcl |= SetCRT2ToSCART ;
+
+ if ( pVBInfo->IF_DEF_HiVision == 1 )
+ {
+ if ( ( temp >> 8 ) & ActiveHiTV )
+ tempcl |= SetCRT2ToHiVisionTV ;
+ }
+
+ if ( pVBInfo->IF_DEF_YPbPr == 1 )
+ {
+ if ( ( temp >> 8 ) & ActiveYPbPr )
+ tempch |= SetYPbPr ;
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( ( temp >> 8 ) & ActiveAVideo )
+ tempcl |= SetCRT2ToAVIDEO ;
+ if ( ( temp >> 8 ) & ActiveSVideo )
+ tempcl |= SetCRT2ToSVIDEO ;
+ if ( ( temp >> 8 ) & ActiveSCART )
+ tempcl |= SetCRT2ToSCART ;
+
+ if ( pVBInfo->IF_DEF_HiVision == 1 )
+ {
+ if ( ( temp >> 8 ) & ActiveHiTV )
+ tempcl |= SetCRT2ToHiVisionTV ;
+ }
+
+ if ( pVBInfo->IF_DEF_YPbPr == 1 )
+ {
+ if ( ( temp >> 8 ) & ActiveYPbPr )
+ tempch |= SetYPbPr ;
+ }
+ }
+
+
+ tempcl |= SetSimuScanMode ;
+ if ( (!( temp & ActiveCRT1 )) && ( ( temp & ActiveLCD ) || ( temp & ActiveTV ) || ( temp & ActiveCRT2 ) ) )
+ tempcl ^= ( SetSimuScanMode | SwitchToCRT2 ) ;
+ if ( ( temp & ActiveLCD ) && ( temp & ActiveTV ) )
+ tempcl ^= ( SetSimuScanMode | SwitchToCRT2 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4, 0x30 , tempcl ) ;
+
+ CR31Data = XGINew_GetReg1( pVBInfo->P3d4 , 0x31 ) ;
+ CR31Data &= ~( SetNotSimuMode >> 8 ) ;
+ if ( !( temp & ActiveCRT1 ) )
+ CR31Data |= ( SetNotSimuMode >> 8 ) ;
+ CR31Data &= ~( DisableCRT2Display >> 8 ) ;
+ if (!( ( temp & ActiveLCD ) || ( temp & ActiveTV ) || ( temp & ActiveCRT2 ) ) )
+ CR31Data |= ( DisableCRT2Display >> 8 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4, 0x31 , CR31Data ) ;
+
+ CR38Data = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ;
+ CR38Data &= ~SetYPbPr ;
+ CR38Data |= tempch ;
+ XGINew_SetReg1( pVBInfo->P3d4, 0x38 , CR38Data ) ;
+
+}
+
+/* -------------------------------------------------------- */
+/* Function : XGINew_GetXG21Sense */
+/* Input : */
+/* Output : */
+/* Description : */
+/* -------------------------------------------------------- */
+void XGINew_GetXG21Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+{
+ UCHAR Temp;
+ PUCHAR volatile pVideoMemory = ( PUCHAR )pVBInfo->ROMAddr ;
+
+ pVBInfo->IF_DEF_LVDS = 0 ;
+
+#ifdef WIN2000
+ pVBInfo->IF_DEF_CH7007 = 0 ;
+ if ( ( pVideoMemory[ 0x65 ] & 0x02 ) ) /* For XG21 CH7007 */
+ {
+ /* VideoDebugPrint((0, "ReadVBIOSTablData: pVideoMemory[ 0x65 ] =%x\n",pVideoMemory[ 0x65 ])); */
+ pVBInfo->IF_DEF_CH7007 = 1 ; /* [Billy] 07/05/03 */
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x38 , ~0xE0 , 0x60 ) ; /* CH7007 on chip */
+ }
+ else
+#endif
+#if 1
+ if (( pVideoMemory[ 0x65 ] & 0x01 ) ) /* For XG21 LVDS */
+ {
+ pVBInfo->IF_DEF_LVDS = 1 ;
+ XGINew_SetRegOR( pVBInfo->P3d4 , 0x32 , LCDSense ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x38 , ~0xE0 , 0xC0 ) ; /* LVDS on chip */
+ }
+ else
+ {
+#endif
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x4A , ~0x03 , 0x03 ) ; /* Enable GPIOA/B read */
+ Temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) & 0xC0;
+ if ( Temp == 0xC0 )
+ { /* DVI & DVO GPIOA/B pull high */
+ XGINew_SenseLCD( HwDeviceExtension, pVBInfo ) ;
+ XGINew_SetRegOR( pVBInfo->P3d4 , 0x32 , LCDSense ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x4A , ~0x20 , 0x20 ) ; /* Enable read GPIOF */
+ Temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) & 0x04 ;
+ if ( !Temp )
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x38 , ~0xE0 , 0x80 ) ; /* TMDS on chip */
+ else
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x38 , ~0xE0 , 0xA0 ) ; /* Only DVO on chip */
+ XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x20 ) ; /* Disable read GPIOF */
+ }
+#if 1
+ }
+#endif
+}
+
+/* -------------------------------------------------------- */
+/* Function : XGINew_GetXG27Sense */
+/* Input : */
+/* Output : */
+/* Description : */
+/* -------------------------------------------------------- */
+void XGINew_GetXG27Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+{
+ UCHAR Temp,bCR4A;
+
+ pVBInfo->IF_DEF_LVDS = 0 ;
+ bCR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x4A , ~0x07 , 0x07 ) ; /* Enable GPIOA/B/C read */
+ Temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) & 0x07;
+ XGINew_SetReg1( pVBInfo->P3d4, 0x4A , bCR4A ) ;
+
+ if ( Temp <= 0x02 )
+ {
+ pVBInfo->IF_DEF_LVDS = 1 ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x38 , ~0xE0 , 0xC0 ) ; /* LVDS setting */
+ XGINew_SetReg1( pVBInfo->P3d4, 0x30 , 0x21 ) ;
+ }
+ else
+ {
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x38 , ~0xE0 , 0xA0 ) ; /* TMDS/DVO setting */
+ }
+ XGINew_SetRegOR( pVBInfo->P3d4 , 0x32 , LCDSense ) ;
+
+}
+
+UCHAR GetXG21FPBits(PVB_DEVICE_INFO pVBInfo)
+{
+ UCHAR CR38,CR4A,temp;
+
+ CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x4A , ~0x10 , 0x10 ) ; /* enable GPIOE read */
+ CR38 = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ;
+ temp =0;
+ if ( ( CR38 & 0xE0 ) > 0x80 )
+ {
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) ;
+ temp &= 0x08;
+ temp >>= 3;
+ }
+
+ XGINew_SetReg1( pVBInfo->P3d4, 0x4A , CR4A ) ;
+
+ return temp;
+}
+
+UCHAR GetXG27FPBits(PVB_DEVICE_INFO pVBInfo)
+{
+ UCHAR CR4A,temp;
+
+ CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x4A , ~0x03 , 0x03 ) ; /* enable GPIOA/B/C read */
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) ;
+ if ( temp <= 2 )
+ {
+ temp &= 0x03;
+ }
+ else
+ {
+ temp = ((temp&0x04)>>1) || ((~temp)&0x01);
+ }
+ XGINew_SetReg1( pVBInfo->P3d4, 0x4A , CR4A ) ;
+
+ return temp;
+}
+
diff --git a/drivers/staging/xgifb/vb_init.h b/drivers/staging/xgifb/vb_init.h
new file mode 100644
index 0000000..1f39d9c
--- /dev/null
+++ b/drivers/staging/xgifb/vb_init.h
@@ -0,0 +1,7 @@
+#ifndef _VBINIT_
+#define _VBINIT_
+extern BOOLEAN XGIInitNew( PXGI_HW_DEVICE_INFO HwDeviceExtension ) ;
+extern XGI21_LVDSCapStruct XGI21_LCDCapList[13];
+
+#endif
+
diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
new file mode 100644
index 0000000..bd7f738
--- /dev/null
+++ b/drivers/staging/xgifb/vb_setmode.c
@@ -0,0 +1,10736 @@
+#include "osdef.h"
+
+#ifdef TC
+#include <stdio.h>
+#include <string.h>
+#include <conio.h>
+#include <dos.h>
+#endif
+
+
+#ifdef LINUX_XF86
+#include "xf86.h"
+#include "xf86PciInfo.h"
+#include "xgi.h"
+#include "xgi_regs.h"
+#endif
+
+#ifdef LINUX_KERNEL
+#include <asm/io.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include "XGIfb.h"
+/*#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#include <video/XGIfb.h>
+#else
+#include <linux/XGIfb.h>
+#endif*/
+#endif
+
+#ifdef WIN2000
+#include <dderror.h>
+#include <devioctl.h>
+#include <miniport.h>
+#include <ntddvdeo.h>
+#include <video.h>
+
+#include "xgiv.h"
+#include "dd_i2c.h"
+#include "tools.h"
+#endif
+
+#include "vb_def.h"
+#include "vgatypes.h"
+#include "vb_struct.h"
+#include "vb_util.h"
+#include "vb_table.h"
+
+
+
+#define IndexMask 0xff
+#ifndef XGI_MASK_DUAL_CHIP
+#define XGI_MASK_DUAL_CHIP 0x04 /* SR3A */
+#endif
+
+
+
+BOOLEAN XGI_IsLCDDualLink(PVB_DEVICE_INFO pVBInfo);
+BOOLEAN XGI_SetCRT2Group301(USHORT ModeNo, PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
+BOOLEAN XGI_BacklightByDrv(PVB_DEVICE_INFO pVBInfo);
+
+BOOLEAN XGI_IsLCDON(PVB_DEVICE_INFO pVBInfo);
+BOOLEAN XGI_DisableChISLCD(PVB_DEVICE_INFO pVBInfo);
+BOOLEAN XGI_EnableChISLCD(PVB_DEVICE_INFO pVBInfo);
+BOOLEAN XGI_AjustCRT2Rate(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,USHORT *i, PVB_DEVICE_INFO pVBInfo);
+BOOLEAN XGI_SearchModeID( USHORT ModeNo,USHORT *ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+BOOLEAN XGI_GetLCDInfo(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+BOOLEAN XGISetModeNew( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo ) ;
+BOOLEAN XGI_BridgeIsOn(PVB_DEVICE_INFO pVBInfo);
+UCHAR XGI_GetModePtr( USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
+USHORT XGI_GetOffset(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
+USHORT XGI_GetRatePtrCRT2( PXGI_HW_DEVICE_INFO pXGIHWDE, USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo );
+USHORT XGI_GetResInfo(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+USHORT XGI_GetColorDepth(USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
+USHORT XGI_GetVGAHT2(PVB_DEVICE_INFO pVBInfo);
+USHORT XGI_GetVCLK2Ptr(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
+void XGI_VBLongWait(PVB_DEVICE_INFO pVBInfo);
+void XGI_SaveCRT2Info(USHORT ModeNo, PVB_DEVICE_INFO pVBInfo);
+void XGI_GetCRT2Data(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+void XGI_GetCRT2ResInfo(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+void XGI_PreSetGroup1(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+void XGI_SetGroup1(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+void XGI_SetLockRegs(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+void XGI_SetLCDRegs(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+void XGI_SetGroup2(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+void XGI_SetGroup3(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+void XGI_SetGroup4(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+void XGI_SetGroup5(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+void* XGI_GetLcdPtr(USHORT BX, USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+void* XGI_GetTVPtr(USHORT BX, USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+void XGI_FirePWDEnable(PVB_DEVICE_INFO pVBInfo);
+void XGI_EnableGatingCRT(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+void XGI_DisableGatingCRT(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+void XGI_SetPanelDelay(USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
+void XGI_SetPanelPower(USHORT tempah,USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
+void XGI_EnablePWD( PVB_DEVICE_INFO pVBInfo);
+void XGI_DisablePWD( PVB_DEVICE_INFO pVBInfo);
+void XGI_AutoThreshold( PVB_DEVICE_INFO pVBInfo);
+void XGI_SetTap4Regs( PVB_DEVICE_INFO pVBInfo);
+
+void XGI_DisplayOn(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
+void XGI_DisplayOff( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo );
+void XGI_SetCRT1Group(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
+void XGI_SetXG21CRTC(USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+void XGI_SetXG21LCD(PVB_DEVICE_INFO pVBInfo,USHORT RefreshRateTableIndex,USHORT ModeNo);
+void XGI_SetXG27CRTC(USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+void XGI_SetXG27LCD(PVB_DEVICE_INFO pVBInfo,USHORT RefreshRateTableIndex,USHORT ModeNo);
+void XGI_UpdateXG21CRTC(USHORT ModeNo, PVB_DEVICE_INFO pVBInfo, USHORT RefreshRateTableIndex);
+void XGI_WaitDisply(PVB_DEVICE_INFO pVBInfo);
+void XGI_SenseCRT1(PVB_DEVICE_INFO pVBInfo);
+void XGI_SetSeqRegs(USHORT ModeNo,USHORT StandTableIndex,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
+void XGI_SetMiscRegs(USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo);
+void XGI_SetCRTCRegs(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo);
+void XGI_SetATTRegs(USHORT ModeNo,USHORT StandTableIndex,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo );
+void XGI_SetGRCRegs(USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo);
+void XGI_ClearExt1Regs(PVB_DEVICE_INFO pVBInfo);
+
+void XGI_SetSync(USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
+void XGI_SetCRT1CRTC(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo,PXGI_HW_DEVICE_INFO HwDeviceExtension);
+void XGI_SetCRT1Timing_H(PVB_DEVICE_INFO pVBInfo,PXGI_HW_DEVICE_INFO HwDeviceExtension);
+void XGI_SetCRT1Timing_V(USHORT ModeIdIndex,USHORT ModeNo,PVB_DEVICE_INFO pVBInfo);
+void XGI_SetCRT1DE(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
+void XGI_SetCRT1VCLK(USHORT ModeNo,USHORT ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+void XGI_SetCRT1FIFO(USHORT ModeNo,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+void XGI_SetCRT1ModeRegs(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
+void XGI_SetVCLKState(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
+
+void XGI_LoadDAC(USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
+void XGI_WriteDAC(USHORT dl, USHORT ah, USHORT al, USHORT dh, PVB_DEVICE_INFO pVBInfo);
+/*void XGI_ClearBuffer(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,PVB_DEVICE_INFO pVBInfo);*/
+void XGI_SetLCDAGroup(USHORT ModeNo,USHORT ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
+void XGI_GetLVDSResInfo( USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
+void XGI_GetLVDSData(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
+void XGI_ModCRT1Regs(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
+void XGI_SetLVDSRegs(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
+void XGI_UpdateModeInfo(PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
+void XGI_GetVGAType(PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
+void XGI_GetVBType(PVB_DEVICE_INFO pVBInfo);
+void XGI_GetVBInfo(USHORT ModeNo,USHORT ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
+void XGI_GetTVInfo(USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
+void XGI_SetCRT2ECLK( USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
+void InitTo330Pointer(UCHAR,PVB_DEVICE_INFO pVBInfo);
+void XGI_GetLCDSync(USHORT* HSyncWidth, USHORT* VSyncWidth, PVB_DEVICE_INFO pVBInfo);
+void XGI_DisableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+void XGI_EnableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
+void XGI_SetCRT2VCLK(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+void XGI_OEM310Setting(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+void XGI_SetDelayComp(PVB_DEVICE_INFO pVBInfo);
+void XGI_SetLCDCap(PVB_DEVICE_INFO pVBInfo);
+void XGI_SetLCDCap_A(USHORT tempcx,PVB_DEVICE_INFO pVBInfo);
+void XGI_SetLCDCap_B(USHORT tempcx,PVB_DEVICE_INFO pVBInfo);
+void SetSpectrum(PVB_DEVICE_INFO pVBInfo);
+void XGI_SetAntiFlicker(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+void XGI_SetEdgeEnhance(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+void XGI_SetPhaseIncr(PVB_DEVICE_INFO pVBInfo);
+void XGI_SetYFilter(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+void XGI_GetTVPtrIndex2(USHORT* tempbx,UCHAR* tempcl,UCHAR* tempch, PVB_DEVICE_INFO pVBInfo);
+USHORT XGI_GetTVPtrIndex( PVB_DEVICE_INFO pVBInfo );
+void XGI_SetCRT2ModeRegs(USHORT ModeNo,PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo );
+void XGI_CloseCRTC(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
+void XGI_OpenCRTC(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
+void XGI_GetRAMDAC2DATA(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
+void XGI_UnLockCRT2(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
+void XGI_LockCRT2(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
+void XGINew_EnableCRT2(PVB_DEVICE_INFO pVBInfo);
+void XGINew_LCD_Wait_Time(UCHAR DelayTime, PVB_DEVICE_INFO pVBInfo);
+void XGI_LongWait(PVB_DEVICE_INFO pVBInfo);
+void XGI_SetCRT1Offset( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo );
+void XGI_GetLCDVCLKPtr(UCHAR* di_0,UCHAR *di_1, PVB_DEVICE_INFO pVBInfo);
+UCHAR XGI_GetVCLKPtr(USHORT RefreshRateTableIndex,USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+void XGI_GetVCLKLen(UCHAR tempal,UCHAR* di_0,UCHAR* di_1, PVB_DEVICE_INFO pVBInfo);
+USHORT XGI_GetLCDCapPtr(PVB_DEVICE_INFO pVBInfo);
+USHORT XGI_GetLCDCapPtr1(PVB_DEVICE_INFO pVBInfo);
+XGI301C_Tap4TimingStruct* XGI_GetTap4Ptr(USHORT tempcx, PVB_DEVICE_INFO pVBInfo);
+void XGI_SetXG21FPBits(PVB_DEVICE_INFO pVBInfo);
+void XGI_SetXG27FPBits(PVB_DEVICE_INFO pVBInfo);
+UCHAR XGI_XG21GetPSCValue(PVB_DEVICE_INFO pVBInfo);
+UCHAR XGI_XG27GetPSCValue(PVB_DEVICE_INFO pVBInfo);
+void XGI_XG21BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
+void XGI_XG27BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
+void XGI_XG21SetPanelDelay(USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
+BOOLEAN XGI_XG21CheckLVDSMode(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
+void XGI_SetXG21LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
+void XGI_SetXG27LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
+UCHAR XGI_SetDefaultVCLK( PVB_DEVICE_INFO pVBInfo );
+
+extern void ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo);
+#ifdef WIN2000
+/* [Billy] 2007/05/17 For CH7007 */
+extern UCHAR CH7007TVReg_UNTSC[][8],CH7007TVReg_ONTSC[][8],CH7007TVReg_UPAL[][8],CH7007TVReg_OPAL[][8];
+extern UCHAR CH7007TVCRT1UNTSC_H[][10],CH7007TVCRT1ONTSC_H[][10],CH7007TVCRT1UPAL_H[][10],CH7007TVCRT1OPAL_H[][10] ;
+extern UCHAR CH7007TVCRT1UNTSC_V[][10],CH7007TVCRT1ONTSC_V[][10],CH7007TVCRT1UPAL_V[][10],CH7007TVCRT1OPAL_V[][10] ;
+extern UCHAR XGI7007_CHTVVCLKUNTSC[],XGI7007_CHTVVCLKONTSC[],XGI7007_CHTVVCLKUPAL[],XGI7007_CHTVVCLKOPAL[];
+
+extern BOOLEAN XGI_XG21CheckCH7007TVMode(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo ) ;
+extern void SetCH7007Regs(PXGI_HW_DEVICE_INFO HwDeviceExtension, USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo ) ;
+extern VP_STATUS TurnOnCH7007(PHW_DEVICE_EXTENSION pHWDE) ;
+extern VP_STATUS TurnOffCH7007(PHW_DEVICE_EXTENSION pHWDE) ;
+extern BOOLEAN IsCH7007TVMode(PVB_DEVICE_INFO pVBInfo) ;
+#endif
+
+/* USHORT XGINew_flag_clearbuffer; 0: no clear frame buffer 1:clear frame buffer */
+
+
+
+
+
+USHORT XGINew_MDA_DAC[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+ 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+ 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+ 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+ 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F};
+
+USHORT XGINew_CGA_DAC[]={0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+ 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+ 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+ 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+ 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+ 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+ 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+ 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F};
+
+USHORT XGINew_EGA_DAC[]={0x00,0x10,0x04,0x14,0x01,0x11,0x05,0x15,
+ 0x20,0x30,0x24,0x34,0x21,0x31,0x25,0x35,
+ 0x08,0x18,0x0C,0x1C,0x09,0x19,0x0D,0x1D,
+ 0x28,0x38,0x2C,0x3C,0x29,0x39,0x2D,0x3D,
+ 0x02,0x12,0x06,0x16,0x03,0x13,0x07,0x17,
+ 0x22,0x32,0x26,0x36,0x23,0x33,0x27,0x37,
+ 0x0A,0x1A,0x0E,0x1E,0x0B,0x1B,0x0F,0x1F,
+ 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F};
+
+USHORT XGINew_VGA_DAC[]={0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+ 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+ 0x00,0x05,0x08,0x0B,0x0E,0x11,0x14,0x18,
+ 0x1C,0x20,0x24,0x28,0x2D,0x32,0x38,0x3F,
+
+ 0x00,0x10,0x1F,0x2F,0x3F,0x1F,0x27,0x2F,
+ 0x37,0x3F,0x2D,0x31,0x36,0x3A,0x3F,0x00,
+ 0x07,0x0E,0x15,0x1C,0x0E,0x11,0x15,0x18,
+ 0x1C,0x14,0x16,0x18,0x1A,0x1C,0x00,0x04,
+ 0x08,0x0C,0x10,0x08,0x0A,0x0C,0x0E,0x10,
+ 0x0B,0x0C,0x0D,0x0F,0x10};
+
+
+/* --------------------------------------------------------------------- */
+/* Function : InitTo330Pointer */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void InitTo330Pointer( UCHAR ChipType ,PVB_DEVICE_INFO pVBInfo)
+{
+ pVBInfo->SModeIDTable = (XGI_StStruct *) XGI330_SModeIDTable ;
+ pVBInfo->StandTable = (XGI_StandTableStruct *) XGI330_StandTable ;
+ pVBInfo->EModeIDTable = (XGI_ExtStruct *) XGI330_EModeIDTable ;
+ pVBInfo->RefIndex = (XGI_Ext2Struct *) XGI330_RefIndex ;
+ pVBInfo->XGINEWUB_CRT1Table = (XGI_CRT1TableStruct *) XGI_CRT1Table ;
+
+ /* add for new UNIVGABIOS */
+ /* XGINew_UBLCDDataTable = (XGI_LCDDataTablStruct *) XGI_LCDDataTable ; */
+ /* XGINew_UBTVDataTable = (XGI_TVDataTablStruct *) XGI_TVDataTable ; */
+
+
+ if ( ChipType >= XG40 )
+ {
+ pVBInfo->MCLKData = (XGI_MCLKDataStruct *) XGI340New_MCLKData ;
+ pVBInfo->ECLKData = (XGI_ECLKDataStruct *) XGI340_ECLKData ;
+ }
+ else
+ {
+ pVBInfo->MCLKData = (XGI_MCLKDataStruct *) XGI330New_MCLKData ;
+ pVBInfo->ECLKData = (XGI_ECLKDataStruct *) XGI330_ECLKData ;
+ }
+
+ pVBInfo->VCLKData = (XGI_VCLKDataStruct *) XGI_VCLKData ;
+ pVBInfo->VBVCLKData = (XGI_VBVCLKDataStruct *) XGI_VBVCLKData ;
+ pVBInfo->ScreenOffset = XGI330_ScreenOffset ;
+ pVBInfo->StResInfo = (XGI_StResInfoStruct *) XGI330_StResInfo ;
+ pVBInfo->ModeResInfo = (XGI_ModeResInfoStruct *) XGI330_ModeResInfo ;
+
+ pVBInfo->pOutputSelect = &XGI330_OutputSelect ;
+ pVBInfo->pSoftSetting = &XGI330_SoftSetting ;
+ pVBInfo->pSR07 = &XGI330_SR07 ;
+ pVBInfo->LCDResInfo = 0 ;
+ pVBInfo->LCDTypeInfo = 0 ;
+ pVBInfo->LCDInfo = 0 ;
+ pVBInfo->VBInfo = 0 ;
+ pVBInfo->TVInfo = 0;
+
+
+ pVBInfo->SR15 = XGI340_SR13 ;
+ pVBInfo->CR40 = XGI340_cr41 ;
+ pVBInfo->SR25 = XGI330_sr25 ;
+ pVBInfo->pSR31 = &XGI330_sr31 ;
+ pVBInfo->pSR32 = &XGI330_sr32 ;
+ pVBInfo->CR6B = XGI340_CR6B ;
+ pVBInfo->CR6E = XGI340_CR6E ;
+ pVBInfo->CR6F = XGI340_CR6F ;
+ pVBInfo->CR89 = XGI340_CR89 ;
+ pVBInfo->AGPReg = XGI340_AGPReg ;
+ pVBInfo->SR16 = XGI340_SR16 ;
+ pVBInfo->pCRCF = &XG40_CRCF ;
+ pVBInfo->pXGINew_DRAMTypeDefinition = &XG40_DRAMTypeDefinition ;
+
+
+ pVBInfo->CR49 = XGI330_CR49 ;
+ pVBInfo->pSR1F = &XGI330_SR1F ;
+ pVBInfo->pSR21 = &XGI330_SR21 ;
+ pVBInfo->pSR22 = &XGI330_SR22 ;
+ pVBInfo->pSR23 = &XGI330_SR23 ;
+ pVBInfo->pSR24 = &XGI330_SR24 ;
+ pVBInfo->pSR33 = &XGI330_SR33 ;
+
+
+
+ pVBInfo->pCRT2Data_1_2 = &XGI330_CRT2Data_1_2 ;
+ pVBInfo->pCRT2Data_4_D = &XGI330_CRT2Data_4_D ;
+ pVBInfo->pCRT2Data_4_E = &XGI330_CRT2Data_4_E ;
+ pVBInfo->pCRT2Data_4_10 = &XGI330_CRT2Data_4_10 ;
+ pVBInfo->pRGBSenseData = &XGI330_RGBSenseData ;
+ pVBInfo->pVideoSenseData = &XGI330_VideoSenseData ;
+ pVBInfo->pYCSenseData = &XGI330_YCSenseData ;
+ pVBInfo->pRGBSenseData2 = &XGI330_RGBSenseData2 ;
+ pVBInfo->pVideoSenseData2 = &XGI330_VideoSenseData2 ;
+ pVBInfo->pYCSenseData2 = &XGI330_YCSenseData2 ;
+
+ pVBInfo->NTSCTiming = XGI330_NTSCTiming ;
+ pVBInfo->PALTiming = XGI330_PALTiming ;
+ pVBInfo->HiTVExtTiming = XGI330_HiTVExtTiming ;
+ pVBInfo->HiTVSt1Timing = XGI330_HiTVSt1Timing ;
+ pVBInfo->HiTVSt2Timing = XGI330_HiTVSt2Timing ;
+ pVBInfo->HiTVTextTiming = XGI330_HiTVTextTiming ;
+ pVBInfo->YPbPr750pTiming = XGI330_YPbPr750pTiming ;
+ pVBInfo->YPbPr525pTiming = XGI330_YPbPr525pTiming ;
+ pVBInfo->YPbPr525iTiming = XGI330_YPbPr525iTiming ;
+ pVBInfo->HiTVGroup3Data = XGI330_HiTVGroup3Data ;
+ pVBInfo->HiTVGroup3Simu = XGI330_HiTVGroup3Simu ;
+ pVBInfo->HiTVGroup3Text = XGI330_HiTVGroup3Text ;
+ pVBInfo->Ren525pGroup3 = XGI330_Ren525pGroup3 ;
+ pVBInfo->Ren750pGroup3 = XGI330_Ren750pGroup3 ;
+
+
+ pVBInfo->TimingH = (XGI_TimingHStruct *) XGI_TimingH ;
+ pVBInfo->TimingV = (XGI_TimingVStruct *) XGI_TimingV ;
+ pVBInfo->UpdateCRT1 = (XGI_XG21CRT1Struct *) XGI_UpdateCRT1Table ;
+
+ pVBInfo->CHTVVCLKUNTSC = XGI330_CHTVVCLKUNTSC ;
+ pVBInfo->CHTVVCLKONTSC = XGI330_CHTVVCLKONTSC ;
+ pVBInfo->CHTVVCLKUPAL = XGI330_CHTVVCLKUPAL ;
+ pVBInfo->CHTVVCLKOPAL = XGI330_CHTVVCLKOPAL ;
+
+ /* 310 customization related */
+ if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
+ pVBInfo->LCDCapList = XGI_LCDDLCapList ;
+ else
+ pVBInfo->LCDCapList = XGI_LCDCapList ;
+
+ if ( ( ChipType == XG21 ) || ( ChipType == XG27 ) )
+ pVBInfo->XG21_LVDSCapList = XGI21_LCDCapList ;
+
+ pVBInfo->XGI_TVDelayList = XGI301TVDelayList ;
+ pVBInfo->XGI_TVDelayList2 = XGI301TVDelayList2 ;
+
+
+ pVBInfo->pXGINew_I2CDefinition = &XG40_I2CDefinition ;
+
+ if ( ChipType >= XG20 )
+ pVBInfo->pXGINew_CR97 = &XG20_CR97 ;
+
+ if ( ChipType == XG27 )
+ {
+ pVBInfo->MCLKData = (XGI_MCLKDataStruct *) XGI27New_MCLKData ;
+ pVBInfo->CR40 = XGI27_cr41 ;
+ pVBInfo->pXGINew_CR97 = &XG27_CR97 ;
+ pVBInfo->pSR36 = &XG27_SR36 ;
+ pVBInfo->pCR8F = &XG27_CR8F ;
+ pVBInfo->pCRD0 = XG27_CRD0 ;
+ pVBInfo->pCRDE = XG27_CRDE ;
+ pVBInfo->pSR40 = &XG27_SR40 ;
+ pVBInfo->pSR41 = &XG27_SR41 ;
+
+ }
+
+ if ( ChipType >= XG20 )
+ {
+ pVBInfo->pDVOSetting = &XG21_DVOSetting ;
+ pVBInfo->pCR2E = &XG21_CR2E ;
+ pVBInfo->pCR2F = &XG21_CR2F ;
+ pVBInfo->pCR46 = &XG21_CR46 ;
+ pVBInfo->pCR47 = &XG21_CR47 ;
+ }
+
+}
+
+
+
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGISetModeNew */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGISetModeNew( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo )
+{
+ USHORT ModeIdIndex ;
+ /* PUCHAR pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ; */
+ VB_DEVICE_INFO VBINF;
+ PVB_DEVICE_INFO pVBInfo = &VBINF;
+ pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
+ pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
+ pVBInfo->IF_DEF_LVDS = 0 ;
+ pVBInfo->IF_DEF_CH7005 = 0 ;
+ pVBInfo->IF_DEF_LCDA = 1 ;
+ pVBInfo->IF_DEF_CH7017 = 0 ;
+ pVBInfo->IF_DEF_CH7007 = 0 ; /* [Billy] 2007/05/14 */
+ pVBInfo->IF_DEF_VideoCapture = 0 ;
+ pVBInfo->IF_DEF_ScaleLCD = 0 ;
+ pVBInfo->IF_DEF_OEMUtil = 0 ;
+ pVBInfo->IF_DEF_PWD = 0 ;
+
+
+ if ( HwDeviceExtension->jChipType >= XG20 ) /* kuku 2004/06/25 */
+ {
+ pVBInfo->IF_DEF_YPbPr = 0 ;
+ pVBInfo->IF_DEF_HiVision = 0 ;
+ pVBInfo->IF_DEF_CRT2Monitor = 0 ;
+ pVBInfo->VBType = 0 ; /*set VBType default 0*/
+ }
+ else if ( HwDeviceExtension->jChipType >= XG40 )
+ {
+ pVBInfo->IF_DEF_YPbPr = 1 ;
+ pVBInfo->IF_DEF_HiVision = 1 ;
+ pVBInfo->IF_DEF_CRT2Monitor = 1 ;
+ }
+ else
+ {
+ pVBInfo->IF_DEF_YPbPr = 1 ;
+ pVBInfo->IF_DEF_HiVision = 1 ;
+ pVBInfo->IF_DEF_CRT2Monitor = 0 ;
+ }
+
+ pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
+ pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
+ pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
+ pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
+ pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
+ pVBInfo->P3cc = pVBInfo->BaseAddr + 0x1C ;
+ pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
+ pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
+ pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
+ pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
+ pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
+ pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
+ pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
+ pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
+ pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
+ pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
+ pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
+ pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
+
+ if ( HwDeviceExtension->jChipType == XG21 ) /* for x86 Linux, XG21 LVDS */
+ {
+ if ( ( XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) & 0xE0 ) == 0xC0 )
+ {
+ pVBInfo->IF_DEF_LVDS = 1 ;
+ }
+ }
+ if ( HwDeviceExtension->jChipType == XG27 )
+ {
+ if ( ( XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) & 0xE0 ) == 0xC0 )
+ {
+ if ( XGINew_GetReg1( pVBInfo->P3d4 , 0x30 ) & 0x20 )
+ {
+ pVBInfo->IF_DEF_LVDS = 1 ;
+ }
+ }
+ }
+
+ if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */
+ XGI_GetVBType( pVBInfo ) ;
+
+ InitTo330Pointer( HwDeviceExtension->jChipType, pVBInfo ) ;
+#ifdef WIN2000
+ ReadVBIOSTablData( HwDeviceExtension->jChipType , pVBInfo) ;
+#endif
+ if ( ModeNo & 0x80 )
+ {
+ ModeNo = ModeNo & 0x7F ;
+/* XGINew_flag_clearbuffer = 0 ; */
+ }
+/* else
+ {
+ XGINew_flag_clearbuffer = 1 ;
+ }
+*/
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x05 , 0x86 ) ;
+
+ if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 1.Openkey */
+ XGI_UnLockCRT2( HwDeviceExtension , pVBInfo ) ;
+
+ XGI_SearchModeID( ModeNo , &ModeIdIndex, pVBInfo ) ;
+
+ XGI_GetVGAType(HwDeviceExtension, pVBInfo) ;
+
+ if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */
+ {
+ XGI_GetVBInfo(ModeNo , ModeIdIndex , HwDeviceExtension, pVBInfo ) ;
+ XGI_GetTVInfo(ModeNo , ModeIdIndex, pVBInfo ) ;
+ XGI_GetLCDInfo(ModeNo , ModeIdIndex, pVBInfo ) ;
+ XGI_DisableBridge( HwDeviceExtension,pVBInfo ) ;
+/* XGI_OpenCRTC( HwDeviceExtension, pVBInfo ) ; */
+
+ if ( pVBInfo->VBInfo & ( SetSimuScanMode | SetCRT2ToLCDA ) )
+ {
+ XGI_SetCRT1Group(HwDeviceExtension , ModeNo , ModeIdIndex, pVBInfo ) ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+ {
+ XGI_SetLCDAGroup(ModeNo , ModeIdIndex , HwDeviceExtension, pVBInfo ) ;
+ }
+ }
+ else
+ {
+ if ( !( pVBInfo->VBInfo & SwitchToCRT2) )
+ {
+ XGI_SetCRT1Group( HwDeviceExtension , ModeNo , ModeIdIndex, pVBInfo ) ;
+ if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+ {
+ XGI_SetLCDAGroup( ModeNo , ModeIdIndex , HwDeviceExtension, pVBInfo ) ;
+ }
+ }
+ }
+
+ if ( pVBInfo->VBInfo & ( SetSimuScanMode | SwitchToCRT2 ) )
+ {
+ switch( HwDeviceExtension->ujVBChipID )
+ {
+ case VB_CHIP_301:
+ XGI_SetCRT2Group301( ModeNo , HwDeviceExtension, pVBInfo ) ; /*add for CRT2 */
+ break ;
+
+ case VB_CHIP_302:
+ XGI_SetCRT2Group301(ModeNo , HwDeviceExtension, pVBInfo ) ; /*add for CRT2 */
+ break ;
+
+ default:
+ break ;
+ }
+ }
+
+ XGI_SetCRT2ModeRegs( ModeNo, HwDeviceExtension,pVBInfo ) ;
+ XGI_OEM310Setting( ModeNo, ModeIdIndex,pVBInfo ) ; /*0212*/
+ XGI_CloseCRTC( HwDeviceExtension, pVBInfo ) ;
+ XGI_EnableBridge( HwDeviceExtension ,pVBInfo) ;
+ } /* !XG20 */
+ else
+ {
+#ifdef WIN2000
+ if ( pVBInfo->IF_DEF_CH7007 == 1 )
+ {
+
+ VideoDebugPrint((0, "XGISetModeNew: pVBIfo->IF_DEF_CH7007==1\n"));
+ pVBInfo->VBType = VB_CH7007 ;
+ XGI_GetVBInfo(ModeNo , ModeIdIndex , HwDeviceExtension, pVBInfo ) ;
+ XGI_GetTVInfo(ModeNo , ModeIdIndex, pVBInfo ) ;
+ XGI_GetLCDInfo(ModeNo , ModeIdIndex, pVBInfo ) ;
+ if( !(XGI_XG21CheckCH7007TVMode(ModeNo, ModeIdIndex, pVBInfo )) )
+ {
+ return FALSE;
+ }
+ }
+#endif
+
+
+ if ( pVBInfo->IF_DEF_LVDS == 1 )
+ {
+ if ( !XGI_XG21CheckLVDSMode(ModeNo , ModeIdIndex, pVBInfo) )
+ {
+ return FALSE;
+ }
+ }
+
+ if ( ModeNo <= 0x13 )
+ {
+ pVBInfo->ModeType = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag & ModeInfoFlag;
+ }
+ else
+ {
+ pVBInfo->ModeType = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag & ModeInfoFlag;
+ }
+
+ pVBInfo->SetFlag = 0 ;
+ if ( pVBInfo->IF_DEF_CH7007 != 1 )
+ {
+ pVBInfo->VBInfo = DisableCRT2Display ;
+ }
+
+
+ XGI_DisplayOff(HwDeviceExtension, pVBInfo) ;
+
+ XGI_SetCRT1Group(HwDeviceExtension , ModeNo , ModeIdIndex, pVBInfo ) ;
+
+ XGI_DisplayOn( HwDeviceExtension, pVBInfo ) ;
+ /*
+ if( HwDeviceExtension->jChipType == XG21 )
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x09 , ~0x80 , 0x80 ) ;
+ */
+ }
+
+
+/*
+ if ( ModeNo <= 0x13 )
+ {
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+ }
+ else
+ {
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+ }
+ pVBInfo->ModeType = modeflag&ModeInfoFlag ;
+ pVBInfo->SetFlag = 0x00 ;
+ pVBInfo->VBInfo = DisableCRT2Display ;
+ temp = XGINew_CheckMemorySize( HwDeviceExtension , ModeNo , ModeIdIndex, pVBInfo ) ;
+
+ if ( temp == 0 )
+ return( 0 ) ;
+
+ XGI_DisplayOff( HwDeviceExtension, pVBInfo) ;
+ XGI_SetCRT1Group( HwDeviceExtension , ModeNo , ModeIdIndex, pVBInfo ) ;
+ XGI_DisplayOn( HwDeviceExtension, pVBInfo) ;
+*/
+
+ XGI_UpdateModeInfo( HwDeviceExtension, pVBInfo ) ;
+
+ if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */
+{
+ XGI_LockCRT2( HwDeviceExtension, pVBInfo ) ;
+}
+
+ return( TRUE ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT1Group */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT1Group( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT StandTableIndex ,
+ RefreshRateTableIndex ,
+ b3CC ,
+ temp ;
+
+ USHORT XGINew_P3cc = pVBInfo->P3cc;
+
+ /* XGINew_CRT1Mode = ModeNo ; // SaveModeID */
+ StandTableIndex = XGI_GetModePtr( ModeNo , ModeIdIndex, pVBInfo ) ;
+ /* XGI_SetBIOSData(ModeNo , ModeIdIndex ) ; */
+ /* XGI_ClearBankRegs( ModeNo , ModeIdIndex ) ; */
+ XGI_SetSeqRegs( ModeNo , StandTableIndex , ModeIdIndex, pVBInfo ) ;
+ XGI_SetMiscRegs( StandTableIndex, pVBInfo ) ;
+ XGI_SetCRTCRegs( HwDeviceExtension , StandTableIndex, pVBInfo) ;
+ XGI_SetATTRegs( ModeNo , StandTableIndex , ModeIdIndex, pVBInfo ) ;
+ XGI_SetGRCRegs( StandTableIndex, pVBInfo ) ;
+ XGI_ClearExt1Regs(pVBInfo) ;
+
+/* if ( pVBInfo->IF_DEF_ExpLink ) */
+ if ( HwDeviceExtension->jChipType == XG27 )
+ {
+ if ( pVBInfo->IF_DEF_LVDS == 0 )
+ {
+ XGI_SetDefaultVCLK( pVBInfo ) ;
+ }
+ }
+
+ temp = ~ProgrammingCRT2 ;
+ pVBInfo->SetFlag &= temp ;
+ pVBInfo->SelectCRT2Rate = 0 ;
+
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ if ( pVBInfo->VBInfo & ( SetSimuScanMode | SetCRT2ToLCDA | SetInSlaveMode ) )
+ {
+ pVBInfo->SetFlag |= ProgrammingCRT2 ;
+ }
+ }
+
+ RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, pVBInfo ) ;
+ if ( RefreshRateTableIndex != 0xFFFF )
+ {
+ XGI_SetSync( RefreshRateTableIndex, pVBInfo ) ;
+ XGI_SetCRT1CRTC( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo, HwDeviceExtension ) ;
+ XGI_SetCRT1DE( HwDeviceExtension , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+ XGI_SetCRT1Offset( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ;
+ XGI_SetCRT1VCLK( ModeNo , ModeIdIndex , HwDeviceExtension , RefreshRateTableIndex, pVBInfo ) ;
+ }
+
+ if ( ( HwDeviceExtension->jChipType >= XG20 )&&
+ ( HwDeviceExtension->jChipType < XG27 ) ) /* fix H/W DCLK/2 bug */
+ {
+ if ( ( ModeNo == 0x00 ) | (ModeNo == 0x01) )
+ {
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , 0x4E) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , 0xE9) ;
+ b3CC =(UCHAR) XGINew_GetReg2(XGINew_P3cc) ;
+ XGINew_SetReg3(XGINew_P3cc , (b3CC |= 0x0C) ) ;
+ }
+ else if ( ( ModeNo == 0x04) | ( ModeNo == 0x05) | ( ModeNo == 0x0D) )
+ {
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , 0x1B) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , 0xE3) ;
+ b3CC = (UCHAR)XGINew_GetReg2(XGINew_P3cc) ;
+ XGINew_SetReg3(XGINew_P3cc , (b3CC |= 0x0C) ) ;
+ }
+ }
+
+ if ( HwDeviceExtension->jChipType >= XG21 )
+ {
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ;
+ if ( temp & 0xA0 )
+ {
+
+ /*XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x20 ) ;*/ /* Enable write GPIOF */
+ /*XGINew_SetRegAND( pVBInfo->P3d4 , 0x48 , ~0x20 ) ;*/ /* P. DWN */
+ /* XG21 CRT1 Timing */
+ if ( HwDeviceExtension->jChipType == XG27 )
+ XGI_SetXG27CRTC( ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo );
+ else
+ XGI_SetXG21CRTC( ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo );
+
+ XGI_UpdateXG21CRTC( ModeNo , pVBInfo , RefreshRateTableIndex) ;
+
+ if ( HwDeviceExtension->jChipType == XG27 )
+ XGI_SetXG27LCD( pVBInfo , RefreshRateTableIndex , ModeNo );
+ else
+ XGI_SetXG21LCD( pVBInfo , RefreshRateTableIndex , ModeNo );
+
+ if ( pVBInfo->IF_DEF_LVDS == 1 )
+ {
+ if ( HwDeviceExtension->jChipType == XG27 )
+ XGI_SetXG27LVDSPara(ModeNo,ModeIdIndex, pVBInfo );
+ else
+ XGI_SetXG21LVDSPara(ModeNo,ModeIdIndex, pVBInfo );
+ }
+ /*XGINew_SetRegOR( pVBInfo->P3d4 , 0x48 , 0x20 ) ;*/ /* P. ON */
+ }
+ }
+
+ pVBInfo->SetFlag &= ( ~ProgrammingCRT2 ) ;
+ XGI_SetCRT1FIFO( ModeNo , HwDeviceExtension, pVBInfo ) ;
+ XGI_SetCRT1ModeRegs( HwDeviceExtension , ModeNo , ModeIdIndex , RefreshRateTableIndex , pVBInfo) ;
+
+
+ /* XGI_LoadCharacter(); //dif ifdef TVFont */
+
+ XGI_LoadDAC( ModeNo , ModeIdIndex, pVBInfo ) ;
+ /* XGI_ClearBuffer( HwDeviceExtension , ModeNo, pVBInfo ) ; */
+#ifdef WIN2000
+ if ( pVBInfo->IF_DEF_CH7007 == 1 ) /* [Billy] 2007/05/14 */
+ {
+ VideoDebugPrint((0, "XGI_SetCRT1Group: VBInfo->IF_DEF_CH7007==1\n"));
+ SetCH7007Regs(HwDeviceExtension, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo ) ; /* 07/05/28 */
+ }
+#endif
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetModePtr */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+UCHAR XGI_GetModePtr( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ UCHAR index ;
+
+ if ( ModeNo <= 0x13 )
+ index = pVBInfo->SModeIDTable[ ModeIdIndex ].St_StTableIndex ;
+ else
+ {
+ if ( pVBInfo->ModeType <= 0x02 )
+ index = 0x1B ; /* 02 -> ModeEGA */
+ else
+ index = 0x0F ;
+ }
+ return( index ) ; /* Get pVBInfo->StandTable index */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetBIOSData */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+/*UCHAR XGI_SetBIOSData( USHORT ModeNo , USHORT ModeIdIndex )
+{
+ return( 0 ) ;
+}
+*/
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_ClearBankRegs */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+/*UCHAR XGI_ClearBankRegs( USHORT ModeNo , USHORT ModeIdIndex )
+{
+ return( 0 ) ;
+}
+*/
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetSeqRegs */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetSeqRegs( USHORT ModeNo , USHORT StandTableIndex , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ UCHAR tempah ,
+ SRdata ;
+
+ USHORT i ,
+ modeflag ;
+
+ if ( ModeNo <= 0x13 )
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+ else
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x00 , 0x03 ) ; /* Set SR0 */
+ tempah=pVBInfo->StandTable[ StandTableIndex ].SR[ 0 ] ;
+
+ i = SetCRT2ToLCDA ;
+ if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+ {
+ tempah |= 0x01 ;
+ }
+ else
+ {
+ if ( pVBInfo->VBInfo & ( SetCRT2ToTV | SetCRT2ToLCD ) )
+ {
+ if ( pVBInfo->VBInfo & SetInSlaveMode )
+ tempah |= 0x01 ;
+ }
+ }
+
+ tempah |= 0x20 ; /* screen off */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , tempah ) ; /* Set SR1 */
+
+ for( i = 02 ; i <= 04 ; i++ )
+ {
+ SRdata = pVBInfo->StandTable[ StandTableIndex ].SR[ i - 1 ] ; /* Get SR2,3,4 from file */
+ XGINew_SetReg1( pVBInfo->P3c4 , i , SRdata ) ; /* Set SR2 3 4 */
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetMiscRegs */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetMiscRegs( USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ UCHAR Miscdata ;
+
+ Miscdata = pVBInfo->StandTable[ StandTableIndex ].MISC ; /* Get Misc from file */
+/*
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+ {
+ Miscdata |= 0x0C ;
+ }
+ }
+*/
+
+ XGINew_SetReg3( pVBInfo->P3c2 , Miscdata ) ; /* Set Misc(3c2) */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRTCRegs */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRTCRegs( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ UCHAR CRTCdata ;
+ USHORT i ;
+
+ CRTCdata = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
+ CRTCdata &= 0x7f ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , CRTCdata ) ; /* Unlock CRTC */
+
+ for( i = 0 ; i <= 0x18 ; i++ )
+ {
+ CRTCdata = pVBInfo->StandTable[ StandTableIndex ].CRTC[ i ] ; /* Get CRTC from file */
+ XGINew_SetReg1( pVBInfo->P3d4 , i , CRTCdata ) ; /* Set CRTC( 3d4 ) */
+ }
+/*
+ if ( ( HwDeviceExtension->jChipType == XGI_630 )&& ( HwDeviceExtension->jChipRevision == 0x30 ) )
+ {
+ if ( pVBInfo->VBInfo & SetInSlaveMode )
+ {
+ if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToTV ) )
+ {
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x18 , 0xFE ) ;
+ }
+ }
+ }
+*/
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetATTRegs( USHORT ModeNo , USHORT StandTableIndex , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ UCHAR ARdata ;
+ USHORT i ,
+ modeflag ;
+
+ if ( ModeNo <= 0x13 )
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+ else
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+
+ for( i = 0 ; i <= 0x13 ; i++ )
+ {
+ ARdata = pVBInfo->StandTable[ StandTableIndex ].ATTR[ i ] ;
+ if ( modeflag & Charx8Dot ) /* ifndef Dot9 */
+ {
+ if ( i == 0x13 )
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+ ARdata = 0 ;
+ else
+ {
+ if ( pVBInfo->VBInfo & ( SetCRT2ToTV | SetCRT2ToLCD ) )
+ {
+ if ( pVBInfo->VBInfo & SetInSlaveMode )
+ ARdata = 0 ;
+ }
+ }
+ }
+ }
+
+ XGINew_GetReg2( pVBInfo->P3da ) ; /* reset 3da */
+ XGINew_SetReg3( pVBInfo->P3c0 , i ) ; /* set index */
+ XGINew_SetReg3( pVBInfo->P3c0 , ARdata ) ; /* set data */
+ }
+
+ XGINew_GetReg2( pVBInfo->P3da ) ; /* reset 3da */
+ XGINew_SetReg3( pVBInfo->P3c0 , 0x14 ) ; /* set index */
+ XGINew_SetReg3( pVBInfo->P3c0 , 0x00 ) ; /* set data */
+ XGINew_GetReg2( pVBInfo->P3da ) ; /* Enable Attribute */
+ XGINew_SetReg3( pVBInfo->P3c0 , 0x20 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetGRCRegs */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetGRCRegs( USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ UCHAR GRdata ;
+ USHORT i ;
+
+ for( i = 0 ; i <= 0x08 ; i++ )
+ {
+ GRdata = pVBInfo->StandTable[ StandTableIndex ].GRC[ i ] ; /* Get GR from file */
+ XGINew_SetReg1( pVBInfo->P3ce , i , GRdata ) ; /* Set GR(3ce) */
+ }
+
+ if ( pVBInfo->ModeType > ModeVGA )
+ {
+ GRdata = ( UCHAR )XGINew_GetReg1( pVBInfo->P3ce , 0x05 ) ;
+ GRdata &= 0xBF ; /* 256 color disable */
+ XGINew_SetReg1( pVBInfo->P3ce , 0x05 , GRdata ) ;
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_ClearExt1Regs */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_ClearExt1Regs(PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT i ;
+
+ for( i = 0x0A ; i <= 0x0E ; i++ )
+ XGINew_SetReg1( pVBInfo->P3c4 , i , 0x00 ) ; /* Clear SR0A-SR0E */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetDefaultVCLK */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+UCHAR XGI_SetDefaultVCLK( PVB_DEVICE_INFO pVBInfo )
+{
+
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x31 , ~0x30 , 0x20 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , pVBInfo->VCLKData[ 0 ].SR2B ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , pVBInfo->VCLKData[ 0 ].SR2C ) ;
+
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x31 , ~0x30 , 0x10 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , pVBInfo->VCLKData[ 1 ].SR2B ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , pVBInfo->VCLKData[ 1 ].SR2C ) ;
+
+ XGINew_SetRegAND( pVBInfo->P3c4 , 0x31 , ~0x30 ) ;
+ return( 0 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetRatePtrCRT2 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+USHORT XGI_GetRatePtrCRT2( PXGI_HW_DEVICE_INFO pXGIHWDE, USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ SHORT LCDRefreshIndex[] = { 0x00 , 0x00 , 0x03 , 0x01 } ,
+ LCDARefreshIndex[] = { 0x00 , 0x00 , 0x03 , 0x01 , 0x01 , 0x01 , 0x01 } ;
+
+ USHORT RefreshRateTableIndex , i ,
+ modeflag , index , temp ;
+
+ if ( ModeNo <= 0x13 )
+ {
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+ }
+ else
+ {
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+ }
+
+ if ( pVBInfo->IF_DEF_CH7005 == 1 )
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToTV )
+ {
+ if ( modeflag & HalfDCLK )
+ return( 0 ) ;
+ }
+ }
+
+ if ( ModeNo < 0x14 )
+ return( 0xFFFF ) ;
+
+ index = XGINew_GetReg1( pVBInfo->P3d4 , 0x33 ) ;
+ index = index >> pVBInfo->SelectCRT2Rate ;
+ index &= 0x0F ;
+
+ if ( pVBInfo->LCDInfo & LCDNonExpanding )
+ index = 0 ;
+
+ if ( index > 0 )
+ index-- ;
+
+ if ( pVBInfo->SetFlag & ProgrammingCRT2 )
+ {
+ if ( pVBInfo->IF_DEF_CH7005 == 1 )
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToTV )
+ {
+ index = 0 ;
+ }
+ }
+
+ if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+ {
+ if( pVBInfo->IF_DEF_LVDS == 0 )
+ {
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ temp = LCDARefreshIndex[ pVBInfo->LCDResInfo & 0x0F ] ; /* 301b */
+ else
+ temp = LCDRefreshIndex[ pVBInfo->LCDResInfo & 0x0F ] ;
+
+ if ( index > temp )
+ {
+ index = temp ;
+ }
+ }
+ else
+ {
+ index = 0 ;
+ }
+ }
+ }
+
+ RefreshRateTableIndex = pVBInfo->EModeIDTable[ ModeIdIndex ].REFindex ;
+ ModeNo = pVBInfo->RefIndex[ RefreshRateTableIndex ].ModeID ;
+ if ( pXGIHWDE->jChipType >= XG20 ) /* for XG20, XG21, XG27 */
+ {
+ /*
+ if ( pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag & XG2xNotSupport )
+ {
+ index++;
+ }
+ */
+ if ( ( pVBInfo->RefIndex[ RefreshRateTableIndex ].XRes == 800 ) &&
+ ( pVBInfo->RefIndex[ RefreshRateTableIndex ].YRes == 600 ) )
+ {
+ index++;
+ }
+/* Alan 10/19/2007; do the similiar adjustment like XGISearchCRT1Rate() */
+ if ( ( pVBInfo->RefIndex[ RefreshRateTableIndex ].XRes == 1024 ) &&
+ ( pVBInfo->RefIndex[ RefreshRateTableIndex ].YRes == 768 ) )
+ {
+ index++;
+ }
+ if ( ( pVBInfo->RefIndex[ RefreshRateTableIndex ].XRes == 1280 ) &&
+ ( pVBInfo->RefIndex[ RefreshRateTableIndex ].YRes == 1024 ) )
+ {
+ index++;
+ }
+ }
+
+ i = 0 ;
+ do
+ {
+ if ( pVBInfo->RefIndex[ RefreshRateTableIndex + i ].ModeID != ModeNo )
+ break ;
+ temp = pVBInfo->RefIndex[ RefreshRateTableIndex + i ].Ext_InfoFlag ;
+ temp &= ModeInfoFlag ;
+ if ( temp < pVBInfo->ModeType )
+ break ;
+ i++ ;
+ index-- ;
+
+ } while( index != 0xFFFF ) ;
+ if ( !( pVBInfo->VBInfo & SetCRT2ToRAMDAC ) )
+ {
+ if ( pVBInfo->VBInfo & SetInSlaveMode )
+ {
+ temp = pVBInfo->RefIndex[ RefreshRateTableIndex + i - 1 ].Ext_InfoFlag ;
+ if ( temp & InterlaceMode )
+ {
+ i++ ;
+ }
+ }
+ }
+ i-- ;
+ if ( ( pVBInfo->SetFlag & ProgrammingCRT2 ) )
+ {
+ temp = XGI_AjustCRT2Rate( ModeNo , ModeIdIndex , RefreshRateTableIndex , &i, pVBInfo) ;
+ }
+ return( RefreshRateTableIndex + i ) ; /*return(0x01|(temp1<<1)); */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_AjustCRT2Rate */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_AjustCRT2Rate( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex , USHORT *i, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT tempax ,
+ tempbx ,
+ resinfo ,
+ modeflag ,
+ infoflag ;
+
+ if ( ModeNo <= 0x13 )
+ {
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ModeFlag */
+ }
+ else
+ {
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+ }
+
+ resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;
+ tempbx = pVBInfo->RefIndex[ RefreshRateTableIndex + ( *i ) ].ModeID ;
+ tempax = 0 ;
+
+ if ( pVBInfo->IF_DEF_LVDS == 0 )
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC )
+ {
+ tempax |= SupportRAMDAC2 ;
+
+ if ( pVBInfo->VBType & VB_XGI301C )
+ tempax |= SupportCRT2in301C ;
+ }
+
+ if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) /* 301b */
+ {
+ tempax |= SupportLCD ;
+
+ if ( pVBInfo->LCDResInfo != Panel1280x1024 )
+ {
+ if ( pVBInfo->LCDResInfo != Panel1280x960 )
+ {
+ if ( pVBInfo->LCDInfo & LCDNonExpanding )
+ {
+ if ( resinfo >= 9 )
+ {
+ tempax = 0 ;
+ return( 0 ) ;
+ }
+ }
+ }
+ }
+ }
+
+ if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) /* for HiTV */
+ {
+ if ( ( pVBInfo->VBType & VB_XGI301LV ) && ( pVBInfo->VBExtInfo == VB_YPbPr1080i ) )
+ {
+ tempax |= SupportYPbPr ;
+ if ( pVBInfo->VBInfo & SetInSlaveMode )
+ {
+ if ( resinfo == 4 )
+ return( 0 ) ;
+
+ if ( resinfo == 3 )
+ return( 0 ) ;
+
+ if ( resinfo > 7 )
+ return( 0 ) ;
+ }
+ }
+ else
+ {
+ tempax |= SupportHiVisionTV ;
+ if ( pVBInfo->VBInfo & SetInSlaveMode )
+ {
+ if ( resinfo == 4 )
+ return( 0 ) ;
+
+ if ( resinfo == 3 )
+ {
+ if ( pVBInfo->SetFlag & TVSimuMode )
+ return( 0 ) ;
+ }
+
+ if ( resinfo > 7 )
+ return( 0 ) ;
+ }
+ }
+ }
+ else
+ {
+ if ( pVBInfo->VBInfo & ( SetCRT2ToAVIDEO | SetCRT2ToSVIDEO | SetCRT2ToSCART | SetCRT2ToYPbPr | SetCRT2ToHiVisionTV ) )
+ {
+ tempax |= SupportTV ;
+
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ tempax |= SupportTV1024 ;
+ }
+
+ if ( !( pVBInfo->VBInfo & SetPALTV ) )
+ {
+ if ( modeflag & NoSupportSimuTV )
+ {
+ if ( pVBInfo->VBInfo & SetInSlaveMode )
+ {
+ if ( !( pVBInfo->VBInfo & SetNotSimuMode ) )
+ {
+ return( 0 ) ;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else /* for LVDS */
+ {
+ if ( pVBInfo->IF_DEF_CH7005 == 1 )
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToTV )
+ {
+ tempax |= SupportCHTV ;
+ }
+ }
+
+ if ( pVBInfo->VBInfo & SetCRT2ToLCD )
+ {
+ tempax |= SupportLCD ;
+
+ if ( resinfo > 0x08 )
+ return( 0 ) ; /* 1024x768 */
+
+ if ( pVBInfo->LCDResInfo < Panel1024x768 )
+ {
+ if ( resinfo > 0x07 )
+ return( 0 ) ; /* 800x600 */
+
+ if ( resinfo == 0x04 )
+ return( 0 ) ; /* 512x384 */
+ }
+ }
+ }
+
+ for( ; pVBInfo->RefIndex[ RefreshRateTableIndex + ( *i ) ].ModeID == tempbx ; ( *i )-- )
+ {
+ infoflag = pVBInfo->RefIndex[ RefreshRateTableIndex + ( *i ) ].Ext_InfoFlag ;
+ if ( infoflag & tempax )
+ {
+ return( 1 ) ;
+ }
+ if ( ( *i ) == 0 )
+ break ;
+ }
+
+ for( ( *i ) = 0 ; ; ( *i )++ )
+ {
+ infoflag = pVBInfo->RefIndex[ RefreshRateTableIndex + ( *i ) ].Ext_InfoFlag ;
+ if ( pVBInfo->RefIndex[ RefreshRateTableIndex + ( *i ) ].ModeID != tempbx )
+ {
+ return( 0 ) ;
+ }
+
+ if ( infoflag & tempax )
+ {
+ return( 1 ) ;
+ }
+ }
+ return( 1 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetSync */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetSync(USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT sync ,
+ temp ;
+
+ sync = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag >> 8 ; /* di+0x00 */
+ sync &= 0xC0 ;
+ temp = 0x2F ;
+ temp |= sync ;
+ XGINew_SetReg3( pVBInfo->P3c2 , temp ) ; /* Set Misc(3c2) */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT1CRTC */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT1CRTC( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo, PXGI_HW_DEVICE_INFO HwDeviceExtension )
+{
+ UCHAR index ,
+ data ;
+
+ USHORT i ;
+
+ index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ; /* Get index */
+ index = index&IndexMask ;
+
+ data =( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
+ data &= 0x7F ;
+ XGINew_SetReg1(pVBInfo->P3d4,0x11,data); /* Unlock CRTC */
+
+ for( i = 0 ; i < 8 ; i++ )
+ pVBInfo->TimingH[ 0 ].data[ i ] = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ i ] ;
+
+ for( i = 0 ; i < 7 ; i++ )
+ pVBInfo->TimingV[ 0 ].data[ i ] = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ i + 8 ] ;
+
+ XGI_SetCRT1Timing_H( pVBInfo, HwDeviceExtension ) ;
+
+
+
+ XGI_SetCRT1Timing_V( ModeIdIndex , ModeNo, pVBInfo ) ;
+
+
+ if( pVBInfo->ModeType > 0x03 )
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x14 , 0x4F ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT1Timing_H */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT1Timing_H( PVB_DEVICE_INFO pVBInfo, PXGI_HW_DEVICE_INFO HwDeviceExtension )
+{
+ UCHAR data , data1, pushax;
+ USHORT i , j ;
+
+ /* XGINew_SetReg1( pVBInfo->P3d4 , 0x51 , 0 ) ; */
+ /* XGINew_SetReg1( pVBInfo->P3d4 , 0x56 , 0 ) ; */
+ /* XGINew_SetRegANDOR( pVBInfo->P3d4 ,0x11 , 0x7f , 0x00 ) ; */
+
+ data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ; /* unlock cr0-7 */
+ data &= 0x7F ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , data ) ;
+
+ data = pVBInfo->TimingH[ 0 ].data[ 0 ] ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0 , data ) ;
+
+ for( i = 0x01 ; i <= 0x04 ; i++ )
+ {
+ data = pVBInfo->TimingH[ 0 ].data[ i ] ;
+ XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 1 ) , data ) ;
+ }
+
+ for( i = 0x05 ; i <= 0x06 ; i++ )
+ {
+ data = pVBInfo->TimingH[ 0 ].data[ i ];
+ XGINew_SetReg1( pVBInfo->P3c4 ,( USHORT )( i + 6 ) , data ) ;
+ }
+
+ j = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x0e ) ;
+ j &= 0x1F ;
+ data = pVBInfo->TimingH[ 0 ].data[ 7 ] ;
+ data &= 0xE0 ;
+ data |= j ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x0e , data ) ;
+
+ if ( HwDeviceExtension->jChipType >= XG20 )
+ {
+ data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x04 ) ;
+ data = data - 1 ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x04 , data ) ;
+ data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x05 ) ;
+ data1 = data ;
+ data1 &= 0xE0 ;
+ data &= 0x1F ;
+ if ( data == 0 )
+ {
+ pushax = data ;
+ data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x0c ) ;
+ data &= 0xFB ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x0c , data ) ;
+ data = pushax ;
+ }
+ data = data - 1 ;
+ data |= data1 ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x05 , data ) ;
+ data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x0e ) ;
+ data = data >> 5 ;
+ data = data + 3 ;
+ if ( data > 7 )
+ data = data - 7 ;
+ data = data << 5 ;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0e , ~0xE0 , data ) ;
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT1Timing_V */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT1Timing_V( USHORT ModeIdIndex , USHORT ModeNo,PVB_DEVICE_INFO pVBInfo )
+{
+ UCHAR data ;
+ USHORT i , j ;
+
+ /* XGINew_SetReg1( pVBInfo->P3d4 , 0x51 , 0 ) ; */
+ /* XGINew_SetReg1( pVBInfo->P3d4 , 0x56 , 0 ) ; */
+ /* XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x11 , 0x7f , 0x00 ) ; */
+
+ for( i = 0x00 ; i <= 0x01 ; i++ )
+ {
+ data = pVBInfo->TimingV[ 0 ].data[ i ] ;
+ XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 6 ) , data ) ;
+ }
+
+ for( i = 0x02 ; i <= 0x03 ; i++ )
+ {
+ data = pVBInfo->TimingV[ 0 ].data[ i ] ;
+ XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 0x0e ) , data ) ;
+ }
+
+ for( i = 0x04 ; i <= 0x05 ; i++ )
+ {
+ data = pVBInfo->TimingV[ 0 ].data[ i ] ;
+ XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 0x11 ) , data ) ;
+ }
+
+ j = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x0a ) ;
+ j &= 0xC0 ;
+ data = pVBInfo->TimingV[ 0 ].data[ 6 ] ;
+ data &= 0x3F ;
+ data |= j ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x0a , data ) ;
+
+ data = pVBInfo->TimingV[ 0 ].data[ 6 ] ;
+ data &= 0x80 ;
+ data = data >> 2 ;
+
+ if ( ModeNo <= 0x13 )
+ i = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+ else
+ i = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+
+ i &= DoubleScanMode ;
+ if ( i )
+ data |= 0x80 ;
+
+ j = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x09 ) ;
+ j &= 0x5F ;
+ data |= j ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x09 , data ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetXG21CRTC */
+/* Input : Stand or enhance CRTC table */
+/* Output : Fill CRT Hsync/Vsync to SR2E/SR2F/SR30/SR33/SR34/SR3F */
+/* Description : Set LCD timing */
+/* --------------------------------------------------------------------- */
+void XGI_SetXG21CRTC(USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo)
+{
+ UCHAR StandTableIndex, index, Tempax, Tempbx, Tempcx, Tempdx ;
+ USHORT Temp1, Temp2, Temp3 ;
+
+ if ( ModeNo <= 0x13 )
+ {
+ StandTableIndex = XGI_GetModePtr( ModeNo , ModeIdIndex, pVBInfo ) ;
+ Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 4 ] ; /* CR04 HRS */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , Tempax ) ; /* SR2E [7:0]->HRS */
+ Tempbx = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 5 ] ; /* Tempbx: CR05 HRE */
+ Tempbx &= 0x1F ; /* Tempbx: HRE[4:0] */
+ Tempcx = Tempax ;
+ Tempcx &= 0xE0 ; /* Tempcx: HRS[7:5] */
+ Tempdx = Tempcx | Tempbx ; /* Tempdx(HRE): HRS[7:5]HRE[4:0] */
+ if ( Tempbx < ( Tempax & 0x1F ) ) /* IF HRE < HRS */
+ Tempdx |= 0x20 ; /* Tempdx: HRE = HRE + 0x20 */
+ Tempdx <<= 2 ; /* Tempdx << 2 */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2F , Tempdx ) ; /* SR2F [7:2]->HRE */
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , 0xE3 , 00 ) ;
+
+ Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 16 ] ; /* Tempax: CR16 VRS */
+ Tempbx = Tempax ; /* Tempbx=Tempax */
+ Tempax &= 0x01 ; /* Tempax: VRS[0] */
+ XGINew_SetRegOR( pVBInfo->P3c4 , 0x33 , Tempax ) ; /* SR33[0]->VRS */
+ Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 7 ] ; /* Tempax: CR7 VRS */
+ Tempdx = Tempbx >> 1 ; /* Tempdx: VRS[7:1] */
+ Tempcx = Tempax & 0x04 ; /* Tempcx: CR7[2] */
+ Tempcx <<= 5 ; /* Tempcx[7]: VRS[8] */
+ Tempdx |= Tempcx ; /* Tempdx: VRS[8:1] */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , Tempdx ) ; /* SR34[7:0]: VRS[8:1] */
+
+ Temp1 = Tempcx << 1 ; /* Temp1[8]: VRS[8] UCHAR -> USHORT */
+ Temp1 |= Tempbx ; /* Temp1[8:0]: VRS[8:0] */
+ Tempax &= 0x80 ; /* Tempax[7]: CR7[7] */
+ Temp2 = Tempax << 2 ; /* Temp2[9]: VRS[9] */
+ Temp1 |= Temp2 ; /* Temp1[9:0]: VRS[9:0] */
+
+ Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 17 ] ; /* CR16 VRE */
+ Tempax &= 0x0F ; /* Tempax[3:0]: VRE[3:0] */
+ Temp2 = Temp1 & 0x3F0 ; /* Temp2[9:4]: VRS[9:4] */
+ Temp2 |= Tempax ; /* Temp2[9:0]: VRE[9:0] */
+ Temp3 = Temp1 & 0x0F ; /* Temp3[3:0]: VRS[3:0] */
+ if ( Tempax < Temp3 ) /* VRE[3:0]<VRS[3:0] */
+ Temp2 |= 0x10 ; /* Temp2: VRE + 0x10 */
+ Temp2 &= 0xFF ; /* Temp2[7:0]: VRE[7:0] */
+ Tempax = (UCHAR)Temp2 ; /* Tempax[7:0]: VRE[7:0] */
+ Tempax <<= 2 ; /* Tempax << 2: VRE[5:0] */
+ Temp1 &= 0x600 ; /* Temp1[10:9]: VRS[10:9] */
+ Temp1 >>= 9 ; /* [10:9]->[1:0] */
+ Tempbx = (UCHAR)Temp1 ; /* Tempbx[1:0]: VRS[10:9] */
+ Tempax |= Tempbx ; /* VRE[5:0]VRS[10:9] */
+ Tempax &= 0x7F ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x3F , Tempax ) ; /* SR3F D[7:2]->VRE D[1:0]->VRS */
+ }
+ else
+ {
+ index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ;
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 3 ] ; /* Tempax: CR4 HRS */
+ Tempcx = Tempax ; /* Tempcx: HRS */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , Tempax ) ; /* SR2E[7:0]->HRS */
+
+ Tempdx = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 5 ] ; /* SRB */
+ Tempdx &= 0xC0 ; /* Tempdx[7:6]: SRB[7:6] */
+ Temp1 = Tempdx ; /* Temp1[7:6]: HRS[9:8] */
+ Temp1 <<= 2 ; /* Temp1[9:8]: HRS[9:8] */
+ Temp1 |= Tempax ; /* Temp1[9:0]: HRS[9:0] */
+
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 4 ] ; /* CR5 HRE */
+ Tempax &= 0x1F ; /* Tempax[4:0]: HRE[4:0] */
+
+ Tempbx = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 6 ] ; /* SRC */
+ Tempbx &= 0x04 ; /* Tempbx[2]: HRE[5] */
+ Tempbx <<= 3 ; /* Tempbx[5]: HRE[5] */
+ Tempax |= Tempbx ; /* Tempax[5:0]: HRE[5:0] */
+
+ Temp2 = Temp1 & 0x3C0 ; /* Temp2[9:6]: HRS[9:6] */
+ Temp2 |= Tempax ; /* Temp2[9:0]: HRE[9:0] */
+
+ Tempcx &= 0x3F ; /* Tempcx[5:0]: HRS[5:0] */
+ if( Tempax < Tempcx ) /* HRE < HRS */
+ Temp2 |= 0x40 ; /* Temp2 + 0x40 */
+
+ Temp2 &= 0xFF ;
+ Tempax = (UCHAR)Temp2 ; /* Tempax: HRE[7:0] */
+ Tempax <<= 2 ; /* Tempax[7:2]: HRE[5:0] */
+ Tempdx >>= 6 ; /* Tempdx[7:6]->[1:0] HRS[9:8] */
+ Tempax |= Tempdx ; /* HRE[5:0]HRS[9:8] */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2F , Tempax ) ; /* SR2F D[7:2]->HRE, D[1:0]->HRS */
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , 0xE3 , 00 ) ;
+
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 10 ] ; /* CR10 VRS */
+ Tempbx = Tempax ; /* Tempbx: VRS */
+ Tempax &= 0x01 ; /* Tempax[0]: VRS[0] */
+ XGINew_SetRegOR( pVBInfo->P3c4 , 0x33 , Tempax ) ; /* SR33[0]->VRS[0] */
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 9 ] ; /* CR7[2][7] VRE */
+ Tempcx = Tempbx >> 1 ; /* Tempcx[6:0]: VRS[7:1] */
+ Tempdx = Tempax & 0x04 ; /* Tempdx[2]: CR7[2] */
+ Tempdx <<= 5 ; /* Tempdx[7]: VRS[8] */
+ Tempcx |= Tempdx ; /* Tempcx[7:0]: VRS[8:1] */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , Tempcx ) ; /* SR34[8:1]->VRS */
+
+ Temp1 = Tempdx ; /* Temp1[7]: Tempdx[7] */
+ Temp1 <<= 1 ; /* Temp1[8]: VRS[8] */
+ Temp1 |= Tempbx ; /* Temp1[8:0]: VRS[8:0] */
+ Tempax &= 0x80 ;
+ Temp2 = Tempax << 2 ; /* Temp2[9]: VRS[9] */
+ Temp1 |= Temp2 ; /* Temp1[9:0]: VRS[9:0] */
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 14 ] ; /* Tempax: SRA */
+ Tempax &= 0x08 ; /* Tempax[3]: VRS[3] */
+ Temp2 = Tempax ;
+ Temp2 <<= 7 ; /* Temp2[10]: VRS[10] */
+ Temp1 |= Temp2 ; /* Temp1[10:0]: VRS[10:0] */
+
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 11 ] ; /* Tempax: CR11 VRE */
+ Tempax &= 0x0F ; /* Tempax[3:0]: VRE[3:0] */
+ Tempbx = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 14 ] ; /* Tempbx: SRA */
+ Tempbx &= 0x20 ; /* Tempbx[5]: VRE[5] */
+ Tempbx >>= 1 ; /* Tempbx[4]: VRE[4] */
+ Tempax |= Tempbx ; /* Tempax[4:0]: VRE[4:0] */
+ Temp2 = Temp1 & 0x7E0 ; /* Temp2[10:5]: VRS[10:5] */
+ Temp2 |= Tempax ; /* Temp2[10:5]: VRE[10:5] */
+
+ Temp3 = Temp1 & 0x1F ; /* Temp3[4:0]: VRS[4:0] */
+ if ( Tempax < Temp3 ) /* VRE < VRS */
+ Temp2 |= 0x20 ; /* VRE + 0x20 */
+
+ Temp2 &= 0xFF ;
+ Tempax = (UCHAR)Temp2 ; /* Tempax: VRE[7:0] */
+ Tempax <<= 2 ; /* Tempax[7:0]; VRE[5:0]00 */
+ Temp1 &= 0x600 ; /* Temp1[10:9]: VRS[10:9] */
+ Temp1 >>= 9 ; /* Temp1[1:0]: VRS[10:9] */
+ Tempbx = (UCHAR)Temp1 ;
+ Tempax |= Tempbx ; /* Tempax[7:0]: VRE[5:0]VRS[10:9] */
+ Tempax &= 0x7F ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x3F , Tempax ) ; /* SR3F D[7:2]->VRE D[1:0]->VRS */
+ }
+}
+
+void XGI_SetXG27CRTC(USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT StandTableIndex, index, Tempax, Tempbx, Tempcx, Tempdx ;
+
+ if ( ModeNo <= 0x13 )
+ {
+ StandTableIndex = XGI_GetModePtr( ModeNo , ModeIdIndex, pVBInfo ) ;
+ Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 4 ] ; /* CR04 HRS */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , Tempax ) ; /* SR2E [7:0]->HRS */
+ Tempbx = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 5 ] ; /* Tempbx: CR05 HRE */
+ Tempbx &= 0x1F ; /* Tempbx: HRE[4:0] */
+ Tempcx = Tempax ;
+ Tempcx &= 0xE0 ; /* Tempcx: HRS[7:5] */
+ Tempdx = Tempcx | Tempbx ; /* Tempdx(HRE): HRS[7:5]HRE[4:0] */
+ if ( Tempbx < ( Tempax & 0x1F ) ) /* IF HRE < HRS */
+ Tempdx |= 0x20 ; /* Tempdx: HRE = HRE + 0x20 */
+ Tempdx <<= 2 ; /* Tempdx << 2 */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2F , Tempdx ) ; /* SR2F [7:2]->HRE */
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , 0xE3 , 00 ) ;
+
+ Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 16 ] ; /* Tempax: CR10 VRS */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , Tempax ) ; /* SR34[7:0]->VRS */
+ Tempcx = Tempax ; /* Tempcx=Tempax=VRS[7:0] */
+ Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 7 ] ; /* Tempax[7][2]: CR7[7][2] VRS[9][8] */
+ Tempbx = Tempax ; /* Tempbx=CR07 */
+ Tempax &= 0x04 ; /* Tempax[2]: CR07[2] VRS[8] */
+ Tempax >>= 2;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x01, Tempax ) ; /* SR35 D[0]->VRS D[8] */
+ Tempcx |= (Tempax << 8) ; /* Tempcx[8] |= VRS[8] */
+ Tempcx |= (Tempbx & 0x80)<<2; /* Tempcx[9] |= VRS[9] */
+
+
+ Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 17 ] ; /* CR11 VRE */
+ Tempax &= 0x0F ; /* Tempax: VRE[3:0] */
+ Tempbx = Tempcx ; /* Tempbx=Tempcx=VRS[9:0] */
+ Tempbx &= 0x3F0 ; /* Tempbx[9:4]: VRS[9:4] */
+ Tempbx |= Tempax ; /* Tempbx[9:0]: VRE[9:0] */
+ if ( Tempax <= (Tempcx & 0x0F) ) /* VRE[3:0]<=VRS[3:0] */
+ Tempbx |= 0x10 ; /* Tempbx: VRE + 0x10 */
+ Tempax = (UCHAR)Tempbx & 0xFF; /* Tempax[7:0]: VRE[7:0] */
+ Tempax <<= 2 ; /* Tempax << 2: VRE[5:0] */
+ Tempcx = (Tempcx&0x600)>>8; /* Tempcx VRS[10:9] */
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x3F , ~0xFC, Tempax ) ; /* SR3F D[7:2]->VRE D[5:0] */
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x06, Tempcx ) ; /* SR35 D[2:1]->VRS[10:9] */
+ }
+ else
+ {
+ index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ;
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 3 ] ; /* Tempax: CR4 HRS */
+ Tempbx = Tempax ; /* Tempbx: HRS[7:0] */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , Tempax ) ; /* SR2E[7:0]->HRS */
+
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 5 ] ; /* SR0B */
+ Tempax &= 0xC0 ; /* Tempax[7:6]: SR0B[7:6]: HRS[9:8]*/
+ Tempbx |= (Tempax << 2); /* Tempbx: HRS[9:0] */
+
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 4 ] ; /* CR5 HRE */
+ Tempax &= 0x1F ; /* Tempax[4:0]: HRE[4:0] */
+ Tempcx = Tempax ; /* Tempcx: HRE[4:0] */
+
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 6 ] ; /* SRC */
+ Tempax &= 0x04 ; /* Tempax[2]: HRE[5] */
+ Tempax <<= 3 ; /* Tempax[5]: HRE[5] */
+ Tempcx |= Tempax ; /* Tempcx[5:0]: HRE[5:0] */
+
+ Tempbx = Tempbx & 0x3C0 ; /* Tempbx[9:6]: HRS[9:6] */
+ Tempbx |= Tempcx ; /* Tempbx: HRS[9:6]HRE[5:0] */
+
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 3 ] ; /* Tempax: CR4 HRS */
+ Tempax &= 0x3F ; /* Tempax: HRS[5:0] */
+ if( Tempcx <= Tempax ) /* HRE[5:0] < HRS[5:0] */
+ Tempbx += 0x40 ; /* Tempbx= Tempbx + 0x40 : HRE[9:0]*/
+
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 5 ] ; /* SR0B */
+ Tempax &= 0xC0 ; /* Tempax[7:6]: SR0B[7:6]: HRS[9:8]*/
+ Tempax >>= 6; /* Tempax[1:0]: HRS[9:8]*/
+ Tempax |= ((Tempbx << 2) & 0xFF); /* Tempax[7:2]: HRE[5:0] */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2F , Tempax ) ; /* SR2F [7:2][1:0]: HRE[5:0]HRS[9:8] */
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , 0xE3 , 00 ) ;
+
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 10 ] ; /* CR10 VRS */
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , Tempax ) ; /* SR34[7:0]->VRS[7:0] */
+
+ Tempcx = Tempax ; /* Tempcx <= VRS[7:0] */
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 9 ] ; /* CR7[7][2] VRS[9][8] */
+ Tempbx = Tempax ; /* Tempbx <= CR07[7:0] */
+ Tempax = Tempax & 0x04 ; /* Tempax[2]: CR7[2]: VRS[8] */
+ Tempax >>= 2 ; /* Tempax[0]: VRS[8] */
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x01 , Tempax ) ; /* SR35[0]: VRS[8] */
+ Tempcx |= (Tempax<<8) ; /* Tempcx <= VRS[8:0] */
+ Tempcx |= ((Tempbx&0x80)<<2) ; /* Tempcx <= VRS[9:0] */
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 14 ] ; /* Tempax: SR0A */
+ Tempax &= 0x08; /* SR0A[3] VRS[10] */
+ Tempcx |= (Tempax<<7) ; /* Tempcx <= VRS[10:0] */
+
+
+ Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 11 ] ; /* Tempax: CR11 VRE */
+ Tempax &= 0x0F ; /* Tempax[3:0]: VRE[3:0] */
+ Tempbx = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 14 ] ; /* Tempbx: SR0A */
+ Tempbx &= 0x20 ; /* Tempbx[5]: SR0A[5]: VRE[4] */
+ Tempbx >>= 1 ; /* Tempbx[4]: VRE[4] */
+ Tempax |= Tempbx ; /* Tempax[4:0]: VRE[4:0] */
+ Tempbx = Tempcx ; /* Tempbx: VRS[10:0] */
+ Tempbx &= 0x7E0 ; /* Tempbx[10:5]: VRS[10:5] */
+ Tempbx |= Tempax ; /* Tempbx: VRS[10:5]VRE[4:0] */
+
+ if ( Tempbx <= Tempcx ) /* VRE <= VRS */
+ Tempbx |= 0x20 ; /* VRE + 0x20 */
+
+ Tempax = (Tempbx<<2) & 0xFF ; /* Tempax: Tempax[7:0]; VRE[5:0]00 */
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x3F , ~0xFC , Tempax ) ; /* SR3F[7:2]:VRE[5:0] */
+ Tempax = Tempcx >> 8;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x07 , Tempax ) ; /* SR35[2:0]:VRS[10:8] */
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetXG21LCD */
+/* Input : */
+/* Output : FCLK duty cycle, FCLK delay compensation */
+/* Description : All values set zero */
+/* --------------------------------------------------------------------- */
+void XGI_SetXG21LCD(PVB_DEVICE_INFO pVBInfo,USHORT RefreshRateTableIndex,USHORT ModeNo)
+{
+ USHORT Data , Temp , b3CC ;
+ USHORT XGI_P3cc ;
+
+ XGI_P3cc = pVBInfo->P3cc ;
+
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x2E , 0x00 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x2F , 0x00 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x46 , 0x00 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x47 , 0x00 ) ;
+ if ( ((*pVBInfo->pDVOSetting)&0xC0) == 0xC0 )
+ {
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x2E , *pVBInfo->pCR2E ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x2F , *pVBInfo->pCR2F ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x46 , *pVBInfo->pCR46 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x47 , *pVBInfo->pCR47 ) ;
+ }
+
+ Temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x37 ) ;
+
+ if ( Temp & 0x01 )
+ {
+ XGINew_SetRegOR( pVBInfo->P3c4 , 0x06 , 0x40 ) ; /* 18 bits FP */
+ XGINew_SetRegOR( pVBInfo->P3c4 , 0x09 , 0x40 ) ;
+ }
+
+ XGINew_SetRegOR( pVBInfo->P3c4 , 0x1E , 0x01 ) ; /* Negative blank polarity */
+
+ XGINew_SetRegAND( pVBInfo->P3c4 , 0x30 , ~0x20 ) ;
+ XGINew_SetRegAND( pVBInfo->P3c4 , 0x35 , ~0x80 ) ;
+
+ if ( ModeNo <= 0x13 )
+ {
+ b3CC = (UCHAR) XGINew_GetReg2( XGI_P3cc ) ;
+ if ( b3CC & 0x40 )
+ XGINew_SetRegOR( pVBInfo->P3c4 , 0x30 , 0x20 ) ; /* Hsync polarity */
+ if ( b3CC & 0x80 )
+ XGINew_SetRegOR( pVBInfo->P3c4 , 0x35 , 0x80 ) ; /* Vsync polarity */
+ }
+ else
+ {
+ Data = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ;
+ if ( Data & 0x4000 )
+ XGINew_SetRegOR( pVBInfo->P3c4 , 0x30 , 0x20 ) ; /* Hsync polarity */
+ if ( Data & 0x8000 )
+ XGINew_SetRegOR( pVBInfo->P3c4 , 0x35 , 0x80 ) ; /* Vsync polarity */
+ }
+}
+
+void XGI_SetXG27LCD(PVB_DEVICE_INFO pVBInfo,USHORT RefreshRateTableIndex,USHORT ModeNo)
+{
+ USHORT Data , Temp , b3CC ;
+ USHORT XGI_P3cc ;
+
+ XGI_P3cc = pVBInfo->P3cc ;
+
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x2E , 0x00 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x2F , 0x00 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x46 , 0x00 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x47 , 0x00 ) ;
+
+ Temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x37 ) ;
+ if ( ( Temp & 0x03 ) == 0 ) /* dual 12 */
+ {
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x46 , 0x13 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x47 , 0x13 ) ;
+ }
+
+ if ( ((*pVBInfo->pDVOSetting)&0xC0) == 0xC0 )
+ {
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x2E , *pVBInfo->pCR2E ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x2F , *pVBInfo->pCR2F ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x46 , *pVBInfo->pCR46 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x47 , *pVBInfo->pCR47 ) ;
+ }
+
+ XGI_SetXG27FPBits(pVBInfo);
+
+ XGINew_SetRegOR( pVBInfo->P3c4 , 0x1E , 0x01 ) ; /* Negative blank polarity */
+
+ XGINew_SetRegAND( pVBInfo->P3c4 , 0x30 , ~0x20 ) ; /* Hsync polarity */
+ XGINew_SetRegAND( pVBInfo->P3c4 , 0x35 , ~0x80 ) ; /* Vsync polarity */
+
+ if ( ModeNo <= 0x13 )
+ {
+ b3CC = (UCHAR) XGINew_GetReg2( XGI_P3cc ) ;
+ if ( b3CC & 0x40 )
+ XGINew_SetRegOR( pVBInfo->P3c4 , 0x30 , 0x20 ) ; /* Hsync polarity */
+ if ( b3CC & 0x80 )
+ XGINew_SetRegOR( pVBInfo->P3c4 , 0x35 , 0x80 ) ; /* Vsync polarity */
+ }
+ else
+ {
+ Data = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ;
+ if ( Data & 0x4000 )
+ XGINew_SetRegOR( pVBInfo->P3c4 , 0x30 , 0x20 ) ; /* Hsync polarity */
+ if ( Data & 0x8000 )
+ XGINew_SetRegOR( pVBInfo->P3c4 , 0x35 , 0x80 ) ; /* Vsync polarity */
+ }
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_UpdateXG21CRTC */
+/* Input : */
+/* Output : CRT1 CRTC */
+/* Description : Modify CRT1 Hsync/Vsync to fix LCD mode timing */
+/* --------------------------------------------------------------------- */
+void XGI_UpdateXG21CRTC( USHORT ModeNo , PVB_DEVICE_INFO pVBInfo , USHORT RefreshRateTableIndex )
+{
+ int i , index = -1;
+
+ XGINew_SetRegAND( pVBInfo->P3d4 , 0x11 , 0x7F ) ; /* Unlock CR0~7 */
+ if ( ModeNo <= 0x13 )
+ {
+ for( i = 0 ; i < 12 ; i++ )
+ {
+ if ( ModeNo == pVBInfo->UpdateCRT1[ i ].ModeID )
+ index = i ;
+ }
+ }
+ else
+ {
+ if ( ModeNo == 0x2E && ( pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC == RES640x480x60 ) )
+ index = 12 ;
+ else if ( ModeNo == 0x2E && ( pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC == RES640x480x72 ) )
+ index = 13 ;
+ else if ( ModeNo == 0x2F )
+ index = 14 ;
+ else if ( ModeNo == 0x50 )
+ index = 15 ;
+ else if ( ModeNo == 0x59 )
+ index = 16 ;
+ }
+
+ if( index != -1 )
+ {
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x02 , pVBInfo->UpdateCRT1[ index ].CR02 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x03 , pVBInfo->UpdateCRT1[ index ].CR03 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x15 , pVBInfo->UpdateCRT1[ index ].CR15 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x16 , pVBInfo->UpdateCRT1[ index ].CR16 ) ;
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT1DE */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT1DE( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo,USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT resindex ,
+ tempax ,
+ tempbx ,
+ tempcx ,
+ temp ,
+ modeflag ;
+
+ UCHAR data ;
+
+ resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
+
+ if ( ModeNo <= 0x13 )
+ {
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+ tempax = pVBInfo->StResInfo[ resindex ].HTotal ;
+ tempbx = pVBInfo->StResInfo[ resindex ].VTotal ;
+ }
+ else
+ {
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+ tempax = pVBInfo->ModeResInfo[ resindex ].HTotal ;
+ tempbx = pVBInfo->ModeResInfo[ resindex ].VTotal ;
+ }
+
+ if ( modeflag & HalfDCLK )
+ tempax = tempax >> 1 ;
+
+ if ( ModeNo > 0x13 )
+ {
+ if ( modeflag & HalfDCLK )
+ tempax = tempax << 1 ;
+
+ temp = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ;
+
+ if ( temp & InterlaceMode )
+ tempbx = tempbx >> 1 ;
+
+ if ( modeflag & DoubleScanMode )
+ tempbx = tempbx << 1 ;
+ }
+
+ tempcx = 8 ;
+
+ /* if ( !( modeflag & Charx8Dot ) ) */
+ /* tempcx = 9 ; */
+
+ tempax /= tempcx ;
+ tempax -= 1 ;
+ tempbx -= 1 ;
+ tempcx = tempax ;
+ temp = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
+ data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
+ data &= 0x7F ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , data ) ; /* Unlock CRTC */
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x01 , ( USHORT )( tempcx & 0xff ) ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x0b , ~0x0c , ( USHORT )( ( tempcx & 0x0ff00 ) >> 10 ) ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x12 , ( USHORT )( tempbx & 0xff ) ) ;
+ tempax = 0 ;
+ tempbx = tempbx >> 8 ;
+
+ if ( tempbx & 0x01 )
+ tempax |= 0x02 ;
+
+ if ( tempbx & 0x02 )
+ tempax |= 0x40 ;
+
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x42 , tempax ) ;
+ data =( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x07 ) ;
+ data &= 0xFF ;
+ tempax = 0 ;
+
+ if ( tempbx & 0x04 )
+ tempax |= 0x02 ;
+
+ XGINew_SetRegANDOR( pVBInfo->P3d4 ,0x0a , ~0x02 , tempax ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , temp ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetResInfo */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+USHORT XGI_GetResInfo(USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT resindex ;
+
+ if ( ModeNo <= 0x13 )
+ {
+ resindex = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ; /* si+St_ResInfo */
+ }
+ else
+ {
+ resindex = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ; /* si+Ext_ResInfo */
+ }
+ return( resindex ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT1Offset */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT1Offset( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT temp ,
+ ah ,
+ al ,
+ temp2 ,
+ i ,
+ DisplayUnit ;
+
+ /* GetOffset */
+ temp = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeInfo ;
+ temp = temp >> 8 ;
+ temp = pVBInfo->ScreenOffset[ temp ] ;
+
+ temp2 = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ;
+ temp2 &= InterlaceMode ;
+
+ if ( temp2 )
+ temp = temp << 1;
+
+ temp2 = pVBInfo->ModeType - ModeEGA ;
+
+ switch( temp2 )
+ {
+ case 0:
+ temp2 = 1 ;
+ break ;
+ case 1:
+ temp2 = 2 ;
+ break ;
+ case 2:
+ temp2 = 4 ;
+ break ;
+ case 3:
+ temp2 = 4 ;
+ break ;
+ case 4:
+ temp2 = 6 ;
+ break;
+ case 5:
+ temp2 = 8 ;
+ break ;
+ default:
+ break ;
+ }
+
+ if ( ( ModeNo >= 0x26 ) && ( ModeNo <= 0x28 ) )
+ temp = temp * temp2 + temp2 / 2 ;
+ else
+ temp *= temp2 ;
+
+ /* SetOffset */
+ DisplayUnit = temp ;
+ temp2 = temp ;
+ temp = temp >> 8 ; /* ah */
+ temp &= 0x0F ;
+ i = XGINew_GetReg1( pVBInfo->P3c4 , 0x0E ) ;
+ i &= 0xF0 ;
+ i |= temp ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x0E , i ) ;
+
+ temp =( UCHAR )temp2 ;
+ temp &= 0xFF ; /* al */
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x13 , temp ) ;
+
+ /* SetDisplayUnit */
+ temp2 = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ;
+ temp2 &= InterlaceMode ;
+ if ( temp2 )
+ DisplayUnit >>= 1 ;
+
+ DisplayUnit = DisplayUnit << 5 ;
+ ah = ( DisplayUnit & 0xff00 ) >> 8 ;
+ al = DisplayUnit & 0x00ff ;
+ if ( al == 0 )
+ ah += 1 ;
+ else
+ ah += 2 ;
+
+ if ( HwDeviceExtension->jChipType >= XG20 )
+ if ( ( ModeNo == 0x4A ) | (ModeNo == 0x49 ) )
+ ah -= 1 ;
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x10 , ah ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT1VCLK */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT1VCLK( USHORT ModeNo , USHORT ModeIdIndex ,
+ PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ UCHAR index , data ;
+ USHORT vclkindex ;
+
+ if ( pVBInfo->IF_DEF_LVDS == 1 )
+ {
+ index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRTVCLK ;
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x31 ) & 0xCF ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , data ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , pVBInfo->VCLKData[ index ].SR2B ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , pVBInfo->VCLKData[ index ].SR2C ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2D , 0x01 ) ;
+ }
+ else if ( ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) && ( pVBInfo->VBInfo & SetCRT2ToLCDA ) )
+ {
+ vclkindex = XGI_GetVCLK2Ptr( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ;
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x31 ) & 0xCF ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , data ) ;
+ data = pVBInfo->VBVCLKData[ vclkindex ].Part4_A ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , data ) ;
+ data = pVBInfo->VBVCLKData[ vclkindex ].Part4_B ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , data ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2D , 0x01 ) ;
+ }
+ else
+ {
+ index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRTVCLK ;
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x31 ) & 0xCF ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , data ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , pVBInfo->VCLKData[ index ].SR2B ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , pVBInfo->VCLKData[ index ].SR2C ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2D , 0x01 ) ;
+ }
+
+ if ( HwDeviceExtension->jChipType >= XG20 )
+ {
+ if ( pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag & HalfDCLK )
+ {
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x2B ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , data ) ;
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x2C ) ;
+ index = data ;
+ index &= 0xE0 ;
+ data &= 0x1F ;
+ data = data << 1 ;
+ data += 1 ;
+ data |= index ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , data ) ;
+ }
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT1FIFO */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT1FIFO( USHORT ModeNo , PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT data ;
+
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x3D ) ;
+ data &= 0xfe ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x3D , data ) ; /* diable auto-threshold */
+
+ if ( ModeNo > 0x13 )
+ {
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x08 , 0x34 ) ;
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x09 ) ;
+ data &= 0xC0 ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x09 , data | 0x30) ;
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x3D ) ;
+ data |= 0x01 ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x3D , data ) ;
+ }
+ else
+ {
+ if (HwDeviceExtension->jChipType == XG27)
+ {
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x08 , 0x0E ) ;
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x09 ) ;
+ data &= 0xC0 ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x09 , data | 0x20 ) ;
+ }
+ else
+ {
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x08 , 0xAE ) ;
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x09 ) ;
+ data &= 0xF0 ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x09 , data ) ;
+ }
+ }
+
+ if (HwDeviceExtension->jChipType == XG21)
+ {
+ XGI_SetXG21FPBits(pVBInfo); /* Fix SR9[7:6] can't read back */
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT1ModeRegs */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT1ModeRegs( PXGI_HW_DEVICE_INFO HwDeviceExtension ,
+ USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT data ,
+ data2 ,
+ data3 ,
+ infoflag = 0 ,
+ modeflag ,
+ resindex ,
+ xres ;
+
+ if ( ModeNo > 0x13 )
+ {
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+ infoflag = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ;
+ }
+ else
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ModeFlag */
+
+ if ( XGINew_GetReg1( pVBInfo->P3d4 , 0x31 ) & 0x01 )
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x1F , 0x3F , 0x00 ) ;
+
+ if ( ModeNo > 0x13 )
+ data = infoflag ;
+ else
+ data = 0 ;
+
+ data2 = 0 ;
+
+ if ( ModeNo > 0x13 )
+ {
+ if ( pVBInfo->ModeType > 0x02 )
+ {
+ data2 |= 0x02 ;
+ data3 = pVBInfo->ModeType - ModeVGA ;
+ data3 = data3 << 2 ;
+ data2 |= data3 ;
+ }
+ }
+
+ data &= InterlaceMode ;
+
+ if ( data )
+ data2 |= 0x20 ;
+
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x06 , ~0x3F , data2 ) ;
+ /* XGINew_SetReg1(pVBInfo->P3c4,0x06,data2); */
+ resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
+ if ( ModeNo <= 0x13 )
+ xres = pVBInfo->StResInfo[ resindex ].HTotal ;
+ else
+ xres = pVBInfo->ModeResInfo[ resindex ].HTotal ; /* xres->ax */
+
+ data = 0x0000 ;
+ if ( infoflag & InterlaceMode )
+ {
+ if ( xres == 1024 )
+ data = 0x0035 ;
+ else if ( xres == 1280 )
+ data = 0x0048 ;
+ }
+
+ data2 = data & 0x00FF ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x19 , 0xFF , data2 ) ;
+ data2 = ( data & 0xFF00 ) >> 8 ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x19 , 0xFC , data2 ) ;
+
+ if( modeflag & HalfDCLK )
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x01 , 0xF7 , 0x08 ) ;
+
+ data2 = 0 ;
+
+ if ( modeflag & LineCompareOff )
+ data2 |= 0x08 ;
+
+ if ( ModeNo > 0x13 )
+ {
+ if ( pVBInfo->ModeType == ModeEGA )
+ data2 |= 0x40 ;
+ }
+
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0F , ~0x48 , data2 ) ;
+ data = 0x60 ;
+ if ( pVBInfo->ModeType != ModeText )
+ {
+ data = data ^ 0x60 ;
+ if ( pVBInfo->ModeType != ModeEGA )
+ {
+ data = data ^ 0xA0 ;
+ }
+ }
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x21 , 0x1F , data ) ;
+
+ XGI_SetVCLKState( HwDeviceExtension , ModeNo , RefreshRateTableIndex, pVBInfo) ;
+
+ /* if(modeflag&HalfDCLK)//030305 fix lowresolution bug */
+ /* if(XGINew_IF_DEF_NEW_LOWRES) */
+ /* XGI_VesaLowResolution(ModeNo,ModeIdIndex);//030305 fix lowresolution bug */
+
+ data=XGINew_GetReg1( pVBInfo->P3d4 , 0x31 ) ;
+
+ if (HwDeviceExtension->jChipType == XG27 )
+ {
+ if ( data & 0x40 )
+ data = 0x2c ;
+ else
+ data = 0x6c ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x52 , data ) ;
+ XGINew_SetRegOR( pVBInfo->P3d4 , 0x51 , 0x10 ) ;
+ }
+ else
+ if (HwDeviceExtension->jChipType >= XG20 )
+ {
+ if ( data & 0x40 )
+ data = 0x33 ;
+ else
+ data = 0x73 ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x52 , data ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x51 , 0x02 ) ;
+ }
+ else
+ {
+ if ( data & 0x40 )
+ data = 0x2c ;
+ else
+ data = 0x6c ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x52 , data ) ;
+ }
+
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetVCLKState */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetVCLKState( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo , USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT data ,
+ data2 = 0 ;
+ SHORT VCLK ;
+
+ UCHAR index ;
+
+ if ( ModeNo <= 0x13 )
+ VCLK = 0 ;
+ else
+ {
+ index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRTVCLK ;
+ index &= IndexMask ;
+ VCLK = pVBInfo->VCLKData[ index ].CLOCK ;
+ }
+
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x32 ) ;
+ data &= 0xf3 ;
+ if ( VCLK >= 200 )
+ data |= 0x0c ; /* VCLK > 200 */
+
+ if ( HwDeviceExtension->jChipType >= XG20 )
+ data &= ~0x04 ; /* 2 pixel mode */
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x32 , data ) ;
+
+ if ( HwDeviceExtension->jChipType < XG20 )
+ {
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x1F ) ;
+ data &= 0xE7 ;
+ if ( VCLK < 200 )
+ data |= 0x10 ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x1F , data ) ;
+ }
+
+/* Jong for Adavantech LCD ripple issue
+ if ( ( VCLK >= 0 ) && ( VCLK < 135 ) )
+ data2 = 0x03 ;
+ else if ( ( VCLK >= 135 ) && ( VCLK < 160 ) )
+ data2 = 0x02 ;
+ else if ( ( VCLK >= 160 ) && ( VCLK < 260 ) )
+ data2 = 0x01 ;
+ else if ( VCLK > 260 )
+ data2 = 0x00 ;
+*/
+ data2 = 0x00 ;
+
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x07 , 0xFC , data2 ) ;
+ if (HwDeviceExtension->jChipType >= XG27 )
+ {
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x40 , 0xFC , data2&0x03 ) ;
+ }
+
+
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_VesaLowResolution */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+/*void XGI_VesaLowResolution( USHORT ModeNo , USHORT ModeIdIndex ,PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT modeflag;
+
+ if ( ModeNo > 0x13 )
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+ else
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+
+ if ( ModeNo > 0x13 )
+ {
+ if ( modeflag & DoubleScanMode )
+ {
+ if ( modeflag & HalfDCLK )
+ {
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ if ( !( pVBInfo->VBInfo & SetCRT2ToRAMDAC ) )
+ {
+ if ( pVBInfo->VBInfo & SetInSlaveMode )
+ {
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x01 , 0xf7 , 0x00 ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0f , 0x7f , 0x00 ) ;
+ return ;
+ }
+ }
+ }
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0f , 0xff , 0x80 ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x01 , 0xf7 , 0x00 ) ;
+ return ;
+ }
+ }
+ }
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0f , 0x7f , 0x00 ) ;
+}
+*/
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_LoadDAC */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_LoadDAC( USHORT ModeNo , USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT data , data2 , time ,
+ i , j , k , m , n , o ,
+ si , di , bx , dl , al , ah , dh ,
+ *table = NULL ;
+
+ if ( ModeNo <= 0x13 )
+ data = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+ else
+ data = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+
+ data &= DACInfoFlag ;
+ time = 64 ;
+
+ if ( data == 0x00 )
+ table = XGINew_MDA_DAC ;
+ else if ( data == 0x08 )
+ table = XGINew_CGA_DAC ;
+ else if ( data == 0x10 )
+ table = XGINew_EGA_DAC ;
+ else if ( data == 0x18 )
+ {
+ time = 256 ;
+ table = XGINew_VGA_DAC ;
+ }
+
+ if ( time == 256 )
+ j = 16 ;
+ else
+ j = time ;
+
+ XGINew_SetReg3( pVBInfo->P3c6 , 0xFF ) ;
+ XGINew_SetReg3( pVBInfo->P3c8 , 0x00 ) ;
+
+ for( i = 0 ; i < j ; i++ )
+ {
+ data = table[ i ] ;
+
+ for( k = 0 ; k < 3 ; k++ )
+ {
+ data2 = 0 ;
+
+ if ( data & 0x01 )
+ data2 = 0x2A ;
+
+ if ( data & 0x02 )
+ data2 += 0x15 ;
+
+ XGINew_SetReg3( pVBInfo->P3c9 , data2 ) ;
+ data = data >> 2 ;
+ }
+ }
+
+ if ( time == 256 )
+ {
+ for( i = 16 ; i < 32 ; i++ )
+ {
+ data = table[ i ] ;
+
+ for( k = 0 ; k < 3 ; k++ )
+ XGINew_SetReg3( pVBInfo->P3c9 , data ) ;
+ }
+
+ si = 32 ;
+
+ for( m = 0 ; m < 9 ; m++ )
+ {
+ di = si ;
+ bx = si + 0x04 ;
+ dl = 0 ;
+
+ for( n = 0 ; n < 3 ; n++ )
+ {
+ for( o = 0 ; o < 5 ; o++ )
+ {
+ dh = table[ si ] ;
+ ah = table[ di ] ;
+ al = table[ bx ] ;
+ si++ ;
+ XGI_WriteDAC( dl , ah , al , dh, pVBInfo ) ;
+ }
+
+ si -= 2 ;
+
+ for( o = 0 ; o < 3 ; o++ )
+ {
+ dh = table[ bx ] ;
+ ah = table[ di ] ;
+ al = table[ si ] ;
+ si-- ;
+ XGI_WriteDAC( dl , ah , al , dh, pVBInfo ) ;
+ }
+
+ dl++ ;
+ }
+
+ si += 5 ;
+ }
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_WriteDAC */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_WriteDAC( USHORT dl , USHORT ah , USHORT al , USHORT dh,PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT temp , bh , bl ;
+
+ bh = ah ;
+ bl = al ;
+
+ if ( dl != 0 )
+ {
+ temp = bh ;
+ bh = dh ;
+ dh = temp ;
+ if ( dl == 1 )
+ {
+ temp = bl ;
+ bl = dh ;
+ dh = temp ;
+ }
+ else
+ {
+ temp = bl ;
+ bl = bh ;
+ bh = temp ;
+ }
+ }
+ XGINew_SetReg3( pVBInfo->P3c9 , ( USHORT )dh ) ;
+ XGINew_SetReg3( pVBInfo->P3c9 , ( USHORT )bh ) ;
+ XGINew_SetReg3( pVBInfo->P3c9 , ( USHORT )bl ) ;
+}
+
+#if 0
+/* --------------------------------------------------------------------- */
+/* Function : XGI_ClearBuffer */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_ClearBuffer( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo, PVB_DEVICE_INFO pVBInfo)
+{
+ PVOID VideoMemoryAddress = ( PVOID )HwDeviceExtension->pjVideoMemoryAddress ;
+ ULONG AdapterMemorySize = ( ULONG )HwDeviceExtension->ulVideoMemorySize ;
+ PUSHORT pBuffer ;
+#ifndef LINUX_XF86
+ int i ;
+#endif
+
+ if ( pVBInfo->ModeType >= ModeEGA )
+ {
+ if ( ModeNo > 0x13 )
+ {
+ AdapterMemorySize = 0x40000 ; /* clear 256k */
+ /* GetDRAMSize( HwDeviceExtension ) ; */
+ XGI_SetMemory( VideoMemoryAddress , AdapterMemorySize , 0 ) ;
+ }
+ else
+ {
+/*
+ pBuffer = VideoMemoryAddress ;
+ for( i = 0 ; i < 0x4000 ; i++ )
+ pBuffer[ i ] = 0x0000 ;
+*/
+ }
+ }
+ else
+ {
+ pBuffer = VideoMemoryAddress ;
+ if ( pVBInfo->ModeType < ModeCGA )
+ {
+/*
+ for ( i = 0 ; i < 0x4000 ; i++ )
+ pBuffer[ i ] = 0x0720 ;
+*/
+ }
+ else
+ XGI_SetMemory( VideoMemoryAddress , 0x8000 , 0 ) ;
+ }
+}
+
+#endif
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetLCDAGroup */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetLCDAGroup( USHORT ModeNo , USHORT ModeIdIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT RefreshRateTableIndex ;
+ /* USHORT temp ; */
+
+ /* pVBInfo->SelectCRT2Rate = 0 ; */
+
+ pVBInfo->SetFlag |= ProgrammingCRT2 ;
+ RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, pVBInfo ) ;
+ XGI_GetLVDSResInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
+ XGI_GetLVDSData( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo);
+ XGI_ModCRT1Regs( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ;
+ XGI_SetLVDSRegs( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+ XGI_SetCRT2ECLK( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetLVDSResInfo */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetLVDSResInfo( USHORT ModeNo , USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT resindex , xres , yres , modeflag ;
+
+ if ( ModeNo <= 0x13 )
+ {
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ; /* si+St_ResInfo */
+ }
+ else
+ {
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ; /* si+Ext_ResInfo */
+ }
+
+
+ /* if ( ModeNo > 0x13 ) */
+ /* modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; */
+ /* else */
+ /* modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; */
+
+ if ( ModeNo <= 0x13 )
+ {
+ resindex = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ; /* si+St_ResInfo */
+ }
+ else
+ {
+ resindex = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ; /* si+Ext_ResInfo */
+ }
+
+ /* resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ; */
+
+ if ( ModeNo <= 0x13 )
+ {
+ xres = pVBInfo->StResInfo[ resindex ].HTotal ;
+ yres = pVBInfo->StResInfo[ resindex ].VTotal ;
+ }
+ else
+ {
+ xres = pVBInfo->ModeResInfo[ resindex ].HTotal ;
+ yres = pVBInfo->ModeResInfo[ resindex ].VTotal ;
+ }
+ if ( ModeNo > 0x13 )
+ {
+ if ( modeflag & HalfDCLK )
+ xres = xres << 1 ;
+
+ if ( modeflag & DoubleScanMode )
+ yres = yres << 1 ;
+ }
+ /* if ( modeflag & Charx8Dot ) */
+ /* { */
+
+ if ( xres == 720 )
+ xres = 640 ;
+
+ /* } */
+ pVBInfo->VGAHDE = xres ;
+ pVBInfo->HDE = xres ;
+ pVBInfo->VGAVDE = yres ;
+ pVBInfo->VDE = yres ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetLVDSData */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetLVDSData( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT tempbx ;
+ XGI330_LVDSDataStruct *LCDPtr = NULL ;
+ XGI330_CHTVDataStruct *TVPtr = NULL ;
+
+ tempbx = 2 ;
+
+ if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+ {
+ LCDPtr = ( XGI330_LVDSDataStruct * )XGI_GetLcdPtr( tempbx, ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo) ;
+ pVBInfo->VGAHT = LCDPtr->VGAHT ;
+ pVBInfo->VGAVT = LCDPtr->VGAVT ;
+ pVBInfo->HT = LCDPtr->LCDHT ;
+ pVBInfo->VT = LCDPtr->LCDVT ;
+ }
+ if ( pVBInfo->IF_DEF_CH7017 == 1 )
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToTV )
+ {
+ TVPtr = ( XGI330_CHTVDataStruct * )XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+ pVBInfo->VGAHT = TVPtr->VGAHT ;
+ pVBInfo->VGAVT = TVPtr->VGAVT ;
+ pVBInfo->HT = TVPtr->LCDHT ;
+ pVBInfo->VT = TVPtr->LCDVT ;
+ }
+ }
+
+ if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+ {
+ if ( !( pVBInfo->LCDInfo & ( SetLCDtoNonExpanding | EnableScalingLCD ) ) )
+ {
+ if ( ( pVBInfo->LCDResInfo == Panel1024x768 ) || ( pVBInfo->LCDResInfo == Panel1024x768x75 ) )
+ {
+ pVBInfo->HDE = 1024 ;
+ pVBInfo->VDE = 768 ;
+ }
+ else if ( ( pVBInfo->LCDResInfo == Panel1280x1024 ) || ( pVBInfo->LCDResInfo == Panel1280x1024x75 ) )
+ {
+ pVBInfo->HDE = 1280 ;
+ pVBInfo->VDE = 1024 ;
+ }
+ else if ( pVBInfo->LCDResInfo == Panel1400x1050 )
+ {
+ pVBInfo->HDE = 1400 ;
+ pVBInfo->VDE = 1050 ;
+ }
+ else
+ {
+ pVBInfo->HDE = 1600 ;
+ pVBInfo->VDE = 1200 ;
+ }
+ }
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_ModCRT1Regs */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_ModCRT1Regs( USHORT ModeNo , USHORT ModeIdIndex ,
+ USHORT RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo )
+{
+ UCHAR index ;
+ USHORT tempbx , i ;
+ XGI_LVDSCRT1HDataStruct *LCDPtr = NULL ;
+ XGI_LVDSCRT1VDataStruct *LCDPtr1 =NULL ;
+ /* XGI330_CHTVDataStruct *TVPtr = NULL ; */
+ XGI_CH7007TV_TimingHStruct *CH7007TV_TimingHPtr = NULL;
+ XGI_CH7007TV_TimingVStruct *CH7007TV_TimingVPtr = NULL;
+
+ if( ModeNo <= 0x13 )
+ index = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ;
+ else
+ index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+
+ index= index & IndexMask ;
+
+ if ( ( pVBInfo->IF_DEF_ScaleLCD == 0 ) || ( ( pVBInfo->IF_DEF_ScaleLCD == 1 ) && ( !( pVBInfo->LCDInfo & EnableScalingLCD ) ) ) )
+ {
+ tempbx = 0 ;
+
+ if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+ {
+ LCDPtr = ( XGI_LVDSCRT1HDataStruct * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+
+ for( i = 0 ; i < 8 ; i++ )
+ pVBInfo->TimingH[ 0 ].data[ i ] = LCDPtr[ 0 ].Reg[ i ] ;
+ }
+
+ if ( pVBInfo->IF_DEF_CH7007 == 1 )
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToTV )
+ {
+ CH7007TV_TimingHPtr = ( XGI_CH7007TV_TimingHStruct *)XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+
+ for( i = 0 ; i < 8 ; i++ )
+ pVBInfo->TimingH[ 0 ].data[ i ] = CH7007TV_TimingHPtr[ 0 ].data[ i ] ;
+ }
+ }
+
+ /* if ( pVBInfo->IF_DEF_CH7017 == 1 )
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToTV )
+ TVPtr = ( XGI330_CHTVDataStruct *)XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+ } */
+
+ XGI_SetCRT1Timing_H(pVBInfo,HwDeviceExtension) ;
+
+ if ( pVBInfo->IF_DEF_CH7007 == 1 )
+ {
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , CH7007TV_TimingHPtr[ 0 ].data[ 8 ] ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2F , CH7007TV_TimingHPtr[ 0 ].data[ 9 ] ) ;
+ }
+
+ tempbx = 1 ;
+
+ if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+ {
+ LCDPtr1 = ( XGI_LVDSCRT1VDataStruct * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+ for( i = 0 ; i < 7 ; i++ )
+ pVBInfo->TimingV[ 0 ].data[ i ] = LCDPtr1[ 0 ].Reg[ i ] ;
+ }
+
+ if ( pVBInfo->IF_DEF_CH7007 == 1 )
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToTV )
+ {
+ CH7007TV_TimingVPtr = ( XGI_CH7007TV_TimingVStruct *)XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+
+ for( i = 0 ; i < 7 ; i++ )
+ pVBInfo->TimingV[ 0 ].data[ i ] = CH7007TV_TimingVPtr[ 0 ].data[ i ] ;
+ }
+ }
+ /* if ( pVBInfo->IF_DEF_CH7017 == 1 )
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToTV )
+ TVPtr = ( XGI330_CHTVDataStruct *)XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+ } */
+
+ XGI_SetCRT1Timing_V( ModeIdIndex , ModeNo , pVBInfo) ;
+
+ if ( pVBInfo->IF_DEF_CH7007 == 1 )
+ {
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x33 , ~0x01 , CH7007TV_TimingVPtr[ 0 ].data[ 7 ]&0x01 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , CH7007TV_TimingVPtr[ 0 ].data[8 ] ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x3F , CH7007TV_TimingVPtr[ 0 ].data[9 ] ) ;
+
+ }
+ }
+}
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetLVDSRegs */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetLVDSRegs( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT tempbx , tempax , tempcx , tempdx , push1 , push2 , modeflag ;
+ unsigned long temp , temp1 , temp2 , temp3 , push3 ;
+ XGI330_LCDDataDesStruct *LCDPtr = NULL ;
+ XGI330_LCDDataDesStruct2 *LCDPtr1 = NULL ;
+
+ if ( ModeNo > 0x13 )
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+ else
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+
+ if ( !( pVBInfo->SetFlag & Win9xDOSMode ) )
+ {
+ if ( ( pVBInfo->IF_DEF_CH7017 == 0 ) || ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) )
+ {
+ if ( pVBInfo->IF_DEF_OEMUtil == 1 )
+ {
+ tempbx = 8 ;
+ LCDPtr = ( XGI330_LCDDataDesStruct * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+ }
+
+ if ( ( pVBInfo->IF_DEF_OEMUtil == 0 ) || ( LCDPtr == 0 ) )
+ {
+ tempbx = 3 ;
+ if ( pVBInfo->LCDInfo & EnableScalingLCD )
+ LCDPtr1 = ( XGI330_LCDDataDesStruct2 * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+ else
+ LCDPtr = ( XGI330_LCDDataDesStruct * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+ }
+
+ XGI_GetLCDSync( &tempax , &tempbx ,pVBInfo) ;
+ push1 = tempbx ;
+ push2 = tempax ;
+
+ /* GetLCDResInfo */
+ if ( ( pVBInfo->LCDResInfo == Panel1024x768 ) || ( pVBInfo->LCDResInfo == Panel1024x768x75 ) )
+ {
+ tempax = 1024 ;
+ tempbx = 768 ;
+ }
+ else if ( ( pVBInfo->LCDResInfo == Panel1280x1024 ) || ( pVBInfo->LCDResInfo == Panel1280x1024x75 ) )
+ {
+ tempax = 1280 ;
+ tempbx = 1024 ;
+ }
+ else if ( pVBInfo->LCDResInfo == Panel1400x1050 )
+ {
+ tempax = 1400 ;
+ tempbx = 1050 ;
+ }
+ else
+ {
+ tempax = 1600 ;
+ tempbx = 1200 ;
+ }
+
+ if ( pVBInfo->LCDInfo & SetLCDtoNonExpanding )
+ {
+ pVBInfo->HDE=tempax;
+ pVBInfo->VDE=tempbx;
+ pVBInfo->VGAHDE=tempax;
+ pVBInfo->VGAVDE=tempbx;
+ }
+
+ if ( ( pVBInfo->IF_DEF_ScaleLCD == 1 ) && ( pVBInfo->LCDInfo & EnableScalingLCD ) )
+ {
+ tempax=pVBInfo->HDE;
+ tempbx=pVBInfo->VDE;
+ }
+
+ tempax = pVBInfo->HT ;
+
+ if ( pVBInfo->LCDInfo & EnableScalingLCD )
+ tempbx = LCDPtr1->LCDHDES ;
+ else
+ tempbx = LCDPtr->LCDHDES ;
+
+ tempcx = pVBInfo->HDE ;
+ tempbx = tempbx & 0x0fff ;
+ tempcx += tempbx ;
+
+ if ( tempcx >= tempax )
+ tempcx -= tempax ;
+
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x1A , tempbx & 0x07 ) ;
+
+ tempcx = tempcx >> 3 ;
+ tempbx = tempbx >> 3 ;
+
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x16 , ( USHORT )( tempbx & 0xff ) ) ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x17 , ( USHORT )( tempcx & 0xff ) ) ;
+
+ tempax = pVBInfo->HT ;
+
+ if ( pVBInfo->LCDInfo & EnableScalingLCD )
+ tempbx = LCDPtr1->LCDHRS ;
+ else
+ tempbx = LCDPtr->LCDHRS ;
+
+ tempcx = push2 ;
+
+ if ( pVBInfo->LCDInfo & EnableScalingLCD )
+ tempcx = LCDPtr1->LCDHSync ;
+
+ tempcx += tempbx ;
+
+ if ( tempcx >= tempax )
+ tempcx -= tempax ;
+
+ tempax = tempbx & 0x07 ;
+ tempax = tempax >> 5 ;
+ tempcx = tempcx >> 3 ;
+ tempbx = tempbx >> 3 ;
+
+ tempcx &= 0x1f ;
+ tempax |= tempcx ;
+
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x15 , tempax ) ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x14 , ( USHORT )( tempbx & 0xff ) ) ;
+
+ tempax = pVBInfo->VT ;
+ if ( pVBInfo->LCDInfo & EnableScalingLCD )
+ tempbx = LCDPtr1->LCDVDES ;
+ else
+ tempbx = LCDPtr->LCDVDES ;
+ tempcx = pVBInfo->VDE ;
+
+ tempbx = tempbx & 0x0fff ;
+ tempcx += tempbx ;
+ if ( tempcx >= tempax )
+ tempcx -= tempax ;
+
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x1b , ( USHORT )( tempbx & 0xff ) ) ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x1c , ( USHORT )( tempcx & 0xff ) ) ;
+
+ tempbx = ( tempbx >> 8 ) & 0x07 ;
+ tempcx = ( tempcx >> 8 ) & 0x07 ;
+
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x1d , ( USHORT )( ( tempcx << 3 ) | tempbx ) ) ;
+
+ tempax = pVBInfo->VT ;
+ if ( pVBInfo->LCDInfo & EnableScalingLCD )
+ tempbx = LCDPtr1->LCDVRS ;
+ else
+ tempbx = LCDPtr->LCDVRS ;
+
+ /* tempbx = tempbx >> 4 ; */
+ tempcx = push1 ;
+
+ if ( pVBInfo->LCDInfo & EnableScalingLCD )
+ tempcx = LCDPtr1->LCDVSync ;
+
+ tempcx += tempbx ;
+ if ( tempcx >= tempax )
+ tempcx -= tempax ;
+
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x18 , ( USHORT )( tempbx & 0xff ) ) ;
+ XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x19 , ~0x0f , ( USHORT )( tempcx & 0x0f ) ) ;
+
+ tempax = ( ( tempbx >> 8 ) & 0x07 ) << 3 ;
+
+ tempbx = pVBInfo->VGAVDE ;
+ if ( tempbx != pVBInfo->VDE )
+ tempax |= 0x40 ;
+
+ if ( pVBInfo->LCDInfo & EnableLVDSDDA )
+ tempax |= 0x40 ;
+
+ XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x1a , 0x07 , tempax ) ;
+
+ tempcx = pVBInfo->VGAVT ;
+ tempbx = pVBInfo->VDE ;
+ tempax = pVBInfo->VGAVDE ;
+ tempcx -= tempax ;
+
+ temp = tempax ; /* 0430 ylshieh */
+ temp1 = ( temp << 18 ) / tempbx ;
+
+ tempdx = ( USHORT )( ( temp << 18 ) % tempbx ) ;
+
+ if ( tempdx != 0 )
+ temp1 += 1 ;
+
+ temp2 = temp1 ;
+ push3 = temp2 ;
+
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x37 , ( USHORT )( temp2 & 0xff ) ) ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x36 , ( USHORT )( ( temp2 >> 8 ) & 0xff ) ) ;
+
+ tempbx = ( USHORT )( temp2 >> 16 ) ;
+ tempax = tempbx & 0x03 ;
+
+ tempbx = pVBInfo->VGAVDE ;
+ if ( tempbx == pVBInfo->VDE )
+ tempax |= 0x04 ;
+
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x35 , tempax ) ;
+
+ if ( pVBInfo->VBType & VB_XGI301C )
+ {
+ temp2 = push3 ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x3c , ( USHORT )( temp2 & 0xff ) ) ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x3b , ( USHORT )( ( temp2 >> 8 ) & 0xff ) ) ;
+ tempbx = ( USHORT )( temp2 >> 16 ) ;
+ XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x3a , ~0xc0 , ( USHORT )( ( tempbx & 0xff ) << 6 ) ) ;
+
+ tempcx = pVBInfo->VGAVDE ;
+ if ( tempcx == pVBInfo->VDE )
+ XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x30 , ~0x0c , 0x00 ) ;
+ else
+ XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x30 , ~0x0c , 0x08 ) ;
+ }
+
+ tempcx = pVBInfo->VGAHDE ;
+ tempbx = pVBInfo->HDE ;
+
+ temp1 = tempcx << 16 ;
+
+ tempax = ( USHORT )( temp1 / tempbx ) ;
+
+ if ( ( tempbx & 0xffff ) == ( tempcx & 0xffff ) )
+ tempax = 65535 ;
+
+ temp3 = tempax ;
+ temp1 = pVBInfo->VGAHDE << 16 ;
+
+ temp1 /= temp3 ;
+ temp3 = temp3 << 16 ;
+ temp1 -= 1 ;
+
+ temp3 = ( temp3 & 0xffff0000 ) + ( temp1 & 0xffff ) ;
+
+ tempax = ( USHORT )( temp3 & 0xff ) ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x1f , tempax ) ;
+
+ temp1 = pVBInfo->VGAVDE << 18 ;
+ temp1 = temp1 / push3 ;
+ tempbx = ( USHORT )( temp1 & 0xffff ) ;
+
+ if ( pVBInfo->LCDResInfo == Panel1024x768 )
+ tempbx -= 1 ;
+
+ tempax = ( ( tempbx >> 8 ) & 0xff ) << 3 ;
+ tempax |= ( USHORT )( ( temp3 >> 8 ) & 0x07 ) ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x20 , ( USHORT )( tempax & 0xff ) ) ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x21 , ( USHORT )( tempbx & 0xff ) ) ;
+
+ temp3 = temp3 >> 16 ;
+
+ if ( modeflag & HalfDCLK )
+ temp3 = temp3 >> 1 ;
+
+ XGINew_SetReg1(pVBInfo->Part1Port , 0x22 , ( USHORT )( ( temp3 >> 8 ) & 0xff ) ) ;
+ XGINew_SetReg1(pVBInfo->Part1Port , 0x23 , ( USHORT )( temp3 & 0xff ) ) ;
+ }
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT2ECLK */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT2ECLK( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ UCHAR di_0 , di_1 , tempal ;
+ int i ;
+
+ tempal = XGI_GetVCLKPtr( RefreshRateTableIndex , ModeNo , ModeIdIndex, pVBInfo ) ;
+ XGI_GetVCLKLen( tempal , &di_0 , &di_1, pVBInfo ) ;
+ XGI_GetLCDVCLKPtr( &di_0 , &di_1, pVBInfo ) ;
+
+ for( i = 0 ; i < 4 ; i++ )
+ {
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x31 , ~0x30 , ( USHORT )( 0x10 * i ) ) ;
+ if ( pVBInfo->IF_DEF_CH7007 == 1 )
+ {
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2b , di_0 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2c , di_1 ) ;
+ }
+ else if ( ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) ) && ( !( pVBInfo->VBInfo & SetInSlaveMode ) ) )
+ {
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2e , di_0 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2f , di_1 ) ;
+ }
+ else
+ {
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2b , di_0 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2c , di_1 ) ;
+ }
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_UpdateModeInfo */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_UpdateModeInfo( PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT tempcl ,
+ tempch ,
+ temp ,
+ tempbl ,
+ tempax ;
+
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ tempcl = 0 ;
+ tempch = 0 ;
+ temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x01 ) ;
+
+ if ( !( temp & 0x20 ) )
+ {
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x17 ) ;
+ if ( temp & 0x80 )
+ {
+ if ( ( HwDeviceExtension->jChipType >= XG20 ) || ( HwDeviceExtension->jChipType >= XG40 ) )
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x53 ) ;
+ else
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x63 ) ;
+
+ if ( !( temp & 0x40 ) )
+ tempcl |= ActiveCRT1 ;
+ }
+ }
+
+ temp = XGINew_GetReg1( pVBInfo->Part1Port , 0x2e ) ;
+ temp &= 0x0f ;
+
+ if ( !( temp == 0x08 ) )
+ {
+ tempax = XGINew_GetReg1( pVBInfo->Part1Port , 0x13 ) ; /* Check ChannelA by Part1_13 [2003/10/03] */
+ if ( tempax & 0x04 )
+ tempcl = tempcl | ActiveLCD ;
+
+ temp &= 0x05 ;
+
+ if ( !( tempcl & ActiveLCD ) )
+ if ( temp == 0x01 )
+ tempcl |= ActiveCRT2 ;
+
+ if ( temp == 0x04 )
+ tempcl |= ActiveLCD ;
+
+ if ( temp == 0x05 )
+ {
+ temp = XGINew_GetReg1( pVBInfo->Part2Port , 0x00 ) ;
+
+ if( !( temp & 0x08 ) )
+ tempch |= ActiveAVideo ;
+
+ if ( !( temp & 0x04 ) )
+ tempch |= ActiveSVideo ;
+
+ if ( temp & 0x02 )
+ tempch |= ActiveSCART ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+ {
+ if ( temp & 0x01 )
+ tempch |= ActiveHiTV ;
+ }
+
+ if ( pVBInfo->VBInfo & SetCRT2ToYPbPr )
+ {
+ temp = XGINew_GetReg1( pVBInfo->Part2Port , 0x4d ) ;
+
+ if ( temp & 0x10 )
+ tempch |= ActiveYPbPr ;
+ }
+
+ if ( tempch != 0 )
+ tempcl |= ActiveTV ;
+ }
+ }
+
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x3d ) ;
+ if ( tempcl & ActiveLCD )
+ {
+ if ( ( pVBInfo->SetFlag & ReserveTVOption ) )
+ {
+ if ( temp & ActiveTV )
+ tempcl |= ActiveTV ;
+ }
+ }
+ temp = tempcl ;
+ tempbl = ~ModeSwitchStatus ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x3d , tempbl , temp ) ;
+
+ if ( !( pVBInfo->SetFlag & ReserveTVOption ) )
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x3e , tempch ) ;
+ }
+ else
+ {
+ return ;
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetVGAType */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetVGAType( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+{
+ /*
+ if ( HwDeviceExtension->jChipType >= XG20 )
+ {
+ pVBInfo->Set_VGAType = XG20;
+ }
+ else if ( HwDeviceExtension->jChipType >= XG40 )
+ {
+ pVBInfo->Set_VGAType = VGA_XGI340 ;
+ }
+ */
+ pVBInfo->Set_VGAType = HwDeviceExtension->jChipType;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetVBType */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetVBType(PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT flag , tempbx , tempah ;
+
+ if ( pVBInfo->IF_DEF_CH7007 == 1 )
+ {
+ pVBInfo->VBType = VB_CH7007 ;
+ return;
+ }
+ if ( pVBInfo->IF_DEF_LVDS == 0 )
+ {
+ tempbx = VB_XGI302B ;
+ flag = XGINew_GetReg1( pVBInfo->Part4Port , 0x00 ) ;
+ if ( flag != 0x02 )
+ {
+ tempbx = VB_XGI301 ;
+ flag = XGINew_GetReg1( pVBInfo->Part4Port , 0x01 ) ;
+ if ( flag >= 0xB0 )
+ {
+ tempbx = VB_XGI301B ;
+ if ( flag >= 0xC0 )
+ {
+ tempbx = VB_XGI301C ;
+ if ( flag >= 0xD0 )
+ {
+ tempbx = VB_XGI301LV ;
+ if ( flag >= 0xE0 )
+ {
+ tempbx = VB_XGI302LV ;
+ tempah = XGINew_GetReg1( pVBInfo->Part4Port , 0x39 ) ;
+ if ( tempah != 0xFF )
+ tempbx = VB_XGI301C ;
+ }
+ }
+ }
+
+ if ( tempbx & ( VB_XGI301B | VB_XGI302B ) )
+ {
+ flag = XGINew_GetReg1( pVBInfo->Part4Port , 0x23 ) ;
+
+ if ( !( flag & 0x02 ) )
+ tempbx = tempbx | VB_NoLCD ;
+ }
+ }
+ }
+ pVBInfo->VBType = tempbx ;
+ }
+/*
+ else if ( pVBInfo->IF_DEF_CH7017 == 1 )
+ pVBInfo->VBType = VB_CH7017 ;
+ else //LVDS
+ pVBInfo->VBType = VB_LVDS_NS ;
+*/
+
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetVBInfo */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetVBInfo( USHORT ModeNo , USHORT ModeIdIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT tempax ,
+ push ,
+ tempbx ,
+ temp ,
+ modeflag ;
+
+ if ( ModeNo <= 0x13 )
+ {
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+ }
+ else
+ {
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+ }
+
+ pVBInfo->SetFlag = 0 ;
+ pVBInfo->ModeType = modeflag & ModeInfoFlag ;
+ tempbx = 0 ;
+
+ if ( pVBInfo->VBType & 0xFFFF )
+ {
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x30 ) ; /* Check Display Device */
+ tempbx = tempbx | temp ;
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x31 ) ;
+ push = temp ;
+ push = push << 8 ;
+ tempax = temp << 8 ;
+ tempbx = tempbx | tempax ;
+ temp = ( SetCRT2ToDualEdge | SetCRT2ToYPbPr | SetCRT2ToLCDA | SetInSlaveMode | DisableCRT2Display ) ;
+ temp = 0xFFFF ^ temp ;
+ tempbx &= temp ;
+
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ;
+
+ if ( pVBInfo->IF_DEF_LCDA == 1 )
+ {
+
+ if ( ( pVBInfo->Set_VGAType >= XG20 ) || ( pVBInfo->Set_VGAType >= XG40 ))
+ {
+ if ( pVBInfo->IF_DEF_LVDS == 0 )
+ {
+ /* if ( ( pVBInfo->VBType & VB_XGI302B ) || ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) || ( pVBInfo->VBType & VB_XGI301C ) ) */
+ if ( pVBInfo->VBType & ( VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ if ( temp & EnableDualEdge )
+ {
+ tempbx |= SetCRT2ToDualEdge ;
+
+ if ( temp & SetToLCDA )
+ tempbx |= SetCRT2ToLCDA ;
+ }
+ }
+ }
+ else if ( pVBInfo->IF_DEF_CH7017 == 1 )
+ {
+ if ( pVBInfo->VBType & VB_CH7017 )
+ {
+ if ( temp & EnableDualEdge )
+ {
+ tempbx |= SetCRT2ToDualEdge ;
+
+ if ( temp & SetToLCDA )
+ tempbx |= SetCRT2ToLCDA ;
+ }
+ }
+ }
+ }
+ }
+
+ if ( pVBInfo->IF_DEF_YPbPr == 1 )
+ {
+ if ( ( ( pVBInfo->IF_DEF_LVDS == 0 ) && ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) || ( pVBInfo->VBType & VB_XGI301C ) ) )
+ || ( ( pVBInfo->IF_DEF_CH7017 == 1 ) && ( pVBInfo->VBType&VB_CH7017 ) ) || ( (pVBInfo->IF_DEF_CH7007 == 1) && (pVBInfo->VBType&VB_CH7007) ) ) /* [Billy] 07/05/04 */
+ {
+ if ( temp & SetYPbPr ) /* temp = CR38 */
+ {
+ if ( pVBInfo->IF_DEF_HiVision == 1 )
+ {
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x35 ) ; /* shampoo add for new scratch */
+ temp &= YPbPrMode ;
+ tempbx |= SetCRT2ToHiVisionTV ;
+
+ if ( temp != YPbPrMode1080i ) {
+ tempbx &= ( ~SetCRT2ToHiVisionTV ) ;
+ tempbx |= SetCRT2ToYPbPr ; }
+ }
+
+ /* tempbx |= SetCRT2ToYPbPr ; */
+ }
+ }
+ }
+
+ tempax = push ; /* restore CR31 */
+
+ if ( pVBInfo->IF_DEF_LVDS == 0 )
+ {
+ if ( pVBInfo->IF_DEF_YPbPr == 1 )
+ {
+ if ( pVBInfo->IF_DEF_HiVision == 1 )
+ temp = 0x09FC ;
+ else
+ temp = 0x097C ;
+ }
+ else
+ {
+ if ( pVBInfo->IF_DEF_HiVision == 1 )
+ temp = 0x01FC ;
+ else
+ temp = 0x017C ;
+ }
+ }
+ else /* 3nd party chip */
+ {
+ if ( pVBInfo->IF_DEF_CH7017 == 1 )
+ temp = ( SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA ) ;
+ else if ( pVBInfo->IF_DEF_CH7007 == 1 ) /* [Billy] 07/05/03 */
+ {
+ temp = SetCRT2ToTV ;
+ }
+ else
+ temp = SetCRT2ToLCD ;
+ }
+
+ if ( !( tempbx & temp ) )
+ {
+ tempax |= DisableCRT2Display ;
+ tempbx = 0 ;
+ }
+
+ if ( pVBInfo->IF_DEF_LCDA == 1 ) /* Select Display Device */
+ {
+ if ( !( pVBInfo->VBType & VB_NoLCD ) )
+ {
+ if ( tempbx & SetCRT2ToLCDA )
+ {
+ if ( tempbx & SetSimuScanMode )
+ tempbx &= ( ~( SetCRT2ToLCD | SetCRT2ToRAMDAC | SwitchToCRT2 ) ) ;
+ else
+ tempbx &= ( ~( SetCRT2ToLCD | SetCRT2ToRAMDAC | SetCRT2ToTV | SwitchToCRT2 ) ) ;
+ }
+ }
+ }
+
+ /* shampoo add */
+ if ( !( tempbx & ( SwitchToCRT2 | SetSimuScanMode ) ) ) /* for driver abnormal */
+ {
+ if ( pVBInfo->IF_DEF_CRT2Monitor == 1 )
+ {
+ if ( tempbx & SetCRT2ToRAMDAC )
+ {
+ tempbx &= ( 0xFF00 | SetCRT2ToRAMDAC | SwitchToCRT2 | SetSimuScanMode ) ;
+ tempbx &= ( 0x00FF | ( ~SetCRT2ToYPbPr ) ) ;
+ }
+ }
+ else
+ tempbx &= ( ~( SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV ) ) ;
+ }
+
+ if ( !( pVBInfo->VBType & VB_NoLCD ) )
+ {
+ if ( tempbx & SetCRT2ToLCD )
+ {
+ tempbx &= ( 0xFF00 | SetCRT2ToLCD | SwitchToCRT2 | SetSimuScanMode ) ;
+ tempbx &= ( 0x00FF | ( ~SetCRT2ToYPbPr ) ) ;
+ }
+ }
+
+ if ( tempbx & SetCRT2ToSCART )
+ {
+ tempbx &= ( 0xFF00 | SetCRT2ToSCART | SwitchToCRT2 | SetSimuScanMode ) ;
+ tempbx &= ( 0x00FF | ( ~SetCRT2ToYPbPr ) ) ;
+ }
+
+ if ( pVBInfo->IF_DEF_YPbPr == 1 )
+ {
+ if ( tempbx & SetCRT2ToYPbPr )
+ tempbx &= ( 0xFF00 | SwitchToCRT2 | SetSimuScanMode ) ;
+ }
+
+ if ( pVBInfo->IF_DEF_HiVision == 1 )
+ {
+ if ( tempbx & SetCRT2ToHiVisionTV )
+ tempbx &= ( 0xFF00 | SetCRT2ToHiVisionTV | SwitchToCRT2 | SetSimuScanMode ) ;
+ }
+
+ if ( tempax & DisableCRT2Display ) /* Set Display Device Info */
+ {
+ if ( !( tempbx & ( SwitchToCRT2 | SetSimuScanMode ) ) )
+ tempbx = DisableCRT2Display ;
+ }
+
+ if ( !( tempbx & DisableCRT2Display ) )
+ {
+ if ( ( !( tempbx & DriverMode ) ) || ( !( modeflag & CRT2Mode ) ) )
+ {
+ if ( pVBInfo->IF_DEF_LCDA == 1 )
+ {
+ if ( !( tempbx & SetCRT2ToLCDA ) )
+ tempbx |= ( SetInSlaveMode | SetSimuScanMode ) ;
+ }
+
+ if ( pVBInfo->IF_DEF_VideoCapture == 1 )
+ {
+ if ( ( ( HwDeviceExtension->jChipType == XG40 ) && ( pVBInfo->Set_VGAType == XG40 ) )
+ || ( ( HwDeviceExtension->jChipType == XG41 ) && ( pVBInfo->Set_VGAType == XG41 ) )
+ || ( ( HwDeviceExtension->jChipType == XG42 ) && ( pVBInfo->Set_VGAType == XG42 ) )
+ || ( ( HwDeviceExtension->jChipType == XG45 ) && ( pVBInfo->Set_VGAType == XG45 ) ) )
+ {
+ if ( ModeNo <= 13 )
+ {
+ if ( !( tempbx & SetCRT2ToRAMDAC ) ) /*CRT2 not need to support*/
+ {
+ tempbx &= ( 0x00FF | ( ~SetInSlaveMode ) ) ;
+ pVBInfo->SetFlag |= EnableVCMode ;
+ }
+ }
+ }
+ }
+ }
+
+ /*LCD+TV can't support in slave mode (Force LCDA+TV->LCDB)*/
+ if ( ( tempbx & SetInSlaveMode ) && ( tempbx & SetCRT2ToLCDA ) )
+ {
+ tempbx ^= ( SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToDualEdge ) ;
+ pVBInfo->SetFlag |= ReserveTVOption ;
+ }
+ }
+ }
+
+ pVBInfo->VBInfo = tempbx ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetTVInfo */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetTVInfo( USHORT ModeNo , USHORT ModeIdIndex ,PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT temp ,
+ tempbx = 0 ,
+ resinfo = 0 ,
+ modeflag ,
+ index1 ;
+
+ tempbx = 0 ;
+ resinfo = 0 ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToTV )
+ {
+ if ( ModeNo <= 0x13 )
+ {
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ModeFlag */
+ resinfo = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ; /* si+St_ResInfo */
+ }
+ else
+ {
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+ resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ; /* si+Ext_ResInfo */
+ }
+
+ if ( pVBInfo->VBInfo & SetCRT2ToTV )
+ {
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x35 ) ;
+ tempbx = temp;
+ if ( tempbx & SetPALTV )
+ {
+ tempbx &= ( SetCHTVOverScan | SetPALMTV | SetPALNTV | SetPALTV ) ;
+ if ( tempbx & SetPALMTV )
+ tempbx &= ~SetPALTV ; /* set to NTSC if PAL-M */
+ }
+ else
+ tempbx &= ( SetCHTVOverScan | SetNTSCJ | SetPALTV ) ;
+/*
+ if ( pVBInfo->IF_DEF_LVDS == 0 )
+ {
+ index1 = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ; //PAL-M/PAL-N Info
+ temp2 = ( index1 & 0xC0 ) >> 5 ; //00:PAL, 01:PAL-M, 10:PAL-N
+ tempbx |= temp2 ;
+ if ( temp2 & 0x02 ) //PAL-M
+ tempbx &= ( ~SetPALTV ) ;
+ }
+*/
+ }
+
+ if ( pVBInfo->IF_DEF_CH7017 == 1 )
+ {
+ tempbx = XGINew_GetReg1( pVBInfo->P3d4 , 0x35 ) ;
+
+ if ( tempbx & TVOverScan )
+ tempbx |= SetCHTVOverScan ;
+ }
+
+ if ( pVBInfo->IF_DEF_CH7007 == 1 ) /* [Billy] 07/05/04 */
+ {
+ tempbx = XGINew_GetReg1( pVBInfo->P3d4 , 0x35 ) ;
+
+ if ( tempbx & TVOverScan )
+ {
+ tempbx |= SetCHTVOverScan ;
+ }
+ }
+
+
+ if ( pVBInfo->IF_DEF_LVDS == 0 )
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToSCART )
+ tempbx |= SetPALTV ;
+ }
+
+ if ( pVBInfo->IF_DEF_YPbPr == 1 )
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToYPbPr )
+ {
+ index1 = XGINew_GetReg1( pVBInfo->P3d4 , 0x35 ) ;
+ index1 &= YPbPrMode ;
+
+ if ( index1 == YPbPrMode525i )
+ tempbx |= SetYPbPrMode525i ;
+
+ if ( index1 == YPbPrMode525p )
+ tempbx = tempbx | SetYPbPrMode525p;
+ if ( index1 == YPbPrMode750p)
+ tempbx = tempbx | SetYPbPrMode750p;
+ }
+ }
+
+ if ( pVBInfo->IF_DEF_HiVision == 1 )
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+ {
+ tempbx = tempbx | SetYPbPrMode1080i | SetPALTV ;
+ }
+ }
+
+ if ( pVBInfo->IF_DEF_LVDS == 0 )
+ { /* shampoo */
+ if ( ( pVBInfo->VBInfo & SetInSlaveMode ) && ( !( pVBInfo->VBInfo & SetNotSimuMode ) ) )
+ tempbx |= TVSimuMode ;
+
+ if ( !( tempbx & SetPALTV ) && ( modeflag > 13 ) && ( resinfo == 8 ) ) /* NTSC 1024x768, */
+ tempbx |= NTSC1024x768 ;
+
+ tempbx |= RPLLDIV2XO ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+ {
+ if ( pVBInfo->VBInfo & SetInSlaveMode )
+ tempbx &=( ~RPLLDIV2XO ) ;
+ }
+ else
+ {
+ if ( tempbx & ( SetYPbPrMode525p | SetYPbPrMode750p ) )
+ tempbx &= ( ~RPLLDIV2XO ) ;
+ else if ( !( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) )
+ {
+ if ( tempbx & TVSimuMode )
+ tempbx &= ( ~RPLLDIV2XO ) ;
+ }
+ }
+ }
+ }
+ pVBInfo->TVInfo = tempbx ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetLCDInfo */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_GetLCDInfo( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT temp ,
+ tempax ,
+ tempbx ,
+ modeflag ,
+ resinfo = 0 ,
+ LCDIdIndex ;
+
+ pVBInfo->LCDResInfo = 0 ;
+ pVBInfo->LCDTypeInfo = 0 ;
+ pVBInfo->LCDInfo = 0 ;
+
+ if ( ModeNo <= 0x13 )
+ {
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ModeFlag // */
+ }
+ else
+ {
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+ resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ; /* si+Ext_ResInfo// */
+ }
+
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x36 ) ; /* Get LCD Res.Info */
+ tempbx = temp & 0x0F ;
+
+ if ( tempbx == 0 )
+ tempbx = Panel1024x768 ; /* default */
+
+ /* LCD75 [2003/8/22] Vicent */
+ if ( ( tempbx == Panel1024x768 ) || ( tempbx == Panel1280x1024 ) )
+ {
+ if ( pVBInfo->VBInfo & DriverMode )
+ {
+ tempax = XGINew_GetReg1( pVBInfo->P3d4 , 0x33 ) ;
+ if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+ tempax &= 0x0F ;
+ else
+ tempax = tempax >> 4 ;
+
+ if ( ( resinfo == 6 ) || ( resinfo == 9 ) )
+ {
+ if ( tempax >= 3 )
+ tempbx |= PanelRef75Hz ;
+ }
+ else if ( ( resinfo == 7 ) || ( resinfo == 8 ) )
+ {
+ if ( tempax >= 4 )
+ tempbx |= PanelRef75Hz ;
+ }
+ }
+ }
+
+ pVBInfo->LCDResInfo = tempbx ;
+
+ /* End of LCD75 */
+
+ if( pVBInfo->IF_DEF_OEMUtil == 1 )
+ {
+ pVBInfo->LCDTypeInfo = ( temp & 0xf0 ) >> 4 ;
+ }
+
+ if ( !( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) )
+ {
+ return 0;
+ }
+
+ tempbx = 0 ;
+
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x37 ) ;
+
+ temp &= ( ScalingLCD | LCDNonExpanding | LCDSyncBit | SetPWDEnable ) ;
+
+ if ( ( pVBInfo->IF_DEF_ScaleLCD == 1 ) && ( temp & LCDNonExpanding ) )
+ temp &= ~EnableScalingLCD ;
+
+ tempbx |= temp ;
+
+ LCDIdIndex = XGI_GetLCDCapPtr1(pVBInfo) ;
+
+ tempax = pVBInfo->LCDCapList[ LCDIdIndex ].LCD_Capability ;
+
+ if ( pVBInfo->IF_DEF_LVDS == 0 ) /* shampoo */
+ {
+ if ( ( ( pVBInfo->VBType & VB_XGI302LV ) || ( pVBInfo->VBType & VB_XGI301C ) ) && ( tempax & LCDDualLink ) )
+ {
+ tempbx |= SetLCDDualLink ;
+ }
+ }
+
+ if ( pVBInfo->IF_DEF_CH7017 == 1 )
+ {
+ if ( tempax & LCDDualLink )
+ {
+ tempbx |= SetLCDDualLink ;
+ }
+ }
+
+ if ( pVBInfo->IF_DEF_LVDS == 0 )
+ {
+ if ( ( pVBInfo->LCDResInfo == Panel1400x1050 ) && ( pVBInfo->VBInfo & SetCRT2ToLCD ) && ( ModeNo > 0x13 ) && ( resinfo == 9 ) && ( !( tempbx & EnableScalingLCD ) ) )
+ tempbx |= SetLCDtoNonExpanding ; /* set to center in 1280x1024 LCDB for Panel1400x1050 */
+ }
+
+/*
+ if ( tempax & LCDBToA )
+ {
+ tempbx |= SetLCDBToA ;
+ }
+*/
+
+ if ( pVBInfo->IF_DEF_ExpLink == 1 )
+ {
+ if ( modeflag & HalfDCLK )
+ {
+ /* if ( !( pVBInfo->LCDInfo&LCDNonExpanding ) ) */
+ if ( !( tempbx & SetLCDtoNonExpanding ) )
+ {
+ tempbx |= EnableLVDSDDA ;
+ }
+ else
+ {
+ if ( ModeNo > 0x13 )
+ {
+ if ( pVBInfo->LCDResInfo == Panel1024x768 )
+ {
+ if ( resinfo == 4 )
+ { /* 512x384 */
+ tempbx |= EnableLVDSDDA ;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if ( pVBInfo->VBInfo & SetInSlaveMode )
+ {
+ if ( pVBInfo->VBInfo & SetNotSimuMode )
+ {
+ tempbx |= LCDVESATiming ;
+ }
+ }
+ else
+ {
+ tempbx |= LCDVESATiming ;
+ }
+
+ pVBInfo->LCDInfo = tempbx ;
+
+ if ( pVBInfo->IF_DEF_PWD == 1 )
+ {
+ if ( pVBInfo->LCDInfo & SetPWDEnable )
+ {
+ if ( ( pVBInfo->VBType & VB_XGI302LV ) || ( pVBInfo->VBType & VB_XGI301C ) )
+ {
+ if ( !( tempax & PWDEnable ) )
+ {
+ pVBInfo->LCDInfo &= ~SetPWDEnable ;
+ }
+ }
+ }
+ }
+
+ if ( pVBInfo->IF_DEF_LVDS == 0 )
+ {
+ if ( tempax & ( LockLCDBToA | StLCDBToA ) )
+ {
+ if ( pVBInfo->VBInfo & SetInSlaveMode )
+ {
+ if ( !( tempax & LockLCDBToA ) )
+ {
+ if ( ModeNo <= 0x13 )
+ {
+ pVBInfo->VBInfo &= ~( SetSimuScanMode | SetInSlaveMode | SetCRT2ToLCD ) ;
+ pVBInfo->VBInfo |= SetCRT2ToLCDA | SetCRT2ToDualEdge ;
+ }
+ }
+ }
+ }
+ }
+
+/*
+ if ( pVBInfo->IF_DEF_LVDS == 0 )
+ {
+ if ( tempax & ( LockLCDBToA | StLCDBToA ) )
+ {
+ if ( pVBInfo->VBInfo & SetInSlaveMode )
+ {
+ if ( !( ( !( tempax & LockLCDBToA ) ) && ( ModeNo > 0x13 ) ) )
+ {
+ pVBInfo->VBInfo&=~(SetSimuScanMode|SetInSlaveMode|SetCRT2ToLCD);
+ pVBInfo->VBInfo|=SetCRT2ToLCDA|SetCRT2ToDualEdge;
+ }
+ }
+ }
+ }
+*/
+
+ return( 1 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SearchModeID */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_SearchModeID( USHORT ModeNo , USHORT *ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+{
+
+#ifdef TC
+
+ if ( ModeNo <= 5 )
+ ModeNo |= 1 ;
+
+ if ( ModeNo <= 0x13 )
+ {
+ /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(pVBInfo->SModeIDTable)/sizeof(XGI_StStruct);(*ModeIdIndex)++) */
+ for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
+ {
+ if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == ModeNo )
+ break ;
+ if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == 0xFF )
+ return( FALSE ) ;
+ }
+
+ VGA_INFO = ( PUCHAR )MK_FP( 0 , 0x489 ) ;
+
+ if ( ModeNo == 0x07 )
+ {
+ if ( ( *VGA_INFO & 0x10 ) != 0 )
+ ( *ModeIdIndex )++ ; /* 400 lines */
+ /* else 350 lines */
+ }
+
+ if ( ModeNo <= 3 )
+ {
+ if ( ( *VGA_INFO & 0x80 ) == 0 )
+ {
+ ( *ModeIdIndex )++ ;
+ if ( ( *VGA_INFO & 0x10 ) != 0 )
+ ( *ModeIdIndex )++ ; /* 400 lines */
+ /* else 350 lines */
+ }
+ /* else 200 lines */
+ }
+ }
+ else
+ {
+ /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(pVBInfo->EModeIDTable)/sizeof(XGI_ExtStruct);(*ModeIdIndex)++) */
+ for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
+ {
+ if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == ModeNo )
+ break ;
+ if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == 0xFF )
+ return( FALSE ) ;
+ }
+ }
+
+
+#endif
+
+#ifdef WIN2000
+
+ if ( ModeNo <= 5 )
+ ModeNo |= 1 ;
+ if ( ModeNo <= 0x13 )
+ {
+ /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(pVBInfo->SModeIDTable)/sizeof(XGI_StStruct);(*ModeIdIndex)++) */
+ for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
+ {
+ if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == ModeNo )
+ break ;
+ if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == 0xFF )
+ return( FALSE ) ;
+ }
+
+ if ( ModeNo == 0x07 )
+ ( *ModeIdIndex )++ ; /* 400 lines */
+
+ if ( ModeNo <=3 )
+ ( *ModeIdIndex ) += 2 ; /* 400 lines */
+ /* else 350 lines */
+ }
+ else
+ {
+ /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(pVBInfo->EModeIDTable)/sizeof(XGI_ExtStruct);(*ModeIdIndex)++) */
+ for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
+ {
+ if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == ModeNo )
+ break ;
+ if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == 0xFF )
+ return( FALSE ) ;
+ }
+ }
+
+#endif
+
+#ifdef LINUX /* chiawen for linux solution */
+
+ if ( ModeNo <= 5 )
+ ModeNo |= 1 ;
+ if ( ModeNo <= 0x13 )
+ {
+ /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(pVBInfo->SModeIDTable)/sizeof(XGI_StStruct);(*ModeIdIndex)++) */
+ for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
+ {
+ if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == ModeNo )
+ break ;
+ if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == 0xFF )
+ return( FALSE ) ;
+ }
+
+ if ( ModeNo == 0x07 )
+ ( *ModeIdIndex )++ ; /* 400 lines */
+
+ if ( ModeNo <= 3 )
+ ( *ModeIdIndex ) += 2 ; /* 400 lines */
+ /* else 350 lines */
+ }
+ else
+ {
+ /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(pVBInfo->EModeIDTable)/sizeof(XGI_ExtStruct);(*ModeIdIndex)++) */
+ for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
+ {
+ if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == ModeNo )
+ break ;
+ if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == 0xFF )
+ return( FALSE ) ;
+ }
+ }
+
+#endif
+
+ return( TRUE ) ;
+}
+
+
+
+
+/* win2000 MM adapter not support standard mode! */
+
+/* --------------------------------------------------------------------- */
+/* Function : */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGINew_CheckMemorySize(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT memorysize ,
+ modeflag ,
+ temp ,
+ temp1 ,
+ tmp ;
+
+/* if ( ( HwDeviceExtension->jChipType == XGI_650 ) ||
+ ( HwDeviceExtension->jChipType == XGI_650M ) )
+ {
+ return( TRUE ) ;
+ } */
+
+ if ( ModeNo <= 0x13 )
+ {
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+ }
+ else {
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+ }
+
+ /* ModeType = modeflag&ModeInfoFlag ; // Get mode type */
+
+ memorysize = modeflag & MemoryInfoFlag ;
+ memorysize = memorysize > MemorySizeShift ;
+ memorysize++ ; /* Get memory size */
+
+ temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) ; /* Get DRAM Size */
+ tmp = temp ;
+
+ if ( HwDeviceExtension->jChipType == XG40 )
+ {
+ temp = 1 << ( ( temp & 0x0F0 ) >> 4 ) ; /* memory size per channel SR14[7:4] */
+ if ( ( tmp & 0x0c ) == 0x0C ) /* Qual channels */
+ {
+ temp <<= 2 ;
+ }
+ else if ( ( tmp & 0x0c ) == 0x08 ) /* Dual channels */
+ {
+ temp <<= 1 ;
+ }
+ }
+ else if ( HwDeviceExtension->jChipType == XG42 )
+ {
+ temp = 1 << ( ( temp & 0x0F0 ) >> 4 ) ; /* memory size per channel SR14[7:4] */
+ if ( ( tmp & 0x04 ) == 0x04 ) /* Dual channels */
+ {
+ temp <<= 1 ;
+ }
+ }
+ else if ( HwDeviceExtension->jChipType == XG45 )
+ {
+ temp = 1 << ( ( temp & 0x0F0 ) >> 4 ) ; /* memory size per channel SR14[7:4] */
+ if ( ( tmp & 0x0c ) == 0x0C ) /* Qual channels */
+ {
+ temp <<= 2 ;
+ }
+ else if ( ( tmp & 0x0c ) == 0x08 ) /* triple channels */
+ {
+ temp1 = temp ;
+ temp <<= 1 ;
+ temp += temp1 ;
+ }
+ else if ( ( tmp & 0x0c ) == 0x04 ) /* Dual channels */
+ {
+ temp <<= 1 ;
+ }
+ }
+ if ( temp < memorysize )
+ return( FALSE ) ;
+ else
+ return( TRUE ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_IsLowResolution */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+/*void XGINew_IsLowResolution( USHORT ModeNo , USHORT ModeIdIndex, BOOLEAN XGINew_CheckMemorySize(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT data ;
+ USHORT ModeFlag ;
+
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x0F ) ;
+ data &= 0x7F ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x0F , data ) ;
+
+ if ( ModeNo > 0x13 )
+ {
+ ModeFlag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+ if ( ( ModeFlag & HalfDCLK ) && ( ModeFlag & DoubleScanMode ) )
+ {
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x0F ) ;
+ data |= 0x80 ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x0F , data ) ;
+ data = XGINew_GetReg1( pVBInfo->P3c4 , 0x01 ) ;
+ data &= 0xF7 ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , data ) ;
+ }
+ }
+}
+
+*/
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_DisplayOn */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_DisplayOn( PXGI_HW_DEVICE_INFO pXGIHWDE , PVB_DEVICE_INFO pVBInfo )
+{
+
+ XGINew_SetRegANDOR(pVBInfo->P3c4,0x01,0xDF,0x00);
+ if ( pXGIHWDE->jChipType == XG21 )
+ {
+ if ( pVBInfo->IF_DEF_LVDS == 1 )
+ {
+ if (!(XGI_XG21GetPSCValue( pVBInfo )&0x1))
+ {
+ XGI_XG21BLSignalVDD( 0x01 , 0x01, pVBInfo ) ; /* LVDS VDD on */
+ XGI_XG21SetPanelDelay( 2,pVBInfo ) ;
+ }
+ if (!(XGI_XG21GetPSCValue( pVBInfo )&0x20))
+ {
+ XGI_XG21BLSignalVDD( 0x20 , 0x20, pVBInfo ) ; /* LVDS signal on */
+ }
+ XGI_XG21SetPanelDelay( 3,pVBInfo ) ;
+ XGI_XG21BLSignalVDD( 0x02 , 0x02, pVBInfo ) ; /* LVDS backlight on */
+ }
+ else
+ {
+ XGI_XG21BLSignalVDD( 0x20 , 0x20, pVBInfo ) ; /* DVO/DVI signal on */
+ }
+
+ }
+
+ if (pVBInfo->IF_DEF_CH7007 == 1) /* [Billy] 07/05/23 For CH7007 */
+ {
+#ifdef WIN2000
+ if ( IsCH7007TVMode( pVBInfo ) )
+ {
+ TurnOnCH7007(pXGIHWDE->pDevice) ; /* 07/05/28 */
+ }
+#endif
+
+ }
+
+
+ if ( pXGIHWDE->jChipType == XG27 )
+ {
+ if ( pVBInfo->IF_DEF_LVDS == 1 )
+ {
+ if (!(XGI_XG27GetPSCValue( pVBInfo )&0x1))
+ {
+ XGI_XG27BLSignalVDD( 0x01 , 0x01, pVBInfo ) ; /* LVDS VDD on */
+ XGI_XG21SetPanelDelay( 2,pVBInfo ) ;
+ }
+ if (!(XGI_XG27GetPSCValue( pVBInfo )&0x20))
+ {
+ XGI_XG27BLSignalVDD( 0x20 , 0x20, pVBInfo ) ; /* LVDS signal on */
+ }
+ XGI_XG21SetPanelDelay( 3,pVBInfo ) ;
+ XGI_XG27BLSignalVDD( 0x02 , 0x02, pVBInfo ) ; /* LVDS backlight on */
+ }
+ else
+ {
+ XGI_XG27BLSignalVDD( 0x20 , 0x20, pVBInfo ) ; /* DVO/DVI signal on */
+ }
+
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_DisplayOff */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_DisplayOff( PXGI_HW_DEVICE_INFO pXGIHWDE , PVB_DEVICE_INFO pVBInfo )
+{
+
+ if ( pXGIHWDE->jChipType == XG21 )
+ {
+ if ( pVBInfo->IF_DEF_LVDS == 1 )
+ {
+ XGI_XG21BLSignalVDD( 0x02 , 0x00, pVBInfo ) ; /* LVDS backlight off */
+ XGI_XG21SetPanelDelay( 3,pVBInfo ) ;
+ }
+ else
+ {
+ XGI_XG21BLSignalVDD( 0x20 , 0x00, pVBInfo ) ; /* DVO/DVI signal off */
+ }
+ }
+
+ if (pVBInfo->IF_DEF_CH7007 == 1) /*[Billy] 07/05/23 For CH7007 */
+ {
+ /* if( IsCH7007TVMode( pVBInfo ) == 0 ) */
+ {
+#ifdef WIN2000
+ TurnOffCH7007(pXGIHWDE->pDevice) ; /* 07/05/28 */
+#endif
+ }
+ }
+
+
+ if ( pXGIHWDE->jChipType == XG27 )
+ {
+ if ((XGI_XG27GetPSCValue( pVBInfo )&0x2))
+ {
+ XGI_XG27BLSignalVDD( 0x02 , 0x00, pVBInfo ) ; /* LVDS backlight off */
+ XGI_XG21SetPanelDelay( 3,pVBInfo ) ;
+ }
+
+ if ( pVBInfo->IF_DEF_LVDS == 0 )
+ {
+ XGI_XG27BLSignalVDD( 0x20 , 0x00, pVBInfo ) ; /* DVO/DVI signal off */
+ }
+ }
+
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x01 , 0xDF , 0x20 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_WaitDisply */
+/* Input : */
+/* Output : */
+/* Description : chiawen for sensecrt1 */
+/* --------------------------------------------------------------------- */
+void XGI_WaitDisply( PVB_DEVICE_INFO pVBInfo )
+{
+ while( ( XGINew_GetReg2( pVBInfo->P3da ) & 0x01 ) )
+ break ;
+
+ while( !( XGINew_GetReg2( pVBInfo->P3da ) & 0x01 ) )
+ break ;
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SenseCRT1 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+
+void XGI_SenseCRT1( PVB_DEVICE_INFO pVBInfo )
+{
+ UCHAR CRTCData[ 17 ] = { 0x5F , 0x4F , 0x50 , 0x82 , 0x55 , 0x81 ,
+ 0x0B , 0x3E , 0xE9 , 0x0B , 0xDF , 0xE7 ,
+ 0x04 , 0x00 , 0x00 , 0x05 , 0x00 } ;
+
+ UCHAR SR01 = 0 , SR1F = 0 , SR07 = 0 , SR06 = 0 ;
+
+ UCHAR CR17 , CR63 , SR31 ;
+ USHORT temp ;
+ UCHAR DAC_TEST_PARMS[ 3 ] = { 0x0F , 0x0F , 0x0F } ;
+
+ int i ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x05 , 0x86 ) ;
+
+ /* [2004/05/06] Vicent to fix XG42 single LCD sense to CRT+LCD */
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x57 , 0x4A ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x53 , ( UCHAR )( XGINew_GetReg1( pVBInfo->P3d4 , 0x53 ) | 0x02 ) ) ;
+
+ SR31 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x31 ) ;
+ CR63 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x63 ) ;
+ SR01 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x01 ) ;
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , ( UCHAR )( SR01 & 0xDF ) ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x63 , ( UCHAR )( CR63 & 0xBF ) ) ;
+
+ CR17 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x17 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x17 , ( UCHAR )( CR17 | 0x80 ) ) ;
+
+ SR1F = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x1F ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x1F , ( UCHAR )( SR1F | 0x04 ) ) ;
+
+ SR07 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x07 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x07 , ( UCHAR )( SR07 & 0xFB ) ) ;
+ SR06 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x06 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x06 , ( UCHAR )( SR06 & 0xC3 ) ) ;
+
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , 0x00 ) ;
+
+ for( i = 0 ; i < 8 ; i++ )
+ XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )i , CRTCData[ i ] ) ;
+
+ for( i = 8 ; i < 11 ; i++ )
+ XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 8 ) , CRTCData[ i ] ) ;
+
+ for( i = 11 ; i < 13 ; i++ )
+ XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 4 ) , CRTCData[ i ] ) ;
+
+ for( i = 13 ; i < 16 ; i++ )
+ XGINew_SetReg1( pVBInfo->P3c4 , ( USHORT )( i - 3 ) , CRTCData[ i ] ) ;
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x0E , ( UCHAR )( CRTCData[ 16 ] & 0xE0 ) ) ;
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , 0x00 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , 0x1B ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , 0xE1 ) ;
+
+ XGINew_SetReg3( pVBInfo->P3c8 , 0x00 ) ;
+
+ for( i = 0 ; i < 256 ; i++ )
+ {
+ XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , ( UCHAR )DAC_TEST_PARMS[ 0 ] ) ;
+ XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , ( UCHAR )DAC_TEST_PARMS[ 1 ] ) ;
+ XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , ( UCHAR )DAC_TEST_PARMS[ 2 ] ) ;
+ }
+
+ XGI_VBLongWait( pVBInfo ) ;
+ XGI_VBLongWait( pVBInfo ) ;
+ XGI_VBLongWait( pVBInfo ) ;
+
+ XGINew_LCD_Wait_Time( 0x01 , pVBInfo ) ;
+
+ XGI_WaitDisply( pVBInfo ) ;
+ temp = XGINew_GetReg2( pVBInfo->P3c2 ) ;
+
+ if( temp & 0x10 )
+ {
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , 0xDF , 0x20 ) ;
+ }
+ else
+ {
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , 0xDF , 0x00 ) ;
+ }
+
+ /* alan, avoid display something, set BLACK DAC if not restore DAC */
+ XGINew_SetReg3( pVBInfo->P3c8 , 0x00 ) ;
+
+ for( i = 0 ; i < 256 ; i++ )
+ {
+ XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , 0 ) ;
+ XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , 0 ) ;
+ XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , 0 ) ;
+ }
+
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , SR01 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x63 , CR63 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , SR31 ) ;
+
+ /* [2004/05/11] Vicent */
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x53 , ( UCHAR )( XGINew_GetReg1( pVBInfo->P3d4 , 0x53 ) & 0xFD ) ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x1F , ( UCHAR ) SR1F ) ;
+}
+
+
+
+
+
+#ifdef TC
+/* --------------------------------------------------------------------- */
+/* Function : INT1AReturnCode */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+int INT1AReturnCode( union REGS regs )
+{
+ if ( regs.x.cflag )
+ {
+ /* printf( "Error to find pci device!\n" ) ; */
+ return( 1 ) ;
+ }
+
+ switch(regs.h.ah)
+ {
+ case 0: return 0;
+ break ;
+ case 0x81:
+ printf( "Function not support\n" ) ;
+ break ;
+ case 0x83:
+ printf( "bad vendor id\n" ) ;
+ break ;
+ case 0x86:
+ printf( "device not found\n" ) ;
+ break ;
+ case 0x87:
+ printf( "bad register number\n" ) ;
+ break ;
+ case 0x88:
+ printf( "set failed\n" ) ;
+ break ;
+ case 0x89:
+ printf( "buffer too small" ) ;
+ break ;
+ default:
+ break ;
+ }
+ return( 1 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : FindPCIIOBase */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+unsigned FindPCIIOBase( unsigned index , unsigned deviceid )
+{
+ union REGS regs ;
+
+ regs.h.ah = 0xb1 ; /* PCI_FUNCTION_ID */
+ regs.h.al = 0x02 ; /* FIND_PCI_DEVICE */
+ regs.x.cx = deviceid ;
+ regs.x.dx = 0x1039 ;
+ regs.x.si = index ; /* find n-th device */
+
+ int86( 0x1A , ®s , ®s ) ;
+
+ if ( INT1AReturnCode( regs ) != 0 )
+ return( 0 ) ;
+
+ /* regs.h.bh bus number */
+ /* regs.h.bl device number */
+ regs.h.ah = 0xb1 ; /* PCI_FUNCTION_ID */
+ regs.h.al = 0x09 ; /* READ_CONFIG_WORD */
+ regs.x.cx = deviceid ;
+ regs.x.dx = 0x1039 ;
+ regs.x.di = 0x18 ; /* register number */
+ int86( 0x1A , ®s , ®s ) ;
+
+ if ( INT1AReturnCode( regs ) != 0 )
+ return( 0 ) ;
+
+ return( regs.x.cx ) ;
+}
+
+#endif
+
+
+
+#ifdef TC
+/* --------------------------------------------------------------------- */
+/* Function : main */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void main(int argc, char *argv[])
+{
+ XGI_HW_DEVICE_INFO HwDeviceExtension ;
+ USHORT temp ;
+ USHORT ModeNo ;
+
+ /* HwDeviceExtension.pjVirtualRomBase =(PUCHAR) MK_FP(0xC000,0); */
+ /* HwDeviceExtension.pjVideoMemoryAddress = (PUCHAR)MK_FP(0xA000,0); */
+
+
+ HwDeviceExtension.pjIOAddress = ( FindPCIIOBase( 0 ,0x6300 ) & 0xFF80 ) + 0x30 ;
+ HwDeviceExtension.jChipType = XGI_340 ;
+
+
+
+ /* HwDeviceExtension.pjIOAddress = ( FindPCIIOBase( 0 , 0x5315 ) & 0xFF80 ) + 0x30 ; */
+
+ HwDeviceExtension.pjIOAddress = ( FindPCIIOBase( 0 , 0x330 ) & 0xFF80 ) + 0x30 ;
+ HwDeviceExtension.jChipType = XGI_340 ;
+
+
+ HwDeviceExtension.ujVBChipID = VB_CHIP_301 ;
+ StrCpy(HwDeviceExtension.szVBIOSVer , "0.84" ) ;
+ HwDeviceExtension.bSkipDramSizing = FALSE ;
+ HwDeviceExtension.ulVideoMemorySize = 0 ;
+
+ if ( argc == 2 )
+ {
+ ModeNo = atoi( argv[ 1 ] ) ;
+ }
+ else
+ {
+ ModeNo = 0x2e ;
+ /* ModeNo = 0x37 ; 1024x768x 4bpp */
+ /* ModeNo = 0x38 ; 1024x768x 8bpp */
+ /* ModeNo = 0x4A ; 1024x768x 16bpp */
+ /* ModeNo = 0x47 ; 800x600x 16bpp */
+ }
+
+ /* XGIInitNew( &HwDeviceExtension ) ; */
+ XGISetModeNew( &HwDeviceExtension , ModeNo ) ;
+}
+#endif
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_WaitDisplay */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_WaitDisplay( PVB_DEVICE_INFO pVBInfo )
+{
+ while( !( XGINew_GetReg2( pVBInfo->P3da ) & 0x01 ) ) ;
+
+ while( XGINew_GetReg2( pVBInfo->P3da ) & 0x01 ) ;
+}
+
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT2Group301 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_SetCRT2Group301( USHORT ModeNo , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT tempbx ,
+ ModeIdIndex ,
+ RefreshRateTableIndex ;
+
+ tempbx=pVBInfo->VBInfo ;
+ pVBInfo->SetFlag |= ProgrammingCRT2 ;
+ XGI_SearchModeID( ModeNo , &ModeIdIndex, pVBInfo ) ;
+ pVBInfo->SelectCRT2Rate = 4 ;
+ RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, pVBInfo ) ;
+ XGI_SaveCRT2Info( ModeNo, pVBInfo ) ;
+ XGI_GetCRT2ResInfo( ModeNo , ModeIdIndex, pVBInfo) ;
+ XGI_GetCRT2Data( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+ XGI_PreSetGroup1( ModeNo , ModeIdIndex , HwDeviceExtension , RefreshRateTableIndex, pVBInfo ) ;
+ XGI_SetGroup1( ModeNo , ModeIdIndex , HwDeviceExtension , RefreshRateTableIndex, pVBInfo ) ;
+ XGI_SetLockRegs( ModeNo , ModeIdIndex , HwDeviceExtension , RefreshRateTableIndex, pVBInfo ) ;
+ XGI_SetGroup2( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ;
+ XGI_SetLCDRegs(ModeNo , ModeIdIndex , HwDeviceExtension , RefreshRateTableIndex, pVBInfo ) ;
+ XGI_SetTap4Regs(pVBInfo) ;
+ XGI_SetGroup3(ModeNo, ModeIdIndex, pVBInfo);
+ XGI_SetGroup4( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ;
+ XGI_SetCRT2VCLK( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+ XGI_SetGroup5( ModeNo , ModeIdIndex, pVBInfo) ;
+ XGI_AutoThreshold( pVBInfo) ;
+ return 1 ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_AutoThreshold */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_AutoThreshold( PVB_DEVICE_INFO pVBInfo )
+{
+ if ( !( pVBInfo->SetFlag & Win9xDOSMode ) )
+ XGINew_SetRegOR( pVBInfo->Part1Port , 0x01 , 0x40 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SaveCRT2Info */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SaveCRT2Info( USHORT ModeNo , PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT temp1 ,
+ temp2 ;
+
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x34 , ModeNo ) ; /* reserve CR34 for CRT1 Mode No */
+ temp1 = ( pVBInfo->VBInfo&SetInSlaveMode ) >> 8 ;
+ temp2 = ~( SetInSlaveMode >> 8 ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x31 , temp2 , temp1 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetCRT2ResInfo */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetCRT2ResInfo( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT xres ,
+ yres ,
+ modeflag ,
+ resindex ;
+
+ resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo) ;
+ if ( ModeNo <= 0x13 )
+ {
+ xres = pVBInfo->StResInfo[ resindex ].HTotal ;
+ yres = pVBInfo->StResInfo[ resindex ].VTotal ;
+ /* modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; si+St_ResInfo */
+ }
+ else
+ {
+ xres = pVBInfo->ModeResInfo[ resindex ].HTotal ; /* xres->ax */
+ yres = pVBInfo->ModeResInfo[ resindex ].VTotal ; /* yres->bx */
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex].Ext_ModeFlag ; /* si+St_ModeFlag */
+
+/* if ( pVBInfo->IF_DEF_FSTN )
+ {
+ xres *= 2 ;
+ yres *= 2 ;
+ }
+ else
+ {
+*/
+ if ( modeflag & HalfDCLK )
+ xres *= 2;
+
+ if ( modeflag & DoubleScanMode )
+ yres *= 2 ;
+/* } */
+ }
+
+ if ( pVBInfo->VBInfo & SetCRT2ToLCD )
+ {
+ if ( pVBInfo->IF_DEF_LVDS == 0 )
+ {
+ if ( pVBInfo->LCDResInfo == Panel1600x1200 )
+ {
+ if ( !( pVBInfo->LCDInfo & LCDVESATiming ) )
+ {
+ if ( yres == 1024 )
+ yres = 1056 ;
+ }
+ }
+
+ if ( pVBInfo->LCDResInfo == Panel1280x1024 )
+ {
+ if ( yres == 400 )
+ yres = 405 ;
+ else if ( yres == 350 )
+ yres = 360 ;
+
+ if ( pVBInfo->LCDInfo & LCDVESATiming )
+ {
+ if ( yres == 360 )
+ yres = 375 ;
+ }
+ }
+
+ if ( pVBInfo->LCDResInfo == Panel1024x768 )
+ {
+ if ( !( pVBInfo->LCDInfo & LCDVESATiming ) )
+ {
+ if ( !( pVBInfo->LCDInfo & LCDNonExpanding ) )
+ {
+ if ( yres == 350 )
+ yres = 357 ;
+ else if ( yres == 400 )
+ yres = 420 ;
+ else if ( yres == 480 )
+ yres = 525 ;
+ }
+ }
+ }
+ }
+
+ if ( xres == 720 )
+ xres = 640 ;
+ }
+
+ pVBInfo->VGAHDE = xres ;
+ pVBInfo->HDE = xres ;
+ pVBInfo->VGAVDE = yres ;
+ pVBInfo->VDE = yres ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_IsLCDDualLink */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_IsLCDDualLink( PVB_DEVICE_INFO pVBInfo )
+{
+
+ if ( ( ( ( pVBInfo->VBInfo & SetCRT2ToLCD ) | SetCRT2ToLCDA ) ) && ( pVBInfo->LCDInfo & SetLCDDualLink ) ) /* shampoo0129 */
+ return ( 1 ) ;
+
+ return( 0 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetCRT2Data */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetCRT2Data( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT tempax = 0,
+ tempbx ,
+ modeflag ,
+ resinfo ;
+
+ XGI_LCDDataStruct *LCDPtr = NULL ;
+ XGI_TVDataStruct *TVPtr = NULL ;
+
+ if ( ModeNo <= 0x13 )
+ {
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ResInfo */
+ resinfo = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ;
+ }
+ else
+ {
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; /* si+Ext_ResInfo */
+ resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;
+ }
+
+ pVBInfo->NewFlickerMode = 0 ;
+ pVBInfo->RVBHRS = 50 ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC )
+ {
+ XGI_GetRAMDAC2DATA( ModeNo , ModeIdIndex , RefreshRateTableIndex,pVBInfo ) ;
+ return ;
+ }
+
+ tempbx = 4 ;
+
+ if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+ {
+ LCDPtr = (XGI_LCDDataStruct* )XGI_GetLcdPtr( tempbx, ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+
+ pVBInfo->RVBHCMAX = LCDPtr->RVBHCMAX ;
+ pVBInfo->RVBHCFACT = LCDPtr->RVBHCFACT ;
+ pVBInfo->VGAHT = LCDPtr->VGAHT ;
+ pVBInfo->VGAVT = LCDPtr->VGAVT ;
+ pVBInfo->HT = LCDPtr->LCDHT ;
+ pVBInfo->VT = LCDPtr->LCDVT ;
+
+ if ( pVBInfo->LCDResInfo == Panel1024x768 )
+ {
+ tempax = 1024 ;
+ tempbx = 768 ;
+
+ if ( !( pVBInfo->LCDInfo & LCDVESATiming ) )
+ {
+ if ( pVBInfo->VGAVDE == 357 )
+ tempbx = 527 ;
+ else if ( pVBInfo->VGAVDE == 420 )
+ tempbx = 620 ;
+ else if ( pVBInfo->VGAVDE == 525 )
+ tempbx = 775 ;
+ else if ( pVBInfo->VGAVDE == 600 )
+ tempbx = 775 ;
+ /* else if(pVBInfo->VGAVDE==350) tempbx=560; */
+ /* else if(pVBInfo->VGAVDE==400) tempbx=640; */
+ else
+ tempbx = 768 ;
+ }
+ else
+ tempbx = 768 ;
+ }
+ else if ( pVBInfo->LCDResInfo == Panel1024x768x75 )
+ {
+ tempax = 1024 ;
+ tempbx = 768 ;
+ }
+ else if ( pVBInfo->LCDResInfo == Panel1280x1024 )
+ {
+ tempax = 1280 ;
+ if ( pVBInfo->VGAVDE == 360 )
+ tempbx = 768 ;
+ else if ( pVBInfo->VGAVDE == 375 )
+ tempbx = 800 ;
+ else if ( pVBInfo->VGAVDE == 405 )
+ tempbx = 864 ;
+ else
+ tempbx = 1024 ;
+ }
+ else if ( pVBInfo->LCDResInfo == Panel1280x1024x75 )
+ {
+ tempax = 1280 ;
+ tempbx = 1024 ;
+ }
+ else if ( pVBInfo->LCDResInfo == Panel1280x960 )
+ {
+ tempax = 1280 ;
+ if ( pVBInfo->VGAVDE == 350 )
+ tempbx = 700 ;
+ else if ( pVBInfo->VGAVDE == 400 )
+ tempbx = 800 ;
+ else if ( pVBInfo->VGAVDE == 1024 )
+ tempbx = 960 ;
+ else
+ tempbx = 960 ;
+ }
+ else if ( pVBInfo->LCDResInfo == Panel1400x1050 )
+ {
+ tempax = 1400 ;
+ tempbx = 1050 ;
+
+ if ( pVBInfo->VGAVDE == 1024 )
+ {
+ tempax = 1280 ;
+ tempbx = 1024 ;
+ }
+ }
+ else if ( pVBInfo->LCDResInfo == Panel1600x1200 )
+ {
+ tempax = 1600 ;
+ tempbx = 1200 ; /* alan 10/14/2003 */
+ if ( !( pVBInfo->LCDInfo & LCDVESATiming ) )
+ {
+ if ( pVBInfo->VGAVDE == 350 )
+ tempbx = 875 ;
+ else if ( pVBInfo->VGAVDE == 400 )
+ tempbx = 1000 ;
+ }
+ }
+
+ if ( pVBInfo->LCDInfo & LCDNonExpanding )
+ {
+ tempax = pVBInfo->VGAHDE ;
+ tempbx = pVBInfo->VGAVDE ;
+ }
+
+ pVBInfo->HDE = tempax ;
+ pVBInfo->VDE = tempbx ;
+ return ;
+ }
+
+ if ( pVBInfo->VBInfo & ( SetCRT2ToTV ) )
+ {
+ tempbx = 4 ;
+ TVPtr = ( XGI_TVDataStruct * )XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+
+ pVBInfo->RVBHCMAX = TVPtr->RVBHCMAX ;
+ pVBInfo->RVBHCFACT = TVPtr->RVBHCFACT ;
+ pVBInfo->VGAHT = TVPtr->VGAHT ;
+ pVBInfo->VGAVT = TVPtr->VGAVT ;
+ pVBInfo->HDE = TVPtr->TVHDE ;
+ pVBInfo->VDE = TVPtr->TVVDE ;
+ pVBInfo->RVBHRS = TVPtr->RVBHRS ;
+ pVBInfo->NewFlickerMode = TVPtr->FlickerMode ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+ {
+ if ( resinfo == 0x08 )
+ pVBInfo->NewFlickerMode = 0x40 ;
+ else if ( resinfo == 0x09 )
+ pVBInfo->NewFlickerMode = 0x40 ;
+ else if ( resinfo == 0x12 )
+ pVBInfo->NewFlickerMode = 0x40 ;
+
+ if ( pVBInfo->VGAVDE == 350 )
+ pVBInfo->TVInfo |= TVSimuMode ;
+
+ tempax = ExtHiTVHT ;
+ tempbx = ExtHiTVVT ;
+
+ if ( pVBInfo->VBInfo & SetInSlaveMode )
+ {
+ if ( pVBInfo->TVInfo & TVSimuMode )
+ {
+ tempax = StHiTVHT ;
+ tempbx = StHiTVVT ;
+
+ if ( !( modeflag & Charx8Dot ) )
+ {
+ tempax = StHiTextTVHT ;
+ tempbx = StHiTextTVVT ;
+ }
+ }
+ }
+ }
+ else if ( pVBInfo->VBInfo & SetCRT2ToYPbPr )
+ {
+ if ( pVBInfo->TVInfo & SetYPbPrMode750p )
+ {
+ tempax = YPbPrTV750pHT ; /* Ext750pTVHT */
+ tempbx = YPbPrTV750pVT ; /* Ext750pTVVT */
+ }
+
+ if ( pVBInfo->TVInfo & SetYPbPrMode525p )
+ {
+ tempax = YPbPrTV525pHT ; /* Ext525pTVHT */
+ tempbx = YPbPrTV525pVT ; /* Ext525pTVVT */
+ }
+ else if ( pVBInfo->TVInfo & SetYPbPrMode525i )
+ {
+ tempax = YPbPrTV525iHT ; /* Ext525iTVHT */
+ tempbx = YPbPrTV525iVT ; /* Ext525iTVVT */
+ if ( pVBInfo->TVInfo & NTSC1024x768 )
+ tempax = NTSC1024x768HT ;
+ }
+ }
+ else
+ {
+ tempax = PALHT ;
+ tempbx = PALVT ;
+ if ( !( pVBInfo->TVInfo & SetPALTV ) )
+ {
+ tempax = NTSCHT ;
+ tempbx = NTSCVT ;
+ if ( pVBInfo->TVInfo & NTSC1024x768 )
+ tempax = NTSC1024x768HT ;
+ }
+ }
+
+ pVBInfo->HT = tempax ;
+ pVBInfo->VT = tempbx ;
+ return ;
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT2VCLK */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT2VCLK( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ UCHAR di_0 ,
+ di_1 ,
+ tempal ;
+
+ tempal = XGI_GetVCLKPtr( RefreshRateTableIndex , ModeNo , ModeIdIndex, pVBInfo ) ;
+ XGI_GetVCLKLen( tempal, &di_0 , &di_1, pVBInfo ) ;
+ XGI_GetLCDVCLKPtr( &di_0 , &di_1, pVBInfo ) ;
+
+ if ( pVBInfo->VBType & VB_XGI301 ) /* shampoo 0129 */
+ { /* 301 */
+ XGINew_SetReg1(pVBInfo->Part4Port , 0x0A , 0x10 ) ;
+ XGINew_SetReg1(pVBInfo->Part4Port , 0x0B , di_1 ) ;
+ XGINew_SetReg1(pVBInfo->Part4Port , 0x0A , di_0 ) ;
+ }
+ else
+ { /* 301b/302b/301lv/302lv */
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x0A , di_0 ) ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x0B , di_1 ) ;
+ }
+
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x00 , 0x12 ) ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC )
+ XGINew_SetRegOR( pVBInfo->Part4Port , 0x12 , 0x28 ) ;
+ else
+ XGINew_SetRegOR( pVBInfo->Part4Port , 0x12 , 0x08 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GETLCDVCLKPtr */
+/* Input : */
+/* Output : al -> VCLK Index */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetLCDVCLKPtr( UCHAR* di_0 , UCHAR *di_1, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT index ;
+
+ if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+ {
+ if ( pVBInfo->IF_DEF_ScaleLCD == 1 )
+ {
+ if ( pVBInfo->LCDInfo & EnableScalingLCD )
+ return ;
+ }
+
+ /* index = XGI_GetLCDCapPtr(pVBInfo) ; */
+ index = XGI_GetLCDCapPtr1( pVBInfo) ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToLCD )
+ { /* LCDB */
+ *di_0 = pVBInfo->LCDCapList[ index ].LCUCHAR_VCLKData1 ;
+ *di_1 = pVBInfo->LCDCapList[ index ].LCUCHAR_VCLKData2 ;
+ }
+ else
+ { /* LCDA */
+ *di_0 = pVBInfo->LCDCapList[ index ].LCDA_VCLKData1 ;
+ *di_1 = pVBInfo->LCDCapList[ index ].LCDA_VCLKData2 ;
+ }
+ }
+ return ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetVCLKPtr */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+UCHAR XGI_GetVCLKPtr(USHORT RefreshRateTableIndex,USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+{
+
+ USHORT index ,
+ modeflag ;
+#ifndef LINUX_XF86
+ USHORT tempbx ;
+#endif
+
+ UCHAR tempal ;
+ UCHAR *CHTVVCLKPtr = NULL ;
+
+ if ( ModeNo <= 0x13 )
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ResInfo */
+ else
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
+
+
+ if ( ( pVBInfo->SetFlag & ProgrammingCRT2 ) && ( !( pVBInfo->LCDInfo & EnableScalingLCD ) ) )
+ { /* {LCDA/LCDB} */
+ index = XGI_GetLCDCapPtr(pVBInfo) ;
+ tempal = pVBInfo->LCDCapList[ index ].LCD_VCLK ;
+
+ if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+ return tempal ;
+
+ /* {TV} */
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV| VB_XGI302LV| VB_XGI301C ) )
+ {
+ if(pVBInfo->VBInfo&SetCRT2ToHiVisionTV)
+ {
+ tempal = HiTVVCLKDIV2;
+ if(!(pVBInfo->TVInfo & RPLLDIV2XO))
+ tempal = HiTVVCLK;
+ if(pVBInfo->TVInfo & TVSimuMode)
+ {
+ tempal = HiTVSimuVCLK;
+ if(!(modeflag & Charx8Dot))
+ tempal = HiTVTextVCLK;
+
+ }
+ return tempal;
+ }
+
+ if ( pVBInfo->TVInfo & SetYPbPrMode750p )
+ {
+ tempal = YPbPr750pVCLK ;
+ return tempal ;
+ }
+
+ if ( pVBInfo->TVInfo & SetYPbPrMode525p )
+ {
+ tempal = YPbPr525pVCLK ;
+ return tempal ;
+ }
+
+ tempal = NTSC1024VCLK ;
+
+ if ( !( pVBInfo->TVInfo & NTSC1024x768 ) )
+ {
+ tempal = TVVCLKDIV2 ;
+ if ( !( pVBInfo->TVInfo & RPLLDIV2XO ) )
+ tempal = TVVCLK ;
+ }
+
+ if ( pVBInfo->VBInfo & SetCRT2ToTV )
+ return tempal ;
+ }
+ /*else
+ if((pVBInfo->IF_DEF_CH7017==1)&&(pVBInfo->VBType&VB_CH7017))
+ {
+ if(ModeNo<=0x13)
+ *tempal = pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+ else
+ *tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+ *tempal = *tempal & 0x1F;
+
+ tempbx = 0;
+ if(pVBInfo->TVInfo & SetPALTV)
+ tempbx = tempbx + 2;
+ if(pVBInfo->TVInfo & SetCHTVOverScan)
+ tempbx++;
+ tempbx = tempbx << 1;
+ } */
+ } /* {End of VB} */
+
+ if((pVBInfo->IF_DEF_CH7007==1)&&(pVBInfo->VBType&VB_CH7007)) /* [Billy] 07/05/08 CH7007 */
+ {
+ /* VideoDebugPrint((0, "XGI_GetVCLKPtr: pVBInfo->IF_DEF_CH7007==1\n")); */
+ if ( (pVBInfo->VBInfo & SetCRT2ToTV) )
+ {
+ if( ModeNo <= 0x13 )
+ {
+ tempal = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ;
+ }
+ else
+ {
+ tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+ }
+
+ tempal = tempal & 0x0F;
+ tempbx = 0;
+
+ if(pVBInfo->TVInfo & SetPALTV)
+ {
+ tempbx = tempbx + 2;
+ }
+ if(pVBInfo->TVInfo & SetCHTVOverScan)
+ {
+ tempbx++;
+ }
+ /** tempbx = tempbx << 1; CH7007 ? **/
+
+/*[Billy]07/05/29 CH7007*/
+ if ( pVBInfo->IF_DEF_CH7007 == 1 )
+ {
+ switch( tempbx )
+ {
+ case 0:
+ CHTVVCLKPtr = XGI7007_CHTVVCLKUNTSC ;
+ break ;
+ case 1:
+ CHTVVCLKPtr = XGI7007_CHTVVCLKONTSC ;
+ break ;
+ case 2:
+ CHTVVCLKPtr = XGI7007_CHTVVCLKUPAL ;
+ break ;
+ case 3:
+ CHTVVCLKPtr = XGI7007_CHTVVCLKOPAL ;
+ break ;
+ default:
+ break ;
+
+ }
+ }
+ /*else
+ {
+ switch( tempbx )
+ {
+ case 0:
+ CHTVVCLKPtr = pVBInfo->CHTVVCLKUNTSC ;
+ break ;
+ case 1:
+ CHTVVCLKPtr = pVBInfo->CHTVVCLKONTSC ;
+ break ;
+ case 2:
+ CHTVVCLKPtr = pVBInfo->CHTVVCLKUPAL ;
+ break ;
+ case 3:
+ CHTVVCLKPtr = pVBInfo->CHTVVCLKOPAL ;
+ break ;
+ default:
+ break ;
+ }
+ }*/
+
+ tempal = CHTVVCLKPtr[ tempal ] ;
+ return tempal ;
+ }
+
+ }
+
+ tempal = ( UCHAR )XGINew_GetReg2( ( pVBInfo->P3ca + 0x02 ) ) ;
+ tempal = tempal >> 2 ;
+ tempal &= 0x03 ;
+
+ if ( ( pVBInfo->LCDInfo & EnableScalingLCD ) && ( modeflag & Charx8Dot ) ) /* for Dot8 Scaling LCD */
+ tempal = tempal ^ tempal ; /* ; set to VCLK25MHz always */
+
+ if ( ModeNo <= 0x13 )
+ return tempal ;
+
+ tempal = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRTVCLK ;
+ return tempal ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetVCLKLen */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetVCLKLen(UCHAR tempal,UCHAR* di_0,UCHAR* di_1, PVB_DEVICE_INFO pVBInfo)
+{
+ if ( pVBInfo->IF_DEF_CH7007 == 1 ) /* [Billy] 2007/05/16 */
+ {
+ /* VideoDebugPrint((0, "XGI_GetVCLKLen: pVBInfo->IF_DEF_CH7007==1\n")); */
+ *di_0 = ( UCHAR )XGI_CH7007VCLKData[ tempal ].SR2B ;
+ *di_1 = ( UCHAR )XGI_CH7007VCLKData[ tempal ].SR2C ;
+ }
+ else if ( pVBInfo->VBType & ( VB_XGI301 | VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ if ( ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) ) && ( pVBInfo->SetFlag & ProgrammingCRT2 ) )
+ {
+ *di_0 = ( UCHAR )XGI_VBVCLKData[ tempal ].SR2B ;
+ *di_1 = XGI_VBVCLKData[ tempal ].SR2C ;
+ }
+ }
+ else
+ {
+ *di_0 = XGI_VCLKData[ tempal ].SR2B ;
+ *di_1 = XGI_VCLKData[ tempal ].SR2C ;
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT2Offset */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT2Offset( USHORT ModeNo ,
+ USHORT ModeIdIndex , USHORT RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT offset ;
+ UCHAR temp ;
+
+ if ( pVBInfo->VBInfo & SetInSlaveMode )
+ {
+ return ;
+ }
+
+ offset = XGI_GetOffset( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ;
+ temp = ( UCHAR )( offset & 0xFF ) ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , temp ) ;
+ temp =( UCHAR)( ( offset & 0xFF00 ) >> 8 ) ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x09 , temp ) ;
+ temp =( UCHAR )( ( ( offset >> 3 ) & 0xFF ) + 1 ) ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x03 , temp ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetOffset */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+USHORT XGI_GetOffset(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT temp ,
+ colordepth ,
+ modeinfo ,
+ index ,
+ infoflag ,
+ ColorDepth[] = { 0x01 , 0x02 , 0x04 } ;
+
+ modeinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeInfo ;
+ if ( ModeNo <= 0x14 )
+ infoflag = 0 ;
+ else
+ infoflag = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ;
+
+
+ index = ( modeinfo >> 8 ) & 0xFF ;
+
+ temp = pVBInfo->ScreenOffset[ index ] ;
+
+ if ( infoflag & InterlaceMode )
+ {
+ temp = temp << 1 ;
+ }
+
+ colordepth = XGI_GetColorDepth( ModeNo , ModeIdIndex, pVBInfo ) ;
+
+ if ( ( ModeNo >= 0x7C ) && ( ModeNo <= 0x7E ) )
+ {
+ temp = ModeNo - 0x7C ;
+ colordepth = ColorDepth[ temp ] ;
+ temp = 0x6B ;
+ if ( infoflag & InterlaceMode )
+ {
+ temp = temp << 1 ;
+ }
+ return( temp * colordepth ) ;
+ }
+ else
+ return( temp * colordepth ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT2FIFO */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT2FIFO( PVB_DEVICE_INFO pVBInfo)
+{
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x01 , 0x3B ) ; /* threshold high ,disable auto threshold */
+ XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x02 , ~( 0x3F ) , 0x04 ) ; /* threshold low default 04h */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_PreSetGroup1 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_PreSetGroup1(USHORT ModeNo , USHORT ModeIdIndex ,PXGI_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT tempcx = 0 ,
+ CRT1Index = 0 ,
+ resinfo = 0 ;
+
+ if ( ModeNo > 0x13 )
+ {
+ CRT1Index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ;
+ CRT1Index &= IndexMask ;
+ resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;
+ }
+
+ XGI_SetCRT2Offset( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ;
+ XGI_SetCRT2FIFO(pVBInfo) ;
+ /* XGI_SetCRT2Sync(ModeNo,RefreshRateTableIndex); */
+
+ for( tempcx = 4 ; tempcx < 7 ; tempcx++ )
+ {
+ XGINew_SetReg1( pVBInfo->Part1Port , tempcx , 0x0 ) ;
+ }
+
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x50 , 0x00 ) ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x02 , 0x44 ) ; /* temp 0206 */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetGroup1 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetGroup1( USHORT ModeNo , USHORT ModeIdIndex ,
+ PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT temp = 0 ,
+ tempax = 0 ,
+ tempbx = 0 ,
+ tempcx = 0 ,
+ pushbx = 0 ,
+ CRT1Index = 0 ,
+ modeflag ,
+ resinfo = 0 ;
+
+ if ( ModeNo > 0x13 )
+ {
+ CRT1Index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ;
+ CRT1Index &= IndexMask ;
+ resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;
+ }
+
+ if ( ModeNo <= 0x13 )
+ {
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+ }
+ else
+ {
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+ }
+
+ /* bainy change table name */
+ if ( modeflag & HalfDCLK )
+ {
+ temp = ( pVBInfo->VGAHT / 2 - 1 ) & 0x0FF ; /* BTVGA2HT 0x08,0x09 */
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , temp ) ;
+ temp = ( ( ( pVBInfo->VGAHT / 2 - 1 ) & 0xFF00 ) >> 8 ) << 4 ;
+ XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x09 , ~0x0F0 , temp ) ;
+ temp = ( pVBInfo->VGAHDE / 2 + 16 ) & 0x0FF ; /* BTVGA2HDEE 0x0A,0x0C */
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x0A , temp ) ;
+ tempcx = ( ( pVBInfo->VGAHT - pVBInfo->VGAHDE ) / 2 ) >> 2 ;
+ pushbx = pVBInfo->VGAHDE / 2 + 16 ;
+ tempcx = tempcx >> 1 ;
+ tempbx = pushbx + tempcx ; /* bx BTVGA@HRS 0x0B,0x0C */
+ tempcx += tempbx ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC )
+ {
+ tempbx = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 4 ] ;
+ tempbx |= ( ( pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 14 ] & 0xC0 ) << 2 ) ;
+ tempbx = ( tempbx - 3 ) << 3 ; /* (VGAHRS-3)*8 */
+ tempcx = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[ 5 ] ;
+ tempcx &= 0x1F ;
+ temp = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 15 ] ;
+ temp = ( temp & 0x04 ) << ( 5 - 2 ) ; /* VGAHRE D[5] */
+ tempcx = ( ( tempcx | temp ) - 3 ) << 3 ; /* (VGAHRE-3)*8 */
+ }
+
+ tempbx += 4 ;
+ tempcx += 4 ;
+
+ if ( tempcx > ( pVBInfo->VGAHT / 2 ) )
+ tempcx = pVBInfo->VGAHT / 2 ;
+
+ temp = tempbx & 0x00FF ;
+
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x0B , temp ) ;
+ }
+ else
+ {
+ temp = ( pVBInfo->VGAHT - 1 ) & 0x0FF ; /* BTVGA2HT 0x08,0x09 */
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , temp ) ;
+ temp = ( ( ( pVBInfo->VGAHT - 1 ) & 0xFF00 ) >> 8 ) << 4 ;
+ XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x09 , ~0x0F0 , temp ) ;
+ temp = ( pVBInfo->VGAHDE + 16 ) & 0x0FF ; /* BTVGA2HDEE 0x0A,0x0C */
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x0A , temp ) ;
+ tempcx = ( pVBInfo->VGAHT - pVBInfo->VGAHDE ) >> 2 ; /* cx */
+ pushbx = pVBInfo->VGAHDE + 16 ;
+ tempcx = tempcx >> 1 ;
+ tempbx = pushbx + tempcx ; /* bx BTVGA@HRS 0x0B,0x0C */
+ tempcx += tempbx ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC )
+ {
+ tempbx = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 3 ] ;
+ tempbx |= ( ( pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 5 ] & 0xC0 ) << 2 ) ;
+ tempbx = ( tempbx - 3 ) << 3 ; /* (VGAHRS-3)*8 */
+ tempcx = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 4 ] ;
+ tempcx &= 0x1F ;
+ temp = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 6 ] ;
+ temp = ( temp & 0x04 ) << ( 5 - 2 ) ; /* VGAHRE D[5] */
+ tempcx = ( ( tempcx | temp ) - 3 ) << 3 ; /* (VGAHRE-3)*8 */
+ tempbx += 16 ;
+ tempcx += 16 ;
+ }
+
+ if ( tempcx > pVBInfo->VGAHT )
+ tempcx = pVBInfo->VGAHT ;
+
+ temp = tempbx & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x0B , temp ) ;
+ }
+
+ tempax = ( tempax & 0x00FF ) | ( tempbx & 0xFF00 ) ;
+ tempbx = pushbx ;
+ tempbx = ( tempbx & 0x00FF ) | ( ( tempbx & 0xFF00 ) << 4 ) ;
+ tempax |= ( tempbx & 0xFF00 ) ;
+ temp = ( tempax & 0xFF00 ) >> 8 ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x0C , temp ) ;
+ temp = tempcx & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x0D , temp ) ;
+ tempcx = ( pVBInfo->VGAVT - 1 ) ;
+ temp = tempcx & 0x00FF ;
+
+ if ( pVBInfo->IF_DEF_CH7005 == 1 )
+ {
+ if ( pVBInfo->VBInfo & 0x0C )
+ {
+ temp-- ;
+ }
+ }
+
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x0E , temp ) ;
+ tempbx = pVBInfo->VGAVDE - 1 ;
+ temp = tempbx & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x0F , temp ) ;
+ temp = ( ( tempbx & 0xFF00 ) << 3 ) >> 8 ;
+ temp |= ( ( tempcx & 0xFF00 ) >> 8 ) ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x12 , temp ) ;
+
+ tempax = pVBInfo->VGAVDE ;
+ tempbx = pVBInfo->VGAVDE ;
+ tempcx = pVBInfo->VGAVT ;
+ tempbx = ( pVBInfo->VGAVT + pVBInfo->VGAVDE ) >> 1 ; /* BTVGA2VRS 0x10,0x11 */
+ tempcx = ( ( pVBInfo->VGAVT - pVBInfo->VGAVDE ) >> 4 ) + tempbx + 1 ; /* BTVGA2VRE 0x11 */
+
+ if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC )
+ {
+ tempbx = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 10 ] ;
+ temp = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 9 ] ;
+
+ if ( temp & 0x04 )
+ tempbx |= 0x0100 ;
+
+ if ( temp & 0x080 )
+ tempbx |= 0x0200 ;
+
+ temp = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 14 ] ;
+
+ if ( temp & 0x08 )
+ tempbx |= 0x0400 ;
+
+ temp = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 11 ] ;
+ tempcx = ( tempcx & 0xFF00 ) | ( temp & 0x00FF ) ;
+ }
+
+ temp = tempbx & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x10 , temp ) ;
+ temp = ( ( tempbx & 0xFF00 ) >> 8 ) << 4 ;
+ temp = ( ( tempcx & 0x000F ) | ( temp ) ) ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x11 , temp ) ;
+ tempax = 0 ;
+
+ if ( modeflag & DoubleScanMode )
+ tempax |= 0x80 ;
+
+ if ( modeflag & HalfDCLK )
+ tempax |= 0x40 ;
+
+ XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2C , ~0x0C0 , tempax ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetLockRegs */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetLockRegs( USHORT ModeNo , USHORT ModeIdIndex ,
+ PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT push1 ,
+ push2 ,
+ tempax ,
+ tempbx = 0 ,
+ tempcx ,
+ temp ,
+ resinfo ,
+ modeflag ,
+ CRT1Index ;
+
+ if ( ModeNo <= 0x13 )
+ {
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ResInfo */
+ resinfo = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ;
+ }
+ else
+ {
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; /* si+Ext_ResInfo */
+ resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;
+ CRT1Index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ;
+ CRT1Index &= IndexMask;
+ }
+
+ if ( !( pVBInfo->VBInfo & SetInSlaveMode ) )
+ {
+ return ;
+ }
+
+ temp = 0xFF ; /* set MAX HT */
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x03 , temp ) ;
+ /* if ( modeflag & Charx8Dot ) tempcx = 0x08 ; */
+ /* else */
+ tempcx=0x08;
+
+ if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ modeflag |= Charx8Dot ;
+
+ tempax = pVBInfo->VGAHDE ; /* 0x04 Horizontal Display End */
+
+ if ( modeflag & HalfDCLK )
+ tempax = tempax >> 1 ;
+
+ tempax = ( tempax / tempcx ) - 1 ;
+ tempbx |= ( ( tempax & 0x00FF ) << 8 ) ;
+ temp = tempax & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x04 , temp ) ;
+
+ temp = ( tempbx & 0xFF00 ) >> 8 ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToTV )
+ {
+ if ( !( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) )
+ temp += 2 ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+ {
+ if ( pVBInfo->VBType & VB_XGI301LV )
+ {
+ if ( pVBInfo->VBExtInfo == VB_YPbPr1080i )
+ {
+ if ( resinfo == 7 )
+ temp -= 2 ;
+ }
+ }
+ else
+ if ( resinfo == 7 )
+ temp -= 2 ;
+ }
+ }
+
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x05 , temp ) ; /* 0x05 Horizontal Display Start */
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x06 , 0x03 ) ; /* 0x06 Horizontal Blank end */
+
+ if ( !( pVBInfo->VBInfo & DisableCRT2Display ) )
+ { /* 030226 bainy */
+ if ( pVBInfo->VBInfo & SetCRT2ToTV )
+ tempax = pVBInfo->VGAHT ;
+ else
+ tempax = XGI_GetVGAHT2( pVBInfo) ;
+ }
+
+ if ( tempax >= pVBInfo->VGAHT )
+ {
+ tempax = pVBInfo->VGAHT ;
+ }
+
+ if ( modeflag & HalfDCLK )
+ {
+ tempax = tempax >> 1 ;
+ }
+
+ tempax = ( tempax / tempcx ) - 5 ;
+ tempcx = tempax ; /* 20030401 0x07 horizontal Retrace Start */
+ if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+ {
+ temp = ( tempbx & 0x00FF ) - 1 ;
+ if ( !( modeflag & HalfDCLK ) )
+ {
+ temp -= 6 ;
+ if ( pVBInfo->TVInfo & TVSimuMode )
+ {
+ temp -= 4 ;
+ if ( ModeNo > 0x13 )
+ temp -= 10 ;
+ }
+ }
+ }
+ else
+ {
+ /* tempcx = tempbx & 0x00FF ; */
+ tempbx = ( tempbx & 0xFF00 ) >> 8 ;
+ tempcx = ( tempcx + tempbx ) >> 1 ;
+ temp = ( tempcx & 0x00FF ) + 2 ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToTV )
+ {
+ temp -= 1 ;
+ if ( !( modeflag & HalfDCLK ) )
+ {
+ if ( ( modeflag & Charx8Dot ) )
+ {
+ temp += 4 ;
+ if ( pVBInfo->VGAHDE >= 800 )
+ {
+ temp -= 6 ;
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( !( modeflag & HalfDCLK ) )
+ {
+ temp -= 4 ;
+ if ( pVBInfo->LCDResInfo != Panel1280x960 )
+ {
+ if( pVBInfo->VGAHDE >= 800 )
+ {
+ temp -= 7 ;
+ if ( pVBInfo->ModeType == ModeEGA )
+ {
+ if ( pVBInfo->VGAVDE == 1024 )
+ {
+ temp += 15 ;
+ if ( pVBInfo->LCDResInfo != Panel1280x1024 )
+ {
+ temp += 7 ;
+ }
+ }
+ }
+
+ if ( pVBInfo->VGAHDE >= 1280 )
+ {
+ if ( pVBInfo->LCDResInfo != Panel1280x960 )
+ {
+ if ( pVBInfo->LCDInfo & LCDNonExpanding )
+ {
+ temp += 28 ;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , temp ) ; /* 0x07 Horizontal Retrace Start */
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0 ) ; /* 0x08 Horizontal Retrace End */
+
+ if ( pVBInfo->VBInfo & SetCRT2ToTV )
+ {
+ if ( pVBInfo->TVInfo & TVSimuMode )
+ {
+ if ( ( ModeNo == 0x06 ) || ( ModeNo == 0x10 ) || ( ModeNo == 0x11 ) || ( ModeNo == 0x13 ) || ( ModeNo == 0x0F ) )
+ {
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x5b ) ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x03 ) ;
+ }
+
+ if ( ( ModeNo == 0x00 ) || ( ModeNo == 0x01 ) )
+ {
+ if ( pVBInfo->TVInfo & SetNTSCTV )
+ {
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x2A ) ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x61 ) ;
+ }
+ else
+ {
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x2A ) ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x41 ) ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x0C , 0xF0 ) ;
+ }
+ }
+
+ if ( ( ModeNo == 0x02 ) || ( ModeNo == 0x03 ) || ( ModeNo == 0x07 ) )
+ {
+ if ( pVBInfo->TVInfo & SetNTSCTV )
+ {
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x54 ) ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x00 ) ;
+ }
+ else
+ {
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x55 ) ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x00 ) ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x0C , 0xF0 ) ;
+ }
+ }
+
+ if ( ( ModeNo == 0x04 ) || ( ModeNo == 0x05 ) || ( ModeNo == 0x0D ) || ( ModeNo == 0x50 ) )
+ {
+ if ( pVBInfo->TVInfo & SetNTSCTV )
+ {
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x30 ) ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x03 ) ;
+ }
+ else
+ {
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x2f ) ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x02 ) ;
+ }
+ }
+ }
+ }
+
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x18 , 0x03 ) ; /* 0x18 SR0B */
+ XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x19 , 0xF0 , 0x00 ) ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x09 , 0xFF ) ; /* 0x09 Set Max VT */
+
+ tempbx = pVBInfo->VGAVT ;
+ push1 = tempbx ;
+ tempcx = 0x121 ;
+ tempbx = pVBInfo->VGAVDE ; /* 0x0E Virtical Display End */
+
+ if ( tempbx == 357 )
+ tempbx = 350 ;
+ if ( tempbx == 360 )
+ tempbx =350 ;
+ if ( tempbx == 375 )
+ tempbx = 350 ;
+ if ( tempbx == 405 )
+ tempbx = 400 ;
+ if ( tempbx == 525 )
+ tempbx = 480 ;
+
+ push2 = tempbx ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToLCD )
+ {
+ if ( pVBInfo->LCDResInfo == Panel1024x768 )
+ {
+ if ( !( pVBInfo->LCDInfo & LCDVESATiming ) )
+ {
+ if ( tempbx == 350 )
+ tempbx += 5 ;
+ if ( tempbx == 480 )
+ tempbx += 5 ;
+ }
+ }
+ }
+ tempbx-- ;
+ temp = tempbx & 0x00FF ;
+ tempbx-- ;
+ temp = tempbx & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x10 ,temp ) ; /* 0x10 vertical Blank Start */
+ tempbx = push2 ;
+ tempbx-- ;
+ temp = tempbx & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x0E , temp ) ;
+
+ if ( tempbx & 0x0100 )
+ {
+ tempcx |= 0x0002 ;
+ }
+
+ tempax = 0x000B ;
+
+ if ( modeflag & DoubleScanMode )
+ {
+ tempax |= 0x08000 ;
+ }
+
+ if ( tempbx & 0x0200 )
+ {
+ tempcx |= 0x0040 ;
+ }
+
+ temp = ( tempax & 0xFF00 ) >> 8 ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x0B , temp ) ;
+
+ if ( tempbx & 0x0400 )
+ {
+ tempcx |= 0x0600 ;
+ }
+
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x11 , 0x00 ) ; /* 0x11 Vertival Blank End */
+
+ tempax = push1 ;
+ tempax -= tempbx ; /* 0x0C Vertical Retrace Start */
+ tempax = tempax >> 2 ;
+ push1 = tempax ; /* push ax */
+
+ if ( resinfo != 0x09 )
+ {
+ tempax = tempax << 1 ;
+ tempbx += tempax ;
+ }
+
+ if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+ {
+ if ( pVBInfo->VBType & VB_XGI301LV )
+ {
+ if ( pVBInfo->TVInfo & SetYPbPrMode1080i )
+ tempbx -= 10 ;
+ else
+ {
+ if ( pVBInfo->TVInfo & TVSimuMode )
+ {
+ if ( pVBInfo->TVInfo & SetPALTV )
+ {
+ if ( pVBInfo->VBType & VB_XGI301LV )
+ {
+ if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p | SetYPbPrMode1080i ) ) )
+ tempbx += 40 ;
+ }
+ else
+ tempbx += 40 ;
+ }
+ }
+ }
+ }
+ else
+ tempbx -= 10 ;
+ }
+ else
+ {
+ if ( pVBInfo->TVInfo & TVSimuMode )
+ {
+ if ( pVBInfo->TVInfo & SetPALTV )
+ {
+ if ( pVBInfo->VBType & VB_XGI301LV )
+ {
+ if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p | SetYPbPrMode1080i ) ) )
+ tempbx += 40 ;
+ }
+ else
+ tempbx += 40 ;
+ }
+ }
+ }
+ tempax = push1 ;
+ tempax = tempax >> 2 ;
+ tempax++ ;
+ tempax += tempbx ;
+ push1 = tempax ; /* push ax */
+
+ if ( ( pVBInfo->TVInfo & SetPALTV ) )
+ {
+ if ( tempbx <= 513 )
+ {
+ if ( tempax >= 513 )
+ {
+ tempbx = 513 ;
+ }
+ }
+ }
+
+ temp = tempbx & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x0C , temp ) ;
+ tempbx-- ;
+ temp = tempbx & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x10 , temp ) ;
+
+ if ( tempbx & 0x0100 )
+ {
+ tempcx |= 0x0008 ;
+ }
+
+ if ( tempbx & 0x0200 )
+ {
+ XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x0B , 0x0FF , 0x20 ) ;
+ }
+
+ tempbx++ ;
+
+ if ( tempbx & 0x0100 )
+ {
+ tempcx |= 0x0004 ;
+ }
+
+ if ( tempbx & 0x0200 )
+ {
+ tempcx |= 0x0080 ;
+ }
+
+ if ( tempbx & 0x0400 )
+ {
+ tempcx |= 0x0C00 ;
+ }
+
+ tempbx = push1 ; /* pop ax */
+ temp = tempbx & 0x00FF ;
+ temp &= 0x0F ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x0D , temp ) ; /* 0x0D vertical Retrace End */
+
+ if ( tempbx & 0x0010 )
+ {
+ tempcx |= 0x2000 ;
+ }
+
+ temp = tempcx & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x0A , temp ) ; /* 0x0A CR07 */
+ temp = ( tempcx & 0x0FF00 ) >> 8 ;
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x17 , temp ) ; /* 0x17 SR0A */
+ tempax = modeflag ;
+ temp = ( tempax & 0xFF00 ) >> 8 ;
+
+ temp = ( temp >> 1 ) & 0x09 ;
+
+ if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ temp |= 0x01 ;
+
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x16 , temp ) ; /* 0x16 SR01 */
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x0F , 0 ) ; /* 0x0F CR14 */
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x12 , 0 ) ; /* 0x12 CR17 */
+
+ if ( pVBInfo->LCDInfo & LCDRGB18Bit )
+ temp = 0x80 ;
+ else
+ temp = 0x00 ;
+
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x1A , temp ) ; /* 0x1A SR0E */
+
+ return ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetGroup2 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetGroup2( USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex,
+ PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT i ,
+ j ,
+ tempax ,
+ tempbx ,
+ tempcx ,
+ temp ,
+ push1 ,
+ push2 ,
+ modeflag ,
+ resinfo ,
+ crt2crtc ;
+ UCHAR *TimingPoint ;
+
+ ULONG longtemp ,
+ tempeax ,
+ tempebx ,
+ temp2 ,
+ tempecx ;
+
+ if ( ModeNo <= 0x13 )
+ {
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ResInfo */
+ resinfo = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ;
+ crt2crtc = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ;
+ }
+ else
+ {
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; /* si+Ext_ResInfo */
+ resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;
+ crt2crtc = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT2CRTC ;
+ }
+
+ tempax = 0 ;
+
+ if ( !( pVBInfo->VBInfo & SetCRT2ToAVIDEO ) )
+ tempax |= 0x0800 ;
+
+ if ( !( pVBInfo->VBInfo & SetCRT2ToSVIDEO ) )
+ tempax |= 0x0400 ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToSCART )
+ tempax |= 0x0200 ;
+
+ if ( !( pVBInfo->TVInfo & SetPALTV ) )
+ tempax |= 0x1000 ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+ tempax |= 0x0100 ;
+
+ if ( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) )
+ tempax &= 0xfe00 ;
+
+ tempax = ( tempax & 0xff00 ) >> 8 ;
+
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x0 , tempax ) ;
+ TimingPoint = pVBInfo->NTSCTiming ;
+
+ if ( pVBInfo->TVInfo & SetPALTV )
+ {
+ TimingPoint = pVBInfo->PALTiming ;
+ }
+
+ if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+ {
+ TimingPoint = pVBInfo->HiTVExtTiming ;
+
+ if ( pVBInfo->VBInfo & SetInSlaveMode )
+ TimingPoint = pVBInfo->HiTVSt2Timing ;
+
+ if ( pVBInfo->SetFlag & TVSimuMode )
+ TimingPoint = pVBInfo->HiTVSt1Timing ;
+
+ if ( !(modeflag & Charx8Dot) )
+ TimingPoint = pVBInfo->HiTVTextTiming ;
+ }
+
+ if ( pVBInfo->VBInfo & SetCRT2ToYPbPr )
+ {
+ if ( pVBInfo->TVInfo & SetYPbPrMode525i )
+ TimingPoint = pVBInfo->YPbPr525iTiming ;
+
+ if ( pVBInfo->TVInfo & SetYPbPrMode525p )
+ TimingPoint = pVBInfo->YPbPr525pTiming ;
+
+ if ( pVBInfo->TVInfo & SetYPbPrMode750p )
+ TimingPoint = pVBInfo->YPbPr750pTiming ;
+ }
+
+ for( i = 0x01 , j = 0 ; i <= 0x2D ; i++ , j++ )
+ {
+ XGINew_SetReg1( pVBInfo->Part2Port , i , TimingPoint[ j ] ) ;
+ }
+
+ for( i = 0x39 ; i <= 0x45 ; i++ , j++ )
+ {
+ XGINew_SetReg1( pVBInfo->Part2Port , i , TimingPoint[ j ] ) ; /* di->temp2[j] */
+ }
+
+ if ( pVBInfo->VBInfo & SetCRT2ToTV )
+ {
+ XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x3A , 0x1F , 0x00 ) ;
+ }
+
+ temp = pVBInfo->NewFlickerMode ;
+ temp &= 0x80 ;
+ XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x0A , 0xFF , temp ) ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+ tempax = 950 ;
+
+ if ( pVBInfo->TVInfo & SetPALTV )
+ tempax = 520 ;
+ else
+ tempax = 440 ;
+
+ if ( pVBInfo->VDE <= tempax )
+ {
+ tempax -= pVBInfo->VDE ;
+ tempax = tempax >> 2 ;
+ tempax = ( tempax & 0x00FF ) | ( ( tempax & 0x00FF ) << 8 ) ;
+ push1 = tempax ;
+ temp = ( tempax & 0xFF00 ) >> 8 ;
+ temp += ( USHORT )TimingPoint[ 0 ] ;
+
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ if ( pVBInfo->VBInfo & ( SetCRT2ToAVIDEO | SetCRT2ToSVIDEO | SetCRT2ToSCART | SetCRT2ToYPbPr ) )
+ {
+ tempcx=pVBInfo->VGAHDE;
+ if ( tempcx >= 1024 )
+ {
+ temp = 0x17 ; /* NTSC */
+ if ( pVBInfo->TVInfo & SetPALTV )
+ temp = 0x19 ; /* PAL */
+ }
+ }
+ }
+
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x01 , temp ) ;
+ tempax = push1 ;
+ temp = ( tempax & 0xFF00 ) >> 8 ;
+ temp += TimingPoint[ 1 ] ;
+
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ if ( ( pVBInfo->VBInfo & ( SetCRT2ToAVIDEO | SetCRT2ToSVIDEO | SetCRT2ToSCART | SetCRT2ToYPbPr ) ) )
+ {
+ tempcx = pVBInfo->VGAHDE ;
+ if ( tempcx >= 1024 )
+ {
+ temp = 0x1D ; /* NTSC */
+ if ( pVBInfo->TVInfo & SetPALTV )
+ temp = 0x52 ; /* PAL */
+ }
+ }
+ }
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x02 , temp ) ;
+ }
+
+ /* 301b */
+ tempcx = pVBInfo->HT ;
+
+ if ( XGI_IsLCDDualLink( pVBInfo ) )
+ tempcx = tempcx >> 1 ;
+
+ tempcx -= 2 ;
+ temp = tempcx & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x1B , temp ) ;
+
+ temp = ( tempcx & 0xFF00 ) >> 8 ;
+ XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x1D , ~0x0F , temp ) ;
+
+ tempcx = pVBInfo->HT >> 1 ;
+ push1 = tempcx ; /* push cx */
+ tempcx += 7 ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+ {
+ tempcx -= 4 ;
+ }
+
+ temp = tempcx & 0x00FF ;
+ temp = temp << 4 ;
+ XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x22 , 0x0F , temp ) ;
+
+ tempbx = TimingPoint[ j ] | ( ( TimingPoint[ j + 1 ] ) << 8 ) ;
+ tempbx += tempcx ;
+ push2 = tempbx ;
+ temp = tempbx & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x24 , temp ) ;
+ temp = ( tempbx & 0xFF00 ) >> 8 ;
+ temp = temp << 4 ;
+ XGINew_SetRegANDOR(pVBInfo->Part2Port,0x25,0x0F,temp);
+
+ tempbx=push2;
+ tempbx=tempbx+8;
+ if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+ {
+ tempbx=tempbx-4;
+ tempcx=tempbx;
+ }
+
+ temp = ( tempbx & 0x00FF ) << 4 ;
+ XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x29 , 0x0F , temp ) ;
+
+ j += 2 ;
+ tempcx += ( TimingPoint[ j ] | ( ( TimingPoint[ j + 1 ] ) << 8 ) ) ;
+ temp = tempcx & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x27 , temp ) ;
+ temp = ( ( tempcx & 0xFF00 ) >> 8 ) << 4 ;
+ XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x28 , 0x0F , temp ) ;
+
+ tempcx += 8 ;
+ if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+ {
+ tempcx -= 4 ;
+ }
+
+ temp = tempcx & 0xFF ;
+ temp = temp << 4 ;
+ XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x2A , 0x0F , temp ) ;
+
+ tempcx = push1 ; /* pop cx */
+ j += 2 ;
+ temp = TimingPoint[ j ] | ( ( TimingPoint[ j + 1 ] ) << 8 ) ;
+ tempcx -= temp ;
+ temp = tempcx & 0x00FF ;
+ temp = temp << 4 ;
+ XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x2D , 0x0F ,temp ) ;
+
+ tempcx -= 11 ;
+
+ if ( !( pVBInfo->VBInfo & SetCRT2ToTV ) )
+ {
+ tempax = XGI_GetVGAHT2( pVBInfo) ;
+ tempcx = tempax - 1 ;
+ }
+ temp = tempcx & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x2E , temp ) ;
+
+ tempbx = pVBInfo->VDE ;
+
+ if ( pVBInfo->VGAVDE == 360 )
+ tempbx = 746 ;
+ if ( pVBInfo->VGAVDE == 375 )
+ tempbx = 746 ;
+ if ( pVBInfo->VGAVDE == 405 )
+ tempbx = 853 ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToTV )
+ {
+ if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) ) )
+ tempbx = tempbx >> 1 ;
+ }
+ else
+ tempbx = tempbx >> 1 ;
+ }
+
+ tempbx -= 2 ;
+ temp = tempbx & 0x00FF ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+ {
+ if ( pVBInfo->VBType & VB_XGI301LV )
+ {
+ if ( pVBInfo->TVInfo & SetYPbPrMode1080i )
+ {
+ if ( pVBInfo->VBInfo & SetInSlaveMode )
+ {
+ if ( ModeNo == 0x2f )
+ temp += 1 ;
+ }
+ }
+ }
+ else
+ {
+ if ( pVBInfo->VBInfo & SetInSlaveMode )
+ {
+ if ( ModeNo == 0x2f )
+ temp += 1 ;
+ }
+ }
+ }
+
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x2F , temp ) ;
+
+ temp = ( tempcx & 0xFF00 ) >> 8 ;
+ temp |= ( ( tempbx & 0xFF00 ) >> 8 ) << 6 ;
+
+ if ( !( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) )
+ {
+ if ( pVBInfo->VBType & VB_XGI301LV )
+ {
+ if ( pVBInfo->TVInfo & SetYPbPrMode1080i )
+ {
+ temp |= 0x10 ;
+
+ if ( !( pVBInfo->VBInfo & SetCRT2ToSVIDEO ) )
+ temp |= 0x20 ;
+ }
+ }
+ else
+ {
+ temp |= 0x10 ;
+ if ( !( pVBInfo->VBInfo & SetCRT2ToSVIDEO ) )
+ temp |= 0x20 ;
+ }
+ }
+
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x30 , temp ) ;
+
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) /* TV gatingno */
+ {
+ tempbx = pVBInfo->VDE ;
+ tempcx = tempbx - 2 ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToTV )
+ {
+ if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) ) )
+ tempbx = tempbx >> 1 ;
+ }
+
+ if ( pVBInfo->VBType & ( VB_XGI302LV | VB_XGI301C ) )
+ {
+ temp=0;
+ if( tempcx & 0x0400 )
+ temp |= 0x20 ;
+
+ if ( tempbx & 0x0400 )
+ temp |= 0x40 ;
+
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x10 , temp ) ;
+ }
+
+ temp = ( ( ( tempbx - 3 ) & 0x0300 ) >> 8 ) << 5 ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x46 , temp ) ;
+ temp = ( tempbx - 3 ) & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x47 , temp ) ;
+ }
+
+ tempbx = tempbx & 0x00FF ;
+
+ if ( !( modeflag & HalfDCLK ) )
+ {
+ tempcx = pVBInfo->VGAHDE ;
+ if ( tempcx >= pVBInfo->HDE )
+ {
+ tempbx |= 0x2000 ;
+ tempax &= 0x00FF ;
+ }
+ }
+
+ tempcx = 0x0101 ;
+
+ if( pVBInfo->VBInfo & SetCRT2ToTV ) { /*301b*/
+ if(pVBInfo->VGAHDE>=1024)
+ {
+ tempcx=0x1920;
+ if(pVBInfo->VGAHDE>=1280)
+ {
+ tempcx=0x1420;
+ tempbx=tempbx&0xDFFF;
+ }
+ }
+ }
+
+ if ( !( tempbx & 0x2000 ) )
+ {
+ if ( modeflag & HalfDCLK )
+ {
+ tempcx = ( tempcx & 0xFF00 ) | ( ( tempcx & 0x00FF ) << 1 ) ;
+ }
+
+ push1 = tempbx ;
+ tempeax = pVBInfo->VGAHDE ;
+ tempebx = ( tempcx & 0xFF00 ) >> 8 ;
+ longtemp = tempeax * tempebx ;
+ tempecx = tempcx & 0x00FF ;
+ longtemp = longtemp / tempecx ;
+
+ /* 301b */
+ tempecx = 8 * 1024 ;
+
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ tempecx = tempecx * 8 ;
+ }
+
+ longtemp = longtemp * tempecx ;
+ tempecx = pVBInfo->HDE ;
+ temp2 = longtemp % tempecx ;
+ tempeax = longtemp / tempecx ;
+ if ( temp2 != 0 )
+ {
+ tempeax += 1 ;
+ }
+
+ tempax = ( USHORT )tempeax ;
+
+ /* 301b */
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ tempcx = ( ( tempax & 0xFF00 ) >> 5 ) >> 8 ;
+ }
+ /* end 301b */
+
+ tempbx = push1 ;
+ tempbx =( USHORT )( ( ( tempeax & 0x0000FF00 ) & 0x1F00 ) | ( tempbx & 0x00FF ) ) ;
+ tempax =( USHORT )( ( ( tempeax & 0x000000FF ) << 8 ) | ( tempax & 0x00FF ) ) ;
+ temp = ( tempax & 0xFF00 ) >> 8 ;
+ }
+ else
+ {
+ temp = ( tempax & 0x00FF ) >> 8 ;
+ }
+
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x44 , temp ) ;
+ temp = ( tempbx & 0xFF00 ) >> 8 ;
+ XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x45 , ~0x03F , temp ) ;
+ temp = tempcx & 0x00FF ;
+
+ if ( tempbx & 0x2000 )
+ temp = 0 ;
+
+ if ( !( pVBInfo->VBInfo & SetCRT2ToLCD ) )
+ temp |= 0x18 ;
+
+ XGINew_SetRegANDOR(pVBInfo->Part2Port,0x46,~0x1F,temp);
+ if ( pVBInfo->TVInfo & SetPALTV )
+ {
+ tempbx = 0x0382 ;
+ tempcx = 0x007e ;
+ }
+ else
+ {
+ tempbx = 0x0369 ;
+ tempcx = 0x0061 ;
+ }
+
+ temp = tempbx & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x4b , temp ) ;
+ temp = tempcx & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x4c , temp ) ;
+
+ temp = ( ( tempcx & 0xFF00 ) >> 8 ) & 0x03 ;
+ temp = temp << 2 ;
+ temp |= ( ( tempbx & 0xFF00 ) >> 8 ) & 0x03 ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToYPbPr )
+ {
+ temp |= 0x10 ;
+
+ if ( pVBInfo->TVInfo & SetYPbPrMode525p )
+ temp |= 0x20 ;
+
+ if ( pVBInfo->TVInfo & SetYPbPrMode750p )
+ temp |= 0x60 ;
+ }
+
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x4d , temp ) ;
+ temp=XGINew_GetReg1( pVBInfo->Part2Port , 0x43 ) ; /* 301b change */
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x43 , ( USHORT )( temp - 3 ) ) ;
+
+ if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) ) )
+ {
+ if ( pVBInfo->TVInfo & NTSC1024x768 )
+ {
+ TimingPoint = XGI_NTSC1024AdjTime ;
+ for( i = 0x1c , j = 0 ; i <= 0x30 ; i++ , j++ )
+ {
+ XGINew_SetReg1( pVBInfo->Part2Port , i , TimingPoint[ j ] ) ;
+ }
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x43 , 0x72 ) ;
+ }
+ }
+
+ /* [ycchen] 01/14/03 Modify for 301C PALM Support */
+ if ( pVBInfo->VBType & VB_XGI301C )
+ {
+ if ( pVBInfo->TVInfo & SetPALMTV )
+ XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x4E , ~0x08 , 0x08 ) ; /* PALM Mode */
+ }
+
+ if ( pVBInfo->TVInfo & SetPALMTV )
+ {
+ tempax = ( UCHAR )XGINew_GetReg1( pVBInfo->Part2Port , 0x01 ) ;
+ tempax-- ;
+ XGINew_SetRegAND( pVBInfo->Part2Port , 0x01 , tempax ) ;
+
+ /* if ( !( pVBInfo->VBType & VB_XGI301C ) ) */
+ XGINew_SetRegAND( pVBInfo->Part2Port , 0x00 , 0xEF ) ;
+ }
+
+ if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+ {
+ if ( !( pVBInfo->VBInfo & SetInSlaveMode ) )
+ {
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x0B , 0x00 ) ;
+ }
+ }
+
+ if ( pVBInfo->VBInfo & SetCRT2ToTV )
+ {
+ return ;
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetLCDRegs */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetLCDRegs(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT push1 ,
+ push2 ,
+ pushbx ,
+ tempax ,
+ tempbx ,
+ tempcx ,
+ temp ,
+ tempah ,
+ tempbh ,
+ tempch ,
+ resinfo ,
+ modeflag ,
+ CRT1Index ;
+
+ XGI_LCDDesStruct *LCDBDesPtr = NULL ;
+
+
+ if ( ModeNo <= 0x13 )
+ {
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ResInfo */
+ resinfo = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ;
+ }
+ else
+ {
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; /* si+Ext_ResInfo */
+ resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;
+ CRT1Index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ;
+ CRT1Index &= IndexMask ;
+ }
+
+ if ( !( pVBInfo->VBInfo & SetCRT2ToLCD ) )
+ {
+ return ;
+ }
+
+ tempbx = pVBInfo->HDE ; /* RHACTE=HDE-1 */
+
+ if ( XGI_IsLCDDualLink( pVBInfo ) )
+ tempbx = tempbx >> 1 ;
+
+ tempbx -= 1 ;
+ temp = tempbx & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x2C , temp ) ;
+ temp = ( tempbx & 0xFF00 ) >> 8 ;
+ temp = temp << 4 ;
+ XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x2B , 0x0F , temp ) ;
+ temp = 0x01 ;
+
+ if ( pVBInfo->LCDResInfo == Panel1280x1024 )
+ {
+ if ( pVBInfo->ModeType == ModeEGA )
+ {
+ if ( pVBInfo->VGAHDE >= 1024 )
+ {
+ temp = 0x02 ;
+ if ( pVBInfo->LCDInfo & LCDVESATiming )
+ temp = 0x01 ;
+ }
+ }
+ }
+
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x0B , temp ) ;
+ tempbx = pVBInfo->VDE ; /* RTVACTEO=(VDE-1)&0xFF */
+ push1 = tempbx ;
+ tempbx-- ;
+ temp = tempbx & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x03 , temp ) ;
+ temp = ( ( tempbx & 0xFF00 ) >> 8 ) & 0x07 ;
+ XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x0C , ~0x07 , temp ) ;
+
+ tempcx = pVBInfo->VT - 1 ;
+ push2 = tempcx + 1 ;
+ temp = tempcx & 0x00FF ; /* RVTVT=VT-1 */
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x19 , temp ) ;
+ temp = ( tempcx & 0xFF00 ) >> 8 ;
+ temp = temp << 5 ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x1A , temp ) ;
+ XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x09 , 0xF0 , 0x00 ) ;
+ XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x0A , 0xF0 , 0x00 ) ;
+ XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x17 , 0xFB , 0x00 ) ;
+ XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x18 , 0xDF , 0x00 ) ;
+
+ /* Customized LCDB Des no add */
+ tempbx = 5 ;
+ LCDBDesPtr = ( XGI_LCDDesStruct * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+ tempah = pVBInfo->LCDResInfo ;
+ tempah &= PanelResInfo ;
+
+ if ( ( tempah == Panel1024x768 ) || ( tempah == Panel1024x768x75 ) )
+ {
+ tempbx = 1024 ;
+ tempcx = 768 ;
+ }
+ else if ( ( tempah == Panel1280x1024 ) || ( tempah == Panel1280x1024x75 ) )
+ {
+ tempbx = 1280 ;
+ tempcx = 1024 ;
+ }
+ else if ( tempah == Panel1400x1050 )
+ {
+ tempbx = 1400 ;
+ tempcx = 1050 ;
+ }
+ else
+ {
+ tempbx = 1600 ;
+ tempcx = 1200 ;
+ }
+
+ if ( pVBInfo->LCDInfo & EnableScalingLCD )
+ {
+ tempbx = pVBInfo->HDE ;
+ tempcx = pVBInfo->VDE ;
+ }
+
+ pushbx = tempbx ;
+ tempax = pVBInfo->VT ;
+ pVBInfo->LCDHDES = LCDBDesPtr->LCDHDES ;
+ pVBInfo->LCDHRS = LCDBDesPtr->LCDHRS ;
+ pVBInfo->LCDVDES = LCDBDesPtr->LCDVDES ;
+ pVBInfo->LCDVRS = LCDBDesPtr->LCDVRS ;
+ tempbx = pVBInfo->LCDVDES ;
+ tempcx += tempbx ;
+
+ if ( tempcx >= tempax )
+ tempcx -= tempax ; /* lcdvdes */
+
+ temp = tempbx & 0x00FF ; /* RVEQ1EQ=lcdvdes */
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x05 , temp ) ;
+ temp = tempcx & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x06 , temp ) ;
+ tempch = ( ( tempcx & 0xFF00 ) >> 8 ) & 0x07 ;
+ tempbh = ( ( tempbx & 0xFF00 ) >> 8 ) & 0x07 ;
+ tempah = tempch ;
+ tempah = tempah << 3 ;
+ tempah |= tempbh ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x02 , tempah ) ;
+
+ /* getlcdsync() */
+ XGI_GetLCDSync( &tempax , &tempbx,pVBInfo ) ;
+ tempcx = tempbx ;
+ tempax = pVBInfo->VT ;
+ tempbx = pVBInfo->LCDVRS ;
+
+ /* if ( SetLCD_Info & EnableScalingLCD ) */
+ tempcx += tempbx ;
+ if ( tempcx >= tempax )
+ tempcx -= tempax ;
+
+ temp = tempbx & 0x00FF ; /* RTVACTEE=lcdvrs */
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x04 , temp ) ;
+ temp = ( tempbx & 0xFF00 ) >> 8 ;
+ temp = temp << 4 ;
+ temp |= ( tempcx & 0x000F ) ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x01 , temp ) ;
+ tempcx = pushbx ;
+ tempax = pVBInfo->HT ;
+ tempbx = pVBInfo->LCDHDES ;
+ tempbx &= 0x0FFF ;
+
+ if ( XGI_IsLCDDualLink( pVBInfo ) )
+ {
+ tempax = tempax >> 1 ;
+ tempbx = tempbx >> 1 ;
+ tempcx = tempcx >> 1 ;
+ }
+
+ if ( pVBInfo->VBType & VB_XGI302LV )
+ tempbx += 1 ;
+
+ if ( pVBInfo->VBType & VB_XGI301C ) /* tap4 */
+ tempbx += 1 ;
+
+ tempcx += tempbx ;
+
+ if ( tempcx >= tempax )
+ tempcx -= tempax ;
+
+ temp = tempbx & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x1F , temp ) ; /* RHBLKE=lcdhdes */
+ temp = ( ( tempbx & 0xFF00 ) >> 8 ) << 4 ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x20 , temp ) ;
+ temp = tempcx & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x23 , temp ) ; /* RHEQPLE=lcdhdee */
+ temp = ( tempcx & 0xFF00 ) >> 8 ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x25 , temp ) ;
+
+ /* getlcdsync() */
+ XGI_GetLCDSync( &tempax , &tempbx ,pVBInfo) ;
+ tempcx = tempax ;
+ tempax = pVBInfo->HT ;
+ tempbx = pVBInfo->LCDHRS ;
+ /* if ( SetLCD_Info & EnableScalingLCD) */
+ if ( XGI_IsLCDDualLink( pVBInfo) )
+ {
+ tempax = tempax >> 1 ;
+ tempbx = tempbx >> 1 ;
+ tempcx = tempcx >> 1 ;
+ }
+
+ if ( pVBInfo->VBType & VB_XGI302LV )
+ tempbx += 1 ;
+
+ tempcx += tempbx ;
+
+ if ( tempcx >= tempax )
+ tempcx -= tempax ;
+
+ temp = tempbx & 0x00FF ; /* RHBURSTS=lcdhrs */
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x1C , temp ) ;
+
+ temp = ( tempbx & 0xFF00 ) >> 8 ;
+ temp = temp << 4 ;
+ XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x1D , ~0x0F0 , temp ) ;
+ temp = tempcx & 0x00FF ; /* RHSYEXP2S=lcdhre */
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x21 , temp ) ;
+
+ if ( !( pVBInfo->LCDInfo & LCDVESATiming ) )
+ {
+ if ( pVBInfo->VGAVDE == 525 )
+ {
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ temp = 0xC6 ;
+ }
+ else
+ temp = 0xC4 ;
+
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x2f , temp ) ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x30 , 0xB3 ) ;
+ }
+
+ if ( pVBInfo->VGAVDE == 420 )
+ {
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ temp = 0x4F ;
+ }
+ else
+ temp = 0x4E ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x2f , temp ) ;
+ }
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetTap4Ptr */
+/* Input : */
+/* Output : di -> Tap4 Reg. Setting Pointer */
+/* Description : */
+/* --------------------------------------------------------------------- */
+XGI301C_Tap4TimingStruct* XGI_GetTap4Ptr(USHORT tempcx, PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT tempax ,
+ tempbx ,
+ i ;
+
+ XGI301C_Tap4TimingStruct *Tap4TimingPtr ;
+
+ if ( tempcx == 0 )
+ {
+ tempax = pVBInfo->VGAHDE ;
+ tempbx = pVBInfo->HDE ;
+ }
+ else
+ {
+ tempax = pVBInfo->VGAVDE ;
+ tempbx = pVBInfo->VDE ;
+ }
+
+ if ( tempax < tempbx )
+ return &EnlargeTap4Timing[ 0 ] ;
+ else if( tempax == tempbx )
+ return &NoScaleTap4Timing[ 0 ] ; /* 1:1 */
+ else
+ Tap4TimingPtr = NTSCTap4Timing ; /* NTSC */
+
+ if ( pVBInfo->TVInfo & SetPALTV )
+ Tap4TimingPtr = PALTap4Timing ;
+
+
+ if ( pVBInfo->VBInfo & SetCRT2ToYPbPr )
+ {
+ if ( pVBInfo->TVInfo & SetYPbPrMode525i )
+ Tap4TimingPtr = YPbPr525iTap4Timing ;
+ if ( pVBInfo->TVInfo & SetYPbPrMode525p )
+ Tap4TimingPtr = YPbPr525pTap4Timing ;
+ if ( pVBInfo->TVInfo & SetYPbPrMode750p )
+ Tap4TimingPtr = YPbPr750pTap4Timing ;
+ }
+
+ if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+ Tap4TimingPtr = HiTVTap4Timing ;
+
+ i = 0 ;
+ while( Tap4TimingPtr[ i ].DE != 0xFFFF )
+ {
+ if ( Tap4TimingPtr[ i ].DE == tempax )
+ break ;
+ i++ ;
+ }
+ return &Tap4TimingPtr[ i ] ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetTap4Regs */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetTap4Regs( PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT i ,
+ j ;
+
+ XGI301C_Tap4TimingStruct *Tap4TimingPtr ;
+
+ if ( !( pVBInfo->VBType & VB_XGI301C ) )
+ return ;
+
+#ifndef Tap4
+ XGINew_SetRegAND( pVBInfo->Part2Port , 0x4E , 0xEB ) ; /* Disable Tap4 */
+#else /* Tap4 Setting */
+
+ Tap4TimingPtr = XGI_GetTap4Ptr( 0 , pVBInfo) ; /* Set Horizontal Scaling */
+ for( i = 0x80 , j = 0 ; i <= 0xBF ; i++ , j++ )
+ XGINew_SetReg1( pVBInfo->Part2Port , i , Tap4TimingPtr->Reg[ j ] ) ;
+
+ if ( ( pVBInfo->VBInfo & SetCRT2ToTV ) && ( !( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) ) )
+ {
+ Tap4TimingPtr = XGI_GetTap4Ptr( 1 , pVBInfo); /* Set Vertical Scaling */
+ for( i = 0xC0 , j = 0 ; i < 0xFF ; i++ , j++ )
+ XGINew_SetReg1( pVBInfo->Part2Port , i , Tap4TimingPtr->Reg[ j ] ) ;
+ }
+
+ if ( ( pVBInfo->VBInfo & SetCRT2ToTV ) && ( !( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) ) )
+ XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x4E , ~0x14 , 0x04 ) ; /* Enable V.Scaling */
+ else
+ XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x4E , ~0x14 , 0x10 ) ; /* Enable H.Scaling */
+#endif
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetGroup3 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetGroup3(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT i;
+ UCHAR *tempdi;
+ USHORT modeflag;
+
+ if(ModeNo<=0x13)
+ {
+ modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
+ }
+ else
+ {
+ modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
+ }
+
+
+ XGINew_SetReg1(pVBInfo->Part3Port,0x00,0x00);
+ if(pVBInfo->TVInfo&SetPALTV)
+ {
+ XGINew_SetReg1(pVBInfo->Part3Port,0x13,0xFA);
+ XGINew_SetReg1(pVBInfo->Part3Port,0x14,0xC8);
+ }
+ else
+ {
+ XGINew_SetReg1(pVBInfo->Part3Port,0x13,0xF5);
+ XGINew_SetReg1(pVBInfo->Part3Port,0x14,0xB7);
+ }
+
+ if(!(pVBInfo->VBInfo&SetCRT2ToTV))
+ {
+ return;
+ }
+
+ if(pVBInfo->TVInfo&SetPALMTV)
+ {
+ XGINew_SetReg1(pVBInfo->Part3Port,0x13,0xFA);
+ XGINew_SetReg1(pVBInfo->Part3Port,0x14,0xC8);
+ XGINew_SetReg1(pVBInfo->Part3Port,0x3D,0xA8);
+ }
+
+ if((pVBInfo->VBInfo&SetCRT2ToHiVisionTV)|| (pVBInfo->VBInfo&SetCRT2ToYPbPr))
+ {
+ if(pVBInfo->TVInfo & SetYPbPrMode525i)
+ {
+ return;
+ }
+ tempdi=pVBInfo->HiTVGroup3Data;
+ if(pVBInfo->SetFlag&TVSimuMode)
+ {
+ tempdi=pVBInfo->HiTVGroup3Simu;
+ if(!(modeflag&Charx8Dot))
+ {
+ tempdi=pVBInfo->HiTVGroup3Text;
+ }
+ }
+
+ if(pVBInfo->TVInfo & SetYPbPrMode525p)
+ {
+ tempdi=pVBInfo->Ren525pGroup3;
+ }
+ if(pVBInfo->TVInfo & SetYPbPrMode750p)
+ {
+ tempdi=pVBInfo->Ren750pGroup3;
+ }
+
+ for(i=0;i<=0x3E;i++)
+ {
+ XGINew_SetReg1(pVBInfo->Part3Port,i,tempdi[i]);
+ }
+ if(pVBInfo->VBType&VB_XGI301C) /* Marcovision */
+ {
+ if(pVBInfo->TVInfo & SetYPbPrMode525p)
+ {
+ XGINew_SetReg1(pVBInfo->Part3Port,0x28,0x3f);
+ }
+ }
+ }
+ return;
+} /* {end of XGI_SetGroup3} */
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetGroup4 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetGroup4(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT tempax ,
+ tempcx ,
+ tempbx ,
+ modeflag ,
+ temp ,
+ temp2 ;
+
+ ULONG tempebx ,
+ tempeax ,
+ templong ;
+
+
+ if ( ModeNo <= 0x13 )
+ {
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ResInfo */
+ }
+ else
+ {
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; /* si+Ext_ResInfo */
+ }
+
+ temp = pVBInfo->RVBHCFACT ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x13 , temp ) ;
+
+ tempbx = pVBInfo->RVBHCMAX ;
+ temp = tempbx & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x14 , temp ) ;
+ temp2 = ( ( tempbx & 0xFF00 ) >> 8 ) << 7 ;
+ tempcx = pVBInfo->VGAHT - 1 ;
+ temp = tempcx & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x16 , temp ) ;
+
+ temp =( ( tempcx & 0xFF00 ) >> 8 ) << 3 ;
+ temp2 |= temp ;
+
+ tempcx = pVBInfo->VGAVT - 1 ;
+ if ( !( pVBInfo->VBInfo & SetCRT2ToTV ) )
+ {
+ tempcx -= 5 ;
+ }
+
+ temp = tempcx & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x17 , temp ) ;
+ temp = temp2 | ( ( tempcx & 0xFF00 ) >> 8 ) ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x15 , temp ) ;
+ XGINew_SetRegOR( pVBInfo->Part4Port , 0x0D , 0x08 ) ;
+ tempcx = pVBInfo->VBInfo ;
+ tempbx = pVBInfo->VGAHDE ;
+
+ if ( modeflag & HalfDCLK )
+ {
+ tempbx = tempbx >> 1 ;
+ }
+
+ if ( XGI_IsLCDDualLink( pVBInfo ) )
+ tempbx = tempbx >> 1 ;
+
+ if(tempcx&SetCRT2ToHiVisionTV)
+ {
+ temp=0;
+ if(tempbx<=1024)
+ temp=0xA0;
+ if(tempbx == 1280)
+ temp = 0xC0;
+ }
+ else if(tempcx&SetCRT2ToTV)
+ {
+ temp=0xA0;
+ if(tempbx <= 800)
+ temp=0x80;
+ }
+ else
+ {
+ temp=0x80;
+ if(pVBInfo->VBInfo&SetCRT2ToLCD)
+ {
+ temp=0;
+ if(tempbx>800)
+ temp=0x60;
+ }
+ }
+
+ if ( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) )
+ {
+ temp = 0x00 ;
+ if ( pVBInfo->VGAHDE == 1280 )
+ temp = 0x40 ;
+ if ( pVBInfo->VGAHDE == 1024 )
+ temp = 0x20 ;
+ }
+ XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x0E , ~0xEF , temp ) ;
+
+ tempebx = pVBInfo->VDE ;
+
+ if ( tempcx & SetCRT2ToHiVisionTV )
+ {
+ if ( !( temp & 0xE000 ) )
+ tempbx = tempbx >> 1 ;
+ }
+
+ tempcx = pVBInfo->RVBHRS ;
+ temp = tempcx & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x18 , temp );
+
+ tempeax = pVBInfo->VGAVDE ;
+ tempcx |= 0x04000 ;
+
+
+ if ( tempeax <= tempebx )
+ {
+ tempcx=(tempcx&(~0x4000));
+ tempeax = pVBInfo->VGAVDE ;
+ }
+ else
+ {
+ tempeax -= tempebx ;
+ }
+
+
+ templong = ( tempeax * 256 * 1024 ) % tempebx ;
+ tempeax = ( tempeax * 256 * 1024 ) / tempebx ;
+ tempebx = tempeax ;
+
+ if ( templong != 0 )
+ {
+ tempebx++ ;
+ }
+
+
+ temp = ( USHORT )( tempebx & 0x000000FF ) ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x1B , temp ) ;
+
+ temp = ( USHORT )( ( tempebx & 0x0000FF00 ) >> 8 ) ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x1A , temp ) ;
+ tempbx = ( USHORT )( tempebx >> 16 ) ;
+ temp = tempbx & 0x00FF ;
+ temp = temp << 4 ;
+ temp |= ( ( tempcx & 0xFF00 ) >> 8 ) ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x19 , temp ) ;
+
+ /* 301b */
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ temp = 0x0028 ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x1C , temp ) ;
+ tempax = pVBInfo->VGAHDE ;
+ if ( modeflag & HalfDCLK )
+ {
+ tempax = tempax >> 1 ;
+ }
+
+ if ( XGI_IsLCDDualLink( pVBInfo ) )
+ tempax = tempax >> 1 ;
+
+ /* if((pVBInfo->VBInfo&(SetCRT2ToLCD))||((pVBInfo->TVInfo&SetYPbPrMode525p)||(pVBInfo->TVInfo&SetYPbPrMode750p))) { */
+ if ( pVBInfo->VBInfo & SetCRT2ToLCD )
+ {
+ if ( tempax > 800 )
+ tempax -= 800 ;
+ }
+ else
+ {
+ if ( pVBInfo->VGAHDE > 800 )
+ {
+ if ( pVBInfo->VGAHDE == 1024 )
+ tempax = ( tempax * 25 / 32 ) - 1 ;
+ else
+ tempax = ( tempax * 20 / 32 ) - 1 ;
+ }
+ }
+ tempax -= 1 ;
+
+/*
+ if ( pVBInfo->VBInfo & ( SetCRT2ToTV | SetCRT2ToHiVisionTV ) )
+ {
+ if ( pVBInfo->VBType & VB_XGI301LV )
+ {
+ if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p | SetYPbPrMode1080i ) ) )
+ {
+ if ( pVBInfo->VGAHDE > 800 )
+ {
+ if ( pVBInfo->VGAHDE == 1024 )
+ tempax = ( tempax * 25 / 32 ) - 1 ;
+ else
+ tempax = ( tempax * 20 / 32 ) - 1 ;
+ }
+ }
+ }
+ else
+ {
+ if ( pVBInfo->VGAHDE > 800 )
+ {
+ if ( pVBInfo->VGAHDE == 1024 )
+ tempax = ( tempax * 25 / 32 ) - 1 ;
+ else
+ tempax = ( tempax * 20 / 32 ) - 1 ;
+ }
+ }
+ }
+*/
+
+ temp = ( tempax & 0xFF00 ) >> 8 ;
+ temp = ( ( temp & 0x0003 ) << 4 ) ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x1E , temp ) ;
+ temp = ( tempax & 0x00FF ) ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x1D , temp ) ;
+
+ if ( pVBInfo->VBInfo & ( SetCRT2ToTV | SetCRT2ToHiVisionTV ) )
+ {
+ if ( pVBInfo->VGAHDE > 800 )
+ {
+ XGINew_SetRegOR( pVBInfo->Part4Port , 0x1E , 0x08 ) ;
+ }
+ }
+ temp = 0x0036 ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToTV )
+ {
+ if ( !( pVBInfo->TVInfo & ( NTSC1024x768 | SetYPbPrMode525p | SetYPbPrMode750p | SetYPbPrMode1080i ) ) )
+ {
+ temp |= 0x0001 ;
+ if ( ( pVBInfo->VBInfo & SetInSlaveMode ) && ( !( pVBInfo->TVInfo & TVSimuMode ) ) )
+ temp &= ( ~0x0001 ) ;
+ }
+ }
+
+ XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x1F , 0x00C0 , temp ) ;
+ tempbx = pVBInfo->HT ;
+ if ( XGI_IsLCDDualLink( pVBInfo ) )
+ tempbx = tempbx >> 1 ;
+ tempbx = ( tempbx >> 1 ) - 2 ;
+ temp = ( ( tempbx & 0x0700 ) >> 8 ) << 3 ;
+ XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x21 , 0x00C0 , temp ) ;
+ temp = tempbx & 0x00FF ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x22 , temp ) ;
+ }
+ /* end 301b */
+
+ if ( pVBInfo->ISXPDOS == 0 )
+ XGI_SetCRT2VCLK( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetGroup5 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetGroup5( USHORT ModeNo , USHORT ModeIdIndex , PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT Pindex ,
+ Pdata ;
+
+ Pindex = pVBInfo->Part5Port ;
+ Pdata = pVBInfo->Part5Port + 1 ;
+ if ( pVBInfo->ModeType == ModeVGA )
+ {
+ if ( !( pVBInfo->VBInfo & ( SetInSlaveMode | LoadDACFlag | CRT2DisplayFlag ) ) )
+ {
+ XGINew_EnableCRT2(pVBInfo) ;
+ /* LoadDAC2(pVBInfo->Part5Port,ModeNo,ModeIdIndex); */
+ }
+ }
+ return ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetLcdPtr */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void* XGI_GetLcdPtr( USHORT BX , USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT i ,
+ tempdx ,
+ tempcx ,
+ tempbx ,
+ tempal ,
+ modeflag ,
+ table ;
+
+ XGI330_LCDDataTablStruct *tempdi = 0 ;
+
+
+ tempbx = BX;
+
+ if ( ModeNo <= 0x13 )
+ {
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+ tempal = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ;
+ }
+ else
+ {
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+ tempal = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT2CRTC ;
+ }
+
+ tempal = tempal & 0x0f ;
+
+ if ( tempbx <= 1 ) /* ExpLink */
+ {
+ if ( ModeNo <= 0x13 )
+ {
+ tempal = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ; /* find no Ext_CRT2CRTC2 */
+ }
+ else
+ {
+ tempal= pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT2CRTC ;
+ }
+
+ if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+ {
+ if ( ModeNo <= 0x13 )
+ tempal = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC2 ;
+ else
+ tempal= pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT2CRTC2 ;
+ }
+
+ if ( tempbx & 0x01 )
+ tempal = ( tempal >> 4 ) ;
+
+ tempal = ( tempal & 0x0f ) ;
+ }
+
+ tempcx = LCDLenList[ tempbx ] ; /* mov cl,byte ptr cs:LCDLenList[bx] */
+
+ if ( pVBInfo->LCDInfo & EnableScalingLCD ) /* ScaleLCD */
+ {
+ if ( ( tempbx == 5 ) || ( tempbx ) == 7 )
+ tempcx = LCDDesDataLen2 ;
+ else if ( ( tempbx == 3 ) || ( tempbx == 8 ) )
+ tempcx = LVDSDesDataLen2 ;
+ }
+ /* mov di, word ptr cs:LCDDataList[bx] */
+ /* tempdi=pVideoMemory[LCDDataList+tempbx*2]|(pVideoMemory[LCDDataList+tempbx*2+1]<<8); */
+
+ switch( tempbx )
+ {
+ case 0:
+ tempdi = XGI_EPLLCDCRT1Ptr_H ;
+ break ;
+ case 1:
+ tempdi = XGI_EPLLCDCRT1Ptr_V ;
+ break ;
+ case 2:
+ tempdi = XGI_EPLLCDDataPtr ;
+ break ;
+ case 3:
+ tempdi = XGI_EPLLCDDesDataPtr ;
+ break ;
+ case 4:
+ tempdi = XGI_LCDDataTable ;
+ break ;
+ case 5:
+ tempdi = XGI_LCDDesDataTable ;
+ break ;
+ case 6:
+ tempdi = XGI_EPLCHLCDRegPtr ;
+ break ;
+ case 7:
+ case 8:
+ case 9:
+ tempdi = 0 ;
+ break ;
+ default:
+ break ;
+ }
+
+ if ( tempdi == 0x00 ) /* OEMUtil */
+ return 0 ;
+
+ table = tempbx ;
+ i = 0 ;
+
+ while( tempdi[ i ].PANELID != 0xff )
+ {
+ tempdx = pVBInfo->LCDResInfo ;
+ if ( tempbx & 0x0080 ) /* OEMUtil */
+ {
+ tempbx &= ( ~0x0080 ) ;
+ tempdx = pVBInfo->LCDTypeInfo ;
+ }
+
+ if ( pVBInfo->LCDInfo & EnableScalingLCD )
+ tempdx &= ( ~PanelResInfo ) ;
+
+ if ( tempdi[ i ].PANELID == tempdx )
+ {
+ tempbx = tempdi[ i ].MASK ;
+ tempdx = pVBInfo->LCDInfo ;
+
+ if ( ModeNo <= 0x13 ) /* alan 09/10/2003 */
+ tempdx |= SetLCDStdMode ;
+
+ if ( modeflag & HalfDCLK )
+ tempdx |= SetLCDLowResolution ;
+
+ tempbx &= tempdx;
+ if ( tempbx == tempdi[ i ].CAP )
+ break ;
+ }
+ i++ ;
+ }
+
+ if ( table == 0 )
+ {
+ switch( tempdi[ i ].DATAPTR )
+ {
+ case 0:
+ return &XGI_LVDSCRT11024x768_1_H[ tempal ] ;
+ break ;
+ case 1:
+ return &XGI_LVDSCRT11024x768_2_H[ tempal ] ;
+ break ;
+ case 2:
+ return &XGI_LVDSCRT11280x1024_1_H[ tempal ] ;
+ break ;
+ case 3:
+ return &XGI_LVDSCRT11280x1024_2_H[ tempal ] ;
+ break ;
+ case 4:
+ return &XGI_LVDSCRT11400x1050_1_H[ tempal ] ;
+ break ;
+ case 5:
+ return &XGI_LVDSCRT11400x1050_2_H[ tempal ] ;
+ break ;
+ case 6:
+ return &XGI_LVDSCRT11600x1200_1_H[ tempal ] ;
+ break ;
+ case 7:
+ return &XGI_LVDSCRT11024x768_1_Hx75[ tempal ] ;
+ break ;
+ case 8:
+ return &XGI_LVDSCRT11024x768_2_Hx75[ tempal ] ;
+ break ;
+ case 9:
+ return &XGI_LVDSCRT11280x1024_1_Hx75[ tempal ] ;
+ break ;
+ case 10:
+ return &XGI_LVDSCRT11280x1024_2_Hx75[ tempal ] ;
+ break ;
+ default:
+ break ;
+ }
+ }
+ else if ( table == 1 )
+ {
+ switch( tempdi[ i ].DATAPTR )
+ {
+ case 0:
+ return &XGI_LVDSCRT11024x768_1_V[ tempal ] ;
+ break ;
+ case 1:
+ return &XGI_LVDSCRT11024x768_2_V[ tempal ] ;
+ break ;
+ case 2:
+ return &XGI_LVDSCRT11280x1024_1_V[ tempal ] ;
+ break ;
+ case 3:
+ return &XGI_LVDSCRT11280x1024_2_V[ tempal ] ;
+ break ;
+ case 4:
+ return &XGI_LVDSCRT11400x1050_1_V[ tempal ] ;
+ break ;
+ case 5:
+ return &XGI_LVDSCRT11400x1050_2_V[ tempal ] ;
+ break ;
+ case 6:
+ return &XGI_LVDSCRT11600x1200_1_V[ tempal ] ;
+ break ;
+ case 7:
+ return &XGI_LVDSCRT11024x768_1_Vx75[ tempal ] ;
+ break ;
+ case 8:
+ return &XGI_LVDSCRT11024x768_2_Vx75[ tempal ] ;
+ break ;
+ case 9:
+ return &XGI_LVDSCRT11280x1024_1_Vx75[ tempal ] ;
+ break ;
+ case 10:
+ return &XGI_LVDSCRT11280x1024_2_Vx75[ tempal ] ;
+ break ;
+ default:
+ break ;
+ }
+ }
+ else if ( table == 2 )
+ {
+ switch( tempdi[ i ].DATAPTR )
+ {
+ case 0:
+ return &XGI_LVDS1024x768Data_1[ tempal ] ;
+ break ;
+ case 1:
+ return &XGI_LVDS1024x768Data_2[ tempal ] ;
+ break ;
+ case 2:
+ return &XGI_LVDS1280x1024Data_1[ tempal ] ;
+ break ;
+ case 3:
+ return &XGI_LVDS1280x1024Data_2[ tempal ] ;
+ break ;
+ case 4:
+ return &XGI_LVDS1400x1050Data_1[ tempal ] ;
+ break ;
+ case 5:
+ return &XGI_LVDS1400x1050Data_2[ tempal ] ;
+ break ;
+ case 6:
+ return &XGI_LVDS1600x1200Data_1[ tempal ] ;
+ break ;
+ case 7:
+ return &XGI_LVDSNoScalingData[ tempal ] ;
+ break ;
+ case 8:
+ return &XGI_LVDS1024x768Data_1x75[ tempal ] ;
+ break ;
+ case 9:
+ return &XGI_LVDS1024x768Data_2x75[ tempal ] ;
+ break ;
+ case 10:
+ return &XGI_LVDS1280x1024Data_1x75[ tempal ] ;
+ break ;
+ case 11:
+ return &XGI_LVDS1280x1024Data_2x75[ tempal ] ;
+ break ;
+ case 12:
+ return &XGI_LVDSNoScalingDatax75[ tempal ] ;
+ break ;
+ default:
+ break ;
+ }
+ }
+ else if ( table == 3 )
+ {
+ switch( tempdi[ i ].DATAPTR )
+ {
+ case 0:
+ return &XGI_LVDS1024x768Des_1[ tempal ] ;
+ break ;
+ case 1:
+ return &XGI_LVDS1024x768Des_3[ tempal ] ;
+ break ;
+ case 2:
+ return &XGI_LVDS1024x768Des_2[ tempal ] ;
+ break ;
+ case 3:
+ return &XGI_LVDS1280x1024Des_1[ tempal ] ;
+ break ;
+ case 4:
+ return &XGI_LVDS1280x1024Des_2[ tempal ] ;
+ break ;
+ case 5:
+ return &XGI_LVDS1400x1050Des_1[ tempal ] ;
+ break ;
+ case 6:
+ return &XGI_LVDS1400x1050Des_2[ tempal ] ;
+ break ;
+ case 7:
+ return &XGI_LVDS1600x1200Des_1[ tempal ] ;
+ break ;
+ case 8:
+ return &XGI_LVDSNoScalingDesData[ tempal ] ;
+ break ;
+ case 9:
+ return &XGI_LVDS1024x768Des_1x75[ tempal ] ;
+ break ;
+ case 10:
+ return &XGI_LVDS1024x768Des_3x75[ tempal ] ;
+ break ;
+ case 11:
+ return &XGI_LVDS1024x768Des_2x75[ tempal ] ;
+ break;
+ case 12:
+ return &XGI_LVDS1280x1024Des_1x75[ tempal ] ;
+ break ;
+ case 13:
+ return &XGI_LVDS1280x1024Des_2x75[ tempal ] ;
+ break ;
+ case 14:
+ return &XGI_LVDSNoScalingDesDatax75[ tempal ] ;
+ break ;
+ default:
+ break ;
+ }
+ }
+ else if ( table == 4 )
+ {
+ switch( tempdi[ i ].DATAPTR )
+ {
+ case 0:
+ return &XGI_ExtLCD1024x768Data[ tempal ] ;
+ break ;
+ case 1:
+ return &XGI_StLCD1024x768Data[ tempal ] ;
+ break ;
+ case 2:
+ return &XGI_CetLCD1024x768Data[ tempal ] ;
+ break ;
+ case 3:
+ return &XGI_ExtLCD1280x1024Data[ tempal ] ;
+ break ;
+ case 4:
+ return &XGI_StLCD1280x1024Data[ tempal ] ;
+ break ;
+ case 5:
+ return &XGI_CetLCD1280x1024Data[ tempal ] ;
+ break ;
+ case 6:
+ return &XGI_ExtLCD1400x1050Data[ tempal ] ;
+ break ;
+ case 7:
+ return &XGI_StLCD1400x1050Data[ tempal ] ;
+ break ;
+ case 8:
+ return &XGI_CetLCD1400x1050Data[ tempal ] ;
+ break ;
+ case 9:
+ return &XGI_ExtLCD1600x1200Data[ tempal ] ;
+ break ;
+ case 10:
+ return &XGI_StLCD1600x1200Data[ tempal ] ;
+ break ;
+ case 11:
+ return &XGI_NoScalingData[ tempal ] ;
+ break ;
+ case 12:
+ return &XGI_ExtLCD1024x768x75Data[ tempal ] ;
+ break ;
+ case 13:
+ return &XGI_ExtLCD1024x768x75Data[ tempal ] ;
+ break ;
+ case 14:
+ return &XGI_CetLCD1024x768x75Data[ tempal ] ;
+ break ;
+ case 15:
+ return &XGI_ExtLCD1280x1024x75Data[ tempal ] ;
+ break ;
+ case 16:
+ return &XGI_StLCD1280x1024x75Data[ tempal ] ;
+ break;
+ case 17:
+ return &XGI_CetLCD1280x1024x75Data[ tempal ] ;
+ break;
+ case 18:
+ return &XGI_NoScalingDatax75[ tempal ] ;
+ break ;
+ default:
+ break ;
+ }
+ }
+ else if ( table == 5 )
+ {
+ switch( tempdi[ i ].DATAPTR )
+ {
+ case 0:
+ return &XGI_ExtLCDDes1024x768Data[ tempal ] ;
+ break ;
+ case 1:
+ return &XGI_StLCDDes1024x768Data[ tempal ] ;
+ break ;
+ case 2:
+ return &XGI_CetLCDDes1024x768Data[ tempal ] ;
+ break ;
+ case 3:
+ if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
+ return &XGI_ExtLCDDLDes1280x1024Data[ tempal ] ;
+ else
+ return &XGI_ExtLCDDes1280x1024Data[ tempal ] ;
+ break ;
+ case 4:
+ if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
+ return &XGI_StLCDDLDes1280x1024Data[ tempal ] ;
+ else
+ return &XGI_StLCDDes1280x1024Data[ tempal ] ;
+ break ;
+ case 5:
+ if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
+ return &XGI_CetLCDDLDes1280x1024Data[ tempal ] ;
+ else
+ return &XGI_CetLCDDes1280x1024Data[ tempal ] ;
+ break ;
+ case 6:
+ if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
+ return &XGI_ExtLCDDLDes1400x1050Data[ tempal ] ;
+ else
+ return &XGI_ExtLCDDes1400x1050Data[ tempal ] ;
+ break ;
+ case 7:
+ if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
+ return &XGI_StLCDDLDes1400x1050Data[ tempal ] ;
+ else
+ return &XGI_StLCDDes1400x1050Data[ tempal ] ;
+ break ;
+ case 8:
+ return &XGI_CetLCDDes1400x1050Data[ tempal ] ;
+ break ;
+ case 9:
+ return &XGI_CetLCDDes1400x1050Data2[ tempal ] ;
+ break ;
+ case 10:
+ if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
+ return &XGI_ExtLCDDLDes1600x1200Data[ tempal ] ;
+ else
+ return &XGI_ExtLCDDes1600x1200Data[ tempal ] ;
+ break ;
+ case 11:
+ if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
+ return &XGI_StLCDDLDes1600x1200Data[ tempal ] ;
+ else
+ return &XGI_StLCDDes1600x1200Data[ tempal ] ;
+ break ;
+ case 12:
+ return &XGI_NoScalingDesData[ tempal ] ;
+ break;
+ case 13:
+ return &XGI_ExtLCDDes1024x768x75Data[ tempal ] ;
+ break ;
+ case 14:
+ return &XGI_StLCDDes1024x768x75Data[ tempal ] ;
+ break ;
+ case 15:
+ return &XGI_CetLCDDes1024x768x75Data[ tempal ] ;
+ break ;
+ case 16:
+ if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
+ return &XGI_ExtLCDDLDes1280x1024x75Data[ tempal ] ;
+ else
+ return &XGI_ExtLCDDes1280x1024x75Data[ tempal ] ;
+ break ;
+ case 17:
+ if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
+ return &XGI_StLCDDLDes1280x1024x75Data[ tempal ] ;
+ else
+ return &XGI_StLCDDes1280x1024x75Data[ tempal ] ;
+ break ;
+ case 18:
+ if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
+ return &XGI_CetLCDDLDes1280x1024x75Data[ tempal ] ;
+ else
+ return &XGI_CetLCDDes1280x1024x75Data[ tempal ] ;
+ break ;
+ case 19:
+ return &XGI_NoScalingDesDatax75[ tempal ] ;
+ break ;
+ default:
+ break ;
+ }
+ }
+ else if ( table == 6 )
+ {
+ switch( tempdi[ i ].DATAPTR )
+ {
+ case 0:
+ return &XGI_CH7017LV1024x768[ tempal ] ;
+ break ;
+ case 1:
+ return &XGI_CH7017LV1400x1050[ tempal ] ;
+ break ;
+ default:
+ break ;
+ }
+ }
+ return 0 ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetTVPtr */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void* XGI_GetTVPtr (USHORT BX,USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT i , tempdx , tempbx , tempal , modeflag , table ;
+ XGI330_TVDataTablStruct *tempdi = 0 ;
+
+ tempbx = BX ;
+
+ if ( ModeNo <= 0x13 )
+ {
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+ tempal = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ;
+ }
+ else
+ {
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+ tempal = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT2CRTC ;
+ }
+
+ tempal = tempal & 0x3f ;
+ table = tempbx ;
+
+ switch( tempbx )
+ {
+ case 0:
+ tempdi = 0 ; /*EPLCHTVCRT1Ptr_H;*/
+ if ( pVBInfo->IF_DEF_CH7007 == 1 )
+ {
+ tempdi = XGI_EPLCHTVCRT1Ptr;
+ }
+ break ;
+ case 1:
+ tempdi = 0 ; /*EPLCHTVCRT1Ptr_V;*/
+ if ( pVBInfo->IF_DEF_CH7007 == 1 )
+ {
+ tempdi = XGI_EPLCHTVCRT1Ptr;
+ }
+ break ;
+ case 2:
+ tempdi = XGI_EPLCHTVDataPtr ;
+ break ;
+ case 3:
+ tempdi = 0 ;
+ break ;
+ case 4:
+ tempdi = XGI_TVDataTable ;
+ break ;
+ case 5:
+ tempdi = 0 ;
+ break ;
+ case 6:
+ tempdi = XGI_EPLCHTVRegPtr ;
+ break ;
+ default:
+ break ;
+ }
+
+ if ( tempdi == 0x00 ) /* OEMUtil */
+ return( 0 ) ;
+
+ tempdx = pVBInfo->TVInfo ;
+
+ if ( pVBInfo->VBInfo & SetInSlaveMode )
+ tempdx = tempdx | SetTVLockMode ;
+
+ if ( modeflag & HalfDCLK )
+ tempdx = tempdx | SetTVLowResolution ;
+
+ i = 0 ;
+
+ while( tempdi[ i ].MASK != 0xffff )
+ {
+ if ( ( tempdx & tempdi[ i ].MASK ) == tempdi[ i ].CAP )
+ break ;
+ i++ ;
+ }
+
+ if ( table == 0x00 ) /* 07/05/22 */
+ {
+#ifdef WIN2000
+ if ( pVBInfo->IF_DEF_CH7007 == 1 )
+ {
+ switch( tempdi[ i ].DATAPTR )
+ {
+ case 0:
+ return &CH7007TVCRT1UNTSC_H[ tempal ] ;
+ break ;
+ case 1:
+ return &CH7007TVCRT1ONTSC_H[ tempal ] ;
+ break ;
+ case 2:
+ return &CH7007TVCRT1UPAL_H[ tempal ] ;
+ break ;
+ case 3:
+ return &CH7007TVCRT1OPAL_H[ tempal ] ;
+ break ;
+ default:
+ break ;
+ }
+ }
+#endif
+ }
+ else if ( table == 0x01 )
+ {
+#ifdef WIN2000
+ if ( pVBInfo->IF_DEF_CH7007 == 1 )
+ {
+ switch( tempdi[ i ].DATAPTR )
+ {
+ case 0:
+ return &CH7007TVCRT1UNTSC_V[ tempal ] ;
+ break ;
+ case 1:
+ return &CH7007TVCRT1ONTSC_V[ tempal ] ;
+ break ;
+ case 2:
+ return &CH7007TVCRT1UPAL_V[ tempal ] ;
+ break ;
+ case 3:
+ return &CH7007TVCRT1OPAL_V[ tempal ] ;
+ break ;
+ default:
+ break ;
+ }
+ }
+#endif
+ }
+ else if ( table == 0x04 )
+ {
+ switch( tempdi[ i ].DATAPTR )
+ {
+ case 0:
+ return &XGI_ExtPALData[ tempal ] ;
+ break ;
+ case 1:
+ return &XGI_ExtNTSCData[ tempal ] ;
+ break ;
+ case 2:
+ return &XGI_StPALData[ tempal ] ;
+ break ;
+ case 3:
+ return &XGI_StNTSCData[ tempal ] ;
+ break ;
+ case 4:
+ return &XGI_ExtHiTVData[ tempal ] ;
+ break ;
+ case 5:
+ return &XGI_St2HiTVData[ tempal ] ;
+ break ;
+ case 6:
+ return &XGI_ExtYPbPr525iData[ tempal ] ;
+ break ;
+ case 7:
+ return &XGI_ExtYPbPr525pData[ tempal ] ;
+ break ;
+ case 8:
+ return &XGI_ExtYPbPr750pData[ tempal ] ;
+ break ;
+ case 9:
+ return &XGI_StYPbPr525iData[ tempal ] ;
+ break ;
+ case 10:
+ return &XGI_StYPbPr525pData[ tempal ] ;
+ break ;
+ case 11:
+ return &XGI_StYPbPr750pData[ tempal ] ;
+ break;
+ case 12: /* avoid system hang */
+ return &XGI_ExtNTSCData[ tempal ] ;
+ break ;
+ case 13:
+ return &XGI_St1HiTVData[ tempal ] ;
+ break ;
+ default:
+ break ;
+ }
+ }
+ else if( table == 0x02 )
+ {
+ switch( tempdi[ i ].DATAPTR )
+ {
+ case 0:
+ return &XGI_CHTVUNTSCData[ tempal ] ;
+ break ;
+ case 1:
+ return &XGI_CHTVONTSCData[ tempal ] ;
+ break ;
+ case 2:
+ return &XGI_CHTVUPALData[ tempal ] ;
+ break ;
+ case 3:
+ return &XGI_CHTVOPALData[ tempal ] ;
+ break ;
+ default:
+ break ;
+ }
+ }
+ else if( table == 0x06 )
+ {
+#ifdef WIN2000
+ if ( pVBInfo->IF_DEF_CH7007 == 1 )
+ {
+ /* VideoDebugPrint((0, "XGI_GetTVPtr: pVBInfo->IF_DEF_CH7007==1\n")); */
+ switch( tempdi[ i ].DATAPTR )
+ {
+ case 0:
+ return &CH7007TVReg_UNTSC[ tempal ] ;
+ break ;
+ case 1:
+ return &CH7007TVReg_ONTSC[ tempal ] ;
+ break ;
+ case 2:
+ return &CH7007TVReg_UPAL[ tempal ] ;
+ break ;
+ case 3:
+ return &CH7007TVReg_OPAL[ tempal ] ;
+ break ;
+ default:
+ break ;
+ }
+ }
+ else
+ {
+ switch( tempdi[ i ].DATAPTR )
+ {
+ case 0:
+ return &XGI_CHTVRegUNTSC[ tempal ] ;
+ break ;
+ case 1:
+ return &XGI_CHTVRegONTSC[ tempal ] ;
+ break ;
+ case 2:
+ return &XGI_CHTVRegUPAL[ tempal ] ;
+ break ;
+ case 3:
+ return &XGI_CHTVRegOPAL[ tempal ] ;
+ break ;
+ default:
+ break ;
+ }
+ }
+#endif
+ }
+ return( 0 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_BacklightByDrv */
+/* Input : */
+/* Output : TRUE -> Skip backlight control */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_BacklightByDrv( PVB_DEVICE_INFO pVBInfo )
+{
+ UCHAR tempah ;
+
+ tempah = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x3A ) ;
+ if ( tempah & BacklightControlBit )
+ return TRUE ;
+ else
+ return FALSE ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_FirePWDDisable */
+/* Input : */
+/* Output : */
+/* Description : Turn off VDD & Backlight : Fire disable procedure */
+/* --------------------------------------------------------------------- */
+/*
+void XGI_FirePWDDisable( PVB_DEVICE_INFO pVBInfo )
+{
+ XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x26 , 0x00 , 0xFC ) ;
+}
+*/
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_FirePWDEnable */
+/* Input : */
+/* Output : */
+/* Description : Turn on VDD & Backlight : Fire enable procedure */
+/* --------------------------------------------------------------------- */
+void XGI_FirePWDEnable(PVB_DEVICE_INFO pVBInfo )
+{
+ XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x26 , 0x03 , 0xFC ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_EnableGatingCRT */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_EnableGatingCRT(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+{
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x63 , 0xBF , 0x40 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_DisableGatingCRT */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_DisableGatingCRT(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+{
+
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x63 , 0xBF , 0x00 ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetPanelDelay */
+/* Input : */
+/* Output : */
+/* Description : */
+/* I/P : bl : 1 ; T1 : the duration between CPL on and signal on */
+/* : bl : 2 ; T2 : the duration signal on and Vdd on */
+/* : bl : 3 ; T3 : the duration between CPL off and signal off */
+/* : bl : 4 ; T4 : the duration signal off and Vdd off */
+/* --------------------------------------------------------------------- */
+void XGI_SetPanelDelay(USHORT tempbl, PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT index ;
+
+ index = XGI_GetLCDCapPtr(pVBInfo) ;
+
+ if ( tempbl == 1 )
+ XGINew_LCD_Wait_Time( pVBInfo->LCDCapList[ index ].PSC_S1, pVBInfo ) ;
+
+ if ( tempbl == 2 )
+ XGINew_LCD_Wait_Time( pVBInfo->LCDCapList[ index ].PSC_S2, pVBInfo ) ;
+
+ if ( tempbl == 3 )
+ XGINew_LCD_Wait_Time( pVBInfo->LCDCapList[ index ].PSC_S3, pVBInfo ) ;
+
+ if ( tempbl == 4 )
+ XGINew_LCD_Wait_Time( pVBInfo->LCDCapList[ index ].PSC_S4, pVBInfo ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetPanelPower */
+/* Input : */
+/* Output : */
+/* Description : */
+/* I/O : ah = 0011b = 03h ; Backlight on, Power on */
+/* = 0111b = 07h ; Backlight on, Power off */
+/* = 1011b = 0Bh ; Backlight off, Power on */
+/* = 1111b = 0Fh ; Backlight off, Power off */
+/* --------------------------------------------------------------------- */
+void XGI_SetPanelPower(USHORT tempah,USHORT tempbl, PVB_DEVICE_INFO pVBInfo)
+{
+ if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x26 , tempbl , tempah ) ;
+ else
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x11 , tempbl , tempah ) ;
+}
+
+UCHAR XG21GPIODataTransfer(UCHAR ujDate)
+{
+ UCHAR ujRet = 0;
+ UCHAR i = 0;
+
+ for (i=0; i<8; i++)
+ {
+ ujRet = ujRet << 1;
+ /* ujRet |= GETBITS(ujDate >> i, 0:0); */
+ ujRet |= (ujDate >> i) & 1;
+ }
+
+ return ujRet;
+}
+
+/*----------------------------------------------------------------------------*/
+/* output */
+/* bl[5] : LVDS signal */
+/* bl[1] : LVDS backlight */
+/* bl[0] : LVDS VDD */
+/*----------------------------------------------------------------------------*/
+UCHAR XGI_XG21GetPSCValue(PVB_DEVICE_INFO pVBInfo)
+{
+ UCHAR CR4A,temp;
+
+ CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
+ XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x23 ) ; /* enable GPIO write */
+
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) ;
+
+ temp = XG21GPIODataTransfer(temp);
+ temp &= 0x23;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x4A , CR4A ) ;
+ return temp;
+}
+
+/*----------------------------------------------------------------------------*/
+/* output */
+/* bl[5] : LVDS signal */
+/* bl[1] : LVDS backlight */
+/* bl[0] : LVDS VDD */
+/*----------------------------------------------------------------------------*/
+UCHAR XGI_XG27GetPSCValue(PVB_DEVICE_INFO pVBInfo)
+{
+ UCHAR CR4A,CRB4,temp;
+
+ CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
+ XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x0C ) ; /* enable GPIO write */
+
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) ;
+
+ temp &= 0x0C;
+ temp >>= 2;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x4A , CR4A ) ;
+ CRB4 = XGINew_GetReg1( pVBInfo->P3d4 , 0xB4 ) ;
+ temp |= ((CRB4&0x04)<<3);
+ return temp;
+}
+/*----------------------------------------------------------------------------*/
+/* input */
+/* bl[5] : 1;LVDS signal on */
+/* bl[1] : 1;LVDS backlight on */
+/* bl[0] : 1:LVDS VDD on */
+/* bh: 100000b : clear bit 5, to set bit5 */
+/* 000010b : clear bit 1, to set bit1 */
+/* 000001b : clear bit 0, to set bit0 */
+/*----------------------------------------------------------------------------*/
+void XGI_XG21BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo)
+{
+ UCHAR CR4A,temp;
+
+ CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
+ tempbh &= 0x23;
+ tempbl &= 0x23;
+ XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~tempbh ) ; /* enable GPIO write */
+
+ if (tempbh&0x20)
+ {
+ temp = (tempbl>>4)&0x02;
+
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0xB4 , ~0x02 , temp) ; /* CR B4[1] */
+
+ }
+
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) ;
+
+ temp = XG21GPIODataTransfer(temp);
+ temp &= ~tempbh;
+ temp |= tempbl;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x48 , temp ) ;
+}
+
+void XGI_XG27BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo)
+{
+ UCHAR CR4A,temp;
+ USHORT tempbh0,tempbl0;
+
+ tempbh0 = tempbh;
+ tempbl0 = tempbl;
+ tempbh0 &= 0x20;
+ tempbl0 &= 0x20;
+ tempbh0 >>= 3;
+ tempbl0 >>= 3;
+
+ if (tempbh&0x20)
+ {
+ temp = (tempbl>>4)&0x02;
+
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0xB4 , ~0x02 , temp) ; /* CR B4[1] */
+
+ }
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0xB4 , ~tempbh0 , tempbl0 ) ;
+
+ CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
+ tempbh &= 0x03;
+ tempbl &= 0x03;
+ tempbh <<= 2;
+ tempbl <<= 2; /* GPIOC,GPIOD */
+ XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~tempbh ) ; /* enable GPIO write */
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x48 , ~tempbh , tempbl ) ;
+}
+
+/* --------------------------------------------------------------------- */
+USHORT XGI_GetLVDSOEMTableIndex(PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT index ;
+
+ index = XGINew_GetReg1( pVBInfo->P3d4 , 0x36 ) ;
+ if (index<sizeof(XGI21_LCDCapList)/sizeof(XGI21_LVDSCapStruct))
+ {
+ return index;
+ }
+ return 0;
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_XG21SetPanelDelay */
+/* Input : */
+/* Output : */
+/* Description : */
+/* I/P : bl : 1 ; T1 : the duration between CPL on and signal on */
+/* : bl : 2 ; T2 : the duration signal on and Vdd on */
+/* : bl : 3 ; T3 : the duration between CPL off and signal off */
+/* : bl : 4 ; T4 : the duration signal off and Vdd off */
+/* --------------------------------------------------------------------- */
+void XGI_XG21SetPanelDelay(USHORT tempbl, PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT index ;
+
+ index = XGI_GetLVDSOEMTableIndex( pVBInfo );
+ if ( tempbl == 1 )
+ XGINew_LCD_Wait_Time( pVBInfo->XG21_LVDSCapList[ index ].PSC_S1, pVBInfo ) ;
+
+ if ( tempbl == 2 )
+ XGINew_LCD_Wait_Time( pVBInfo->XG21_LVDSCapList[ index ].PSC_S2, pVBInfo ) ;
+
+ if ( tempbl == 3 )
+ XGINew_LCD_Wait_Time( pVBInfo->XG21_LVDSCapList[ index ].PSC_S3, pVBInfo ) ;
+
+ if ( tempbl == 4 )
+ XGINew_LCD_Wait_Time( pVBInfo->XG21_LVDSCapList[ index ].PSC_S4, pVBInfo ) ;
+}
+
+BOOLEAN XGI_XG21CheckLVDSMode(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT xres ,
+ yres ,
+ colordepth ,
+ modeflag ,
+ resindex ,
+ lvdstableindex;
+
+ resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
+ if ( ModeNo <= 0x13 )
+ {
+ xres = pVBInfo->StResInfo[ resindex ].HTotal ;
+ yres = pVBInfo->StResInfo[ resindex ].VTotal ;
+ modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
+ }
+ else
+ {
+ xres = pVBInfo->ModeResInfo[ resindex ].HTotal ; /* xres->ax */
+ yres = pVBInfo->ModeResInfo[ resindex ].VTotal ; /* yres->bx */
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex].Ext_ModeFlag ; /* si+St_ModeFlag */
+ }
+
+ if ( !( modeflag & Charx8Dot ) )
+ {
+ xres /= 9;
+ xres *= 8;
+ }
+
+ if ( ModeNo > 0x13 )
+ {
+ if ( ( ModeNo>0x13 ) && ( modeflag & HalfDCLK ) )
+ {
+ xres *= 2 ;
+ }
+ if ( ( ModeNo>0x13 ) && ( modeflag & DoubleScanMode ) )
+ {
+ yres *= 2 ;
+ }
+ }
+
+ lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo );
+ if ( xres > (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE) )
+ return FALSE;
+
+ if ( yres > (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE) )
+ return FALSE;
+
+ if ( ModeNo > 0x13 )
+ {
+ if ( ( xres != (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE) ) ||
+ ( yres != (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE)) )
+ {
+ colordepth = XGI_GetColorDepth( ModeNo , ModeIdIndex, pVBInfo ) ;
+ if ( colordepth > 2 )
+ {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+void XGI_SetXG21FPBits(PVB_DEVICE_INFO pVBInfo)
+{
+ UCHAR temp;
+
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x37 ) ; /* D[0] 1: 18bit */
+ temp = ( temp & 1 ) << 6;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x06 , ~0x40 , temp ) ; /* SR06[6] 18bit Dither */
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x09 , ~0xc0 , temp | 0x80 ) ; /* SR09[7] enable FP output, SR09[6] 1: sigle 18bits, 0: dual 12bits */
+
+}
+
+void XGI_SetXG27FPBits(PVB_DEVICE_INFO pVBInfo)
+{
+ UCHAR temp;
+
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x37 ) ; /* D[1:0] 01: 18bit, 00: dual 12, 10: single 24 */
+ temp = ( temp & 3 ) << 6;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x06 , ~0xc0 , temp & 0x80 ) ; /* SR06[7]0: dual 12/1: single 24 [6] 18bit Dither <= 0 h/w recommend */
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x09 , ~0xc0 , temp | 0x80 ) ; /* SR09[7] enable FP output, SR09[6] 1: sigle 18bits, 0: 24bits */
+
+}
+
+void XGI_SetXG21LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ UCHAR temp,Miscdata;
+ USHORT xres ,
+ yres ,
+ modeflag ,
+ resindex ,
+ lvdstableindex ;
+ USHORT LVDSHT,LVDSHBS,LVDSHRS,LVDSHRE,LVDSHBE;
+ USHORT LVDSVT,LVDSVBS,LVDSVRS,LVDSVRE,LVDSVBE;
+ USHORT value;
+
+ lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo );
+
+ temp = (UCHAR) ( ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability & (LCDPolarity << 8 ) ) >> 8 );
+ temp &= LCDPolarity;
+ Miscdata =(UCHAR) XGINew_GetReg2(pVBInfo->P3cc) ;
+
+ XGINew_SetReg3( pVBInfo->P3c2 , (Miscdata & 0x3F) | temp ) ;
+
+ temp = (UCHAR) ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability & LCDPolarity ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x80 , temp&0x80 ) ; /* SR35[7] FP VSync polarity */
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , ~0x20 , (temp&0x40)>>1 ) ; /* SR30[5] FP HSync polarity */
+
+ XGI_SetXG21FPBits(pVBInfo);
+ resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
+ if ( ModeNo <= 0x13 )
+ {
+ xres = pVBInfo->StResInfo[ resindex ].HTotal ;
+ yres = pVBInfo->StResInfo[ resindex ].VTotal ;
+ modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
+ }
+ else
+ {
+ xres = pVBInfo->ModeResInfo[ resindex ].HTotal ; /* xres->ax */
+ yres = pVBInfo->ModeResInfo[ resindex ].VTotal ; /* yres->bx */
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex].Ext_ModeFlag ; /* si+St_ModeFlag */
+ }
+
+ if (!( modeflag & Charx8Dot ))
+ xres = xres * 8 / 9;
+
+ LVDSHT = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHT;
+
+ LVDSHBS = xres + ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE - xres ) / 2 ;
+ if ( ( ModeNo<=0x13 ) && ( modeflag & HalfDCLK ) )
+ {
+ LVDSHBS -= xres/4 ;
+ }
+ if (LVDSHBS > LVDSHT) LVDSHBS -= LVDSHT ;
+
+ LVDSHRS = LVDSHBS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHFP ;
+ if (LVDSHRS > LVDSHT) LVDSHRS -= LVDSHT ;
+
+ LVDSHRE = LVDSHRS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHSYNC ;
+ if (LVDSHRE > LVDSHT) LVDSHRE -= LVDSHT ;
+
+ LVDSHBE = LVDSHBS + LVDSHT - pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE ;
+
+ LVDSVT = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVT;
+
+ LVDSVBS = yres + ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE - yres ) / 2 ;
+ if ( ( ModeNo>0x13 ) && ( modeflag & DoubleScanMode ) )
+ {
+ LVDSVBS += yres/2 ;
+ }
+ if (LVDSVBS > LVDSVT) LVDSVBS -= LVDSVT ;
+
+ LVDSVRS = LVDSVBS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVFP ;
+ if (LVDSVRS > LVDSVT) LVDSVRS -= LVDSVT ;
+
+ LVDSVRE = LVDSVRS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVSYNC ;
+ if (LVDSVRE > LVDSVT) LVDSVRE -= LVDSVT ;
+
+ LVDSVBE = LVDSVBS + LVDSVT - pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE ;
+
+ temp = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , temp & 0x7f ) ; /* Unlock CRTC */
+
+ if (!( modeflag & Charx8Dot ))
+ {
+ XGINew_SetRegOR( pVBInfo->P3c4 , 0x1 , 0x1 ) ;
+ }
+
+ /* HT SR0B[1:0] CR00 */
+ value = ( LVDSHT >> 3 ) - 5;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0B , ~0x03 , ( value & 0x300 ) >> 8 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x0 , (value & 0xFF) ) ;
+
+ /* HBS SR0B[5:4] CR02 */
+ value = ( LVDSHBS >> 3 ) - 1;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0B , ~0x30 , ( value & 0x300 ) >> 4 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x2 , (value & 0xFF) ) ;
+
+ /* HBE SR0C[1:0] CR05[7] CR03[4:0] */
+ value = ( LVDSHBE >> 3 ) - 1;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0C , ~0x03 , ( value & 0xC0 ) >> 6 ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x05 , ~0x80 , ( value & 0x20 ) << 2 ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x03 , ~0x1F , value & 0x1F ) ;
+
+ /* HRS SR0B[7:6] CR04 */
+ value = ( LVDSHRS >> 3 ) + 2;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0B , ~0xC0 , ( value & 0x300 ) >> 2 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x4 , (value & 0xFF) ) ;
+
+ /* Panel HRS SR2F[1:0] SR2E[7:0] */
+ value--;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x2F , ~0x03 , ( value & 0x300 ) >> 8 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , (value & 0xFF) ) ;
+
+ /* HRE SR0C[2] CR05[4:0] */
+ value = ( LVDSHRE >> 3 ) + 2;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0C , ~0x04 , ( value & 0x20 ) >> 3 ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x05 , ~0x1F , value & 0x1F ) ;
+
+ /* Panel HRE SR2F[7:2] */
+ value--;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x2F , ~0xFC , value << 2 ) ;
+
+ /* VT SR0A[0] CR07[5][0] CR06 */
+ value = LVDSVT - 2 ;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x01 , ( value & 0x400 ) >> 10 ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x20 , ( value & 0x200 ) >> 4 ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x01 , ( value & 0x100 ) >> 8 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x06 , (value & 0xFF) ) ;
+
+ /* VBS SR0A[2] CR09[5] CR07[3] CR15 */
+ value = LVDSVBS - 1 ;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x04 , ( value & 0x400 ) >> 8 ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x09 , ~0x20 , ( value & 0x200 ) >> 4 ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x08 , ( value & 0x100 ) >> 5 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x15 , (value & 0xFF) ) ;
+
+ /* VBE SR0A[4] CR16 */
+ value = LVDSVBE - 1;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x10 , ( value & 0x100 ) >> 4 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x16 , (value & 0xFF) ) ;
+
+ /* VRS SR0A[3] CR7[7][2] CR10 */
+ value = LVDSVRS - 1 ;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x08 , ( value & 0x400 ) >> 7 ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x80 , ( value & 0x200 ) >> 2 ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x04 , ( value & 0x100 ) >> 6 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x10 , (value & 0xFF) ) ;
+
+ /* Panel VRS SR3F[1:0] SR34[7:0] SR33[0] */
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x3F , ~0x03 , ( value & 0x600 ) >> 9 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , (value >> 1) & 0xFF ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x33 , ~0x01 , value & 0x01 ) ;
+
+ /* VRE SR0A[5] CR11[3:0] */
+ value = LVDSVRE - 1;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x20 , ( value & 0x10 ) << 1 ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x11 , ~0x0F , value & 0x0F ) ;
+
+ /* Panel VRE SR3F[7:2] */ /* SR3F[7] has to be 0, h/w bug */
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x3F , ~0xFC , ( value << 2 ) & 0x7C ) ;
+
+ for ( temp=0, value = 0; temp < 3; temp++)
+ {
+
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x31 , ~0x30 , value ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData1) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData2) ;
+ value += 0x10;
+ }
+
+ if (!( modeflag & Charx8Dot ))
+ {
+ XGINew_GetReg2( pVBInfo->P3da ) ; /* reset 3da */
+ XGINew_SetReg3( pVBInfo->P3c0 , 0x13 ) ; /* set index */
+ XGINew_SetReg3( pVBInfo->P3c0 , 0x00 ) ; /* set data, panning = 0, shift left 1 dot*/
+
+ XGINew_GetReg2( pVBInfo->P3da ) ; /* Enable Attribute */
+ XGINew_SetReg3( pVBInfo->P3c0 , 0x20 ) ;
+
+ XGINew_GetReg2( pVBInfo->P3da ) ; /* reset 3da */
+ }
+
+
+}
+
+/* no shadow case */
+void XGI_SetXG27LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ UCHAR temp,Miscdata;
+ USHORT xres ,
+ yres ,
+ modeflag ,
+ resindex ,
+ lvdstableindex ;
+ USHORT LVDSHT,LVDSHBS,LVDSHRS,LVDSHRE,LVDSHBE;
+ USHORT LVDSVT,LVDSVBS,LVDSVRS,LVDSVRE,LVDSVBE;
+ USHORT value;
+
+ lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo );
+ temp = (UCHAR) ( ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability & (LCDPolarity << 8 ) ) >> 8 );
+ temp &= LCDPolarity;
+ Miscdata =(UCHAR) XGINew_GetReg2(pVBInfo->P3cc) ;
+
+ XGINew_SetReg3( pVBInfo->P3c2 , (Miscdata & 0x3F) | temp ) ;
+
+ temp = (UCHAR) ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability & LCDPolarity ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x80 , temp&0x80 ) ; /* SR35[7] FP VSync polarity */
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , ~0x20 , (temp&0x40)>>1 ) ; /* SR30[5] FP HSync polarity */
+
+ XGI_SetXG27FPBits(pVBInfo);
+ resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
+ if ( ModeNo <= 0x13 )
+ {
+ xres = pVBInfo->StResInfo[ resindex ].HTotal ;
+ yres = pVBInfo->StResInfo[ resindex ].VTotal ;
+ modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
+ }
+ else
+ {
+ xres = pVBInfo->ModeResInfo[ resindex ].HTotal ; /* xres->ax */
+ yres = pVBInfo->ModeResInfo[ resindex ].VTotal ; /* yres->bx */
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex].Ext_ModeFlag ; /* si+St_ModeFlag */
+ }
+
+ if (!( modeflag & Charx8Dot ))
+ xres = xres * 8 / 9;
+
+ LVDSHT = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHT;
+
+ LVDSHBS = xres + ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE - xres ) / 2 ;
+ if ( ( ModeNo<=0x13 ) && ( modeflag & HalfDCLK ) )
+ {
+ LVDSHBS -= xres/4 ;
+ }
+ if (LVDSHBS > LVDSHT) LVDSHBS -= LVDSHT ;
+
+ LVDSHRS = LVDSHBS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHFP ;
+ if (LVDSHRS > LVDSHT) LVDSHRS -= LVDSHT ;
+
+ LVDSHRE = LVDSHRS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHSYNC ;
+ if (LVDSHRE > LVDSHT) LVDSHRE -= LVDSHT ;
+
+ LVDSHBE = LVDSHBS + LVDSHT - pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE ;
+
+ LVDSVT = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVT;
+
+ LVDSVBS = yres + ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE - yres ) / 2 ;
+ if ( ( ModeNo>0x13 ) && ( modeflag & DoubleScanMode ) )
+ {
+ LVDSVBS += yres/2 ;
+ }
+ if (LVDSVBS > LVDSVT) LVDSVBS -= LVDSVT ;
+
+ LVDSVRS = LVDSVBS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVFP ;
+ if (LVDSVRS > LVDSVT) LVDSVRS -= LVDSVT ;
+
+ LVDSVRE = LVDSVRS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVSYNC ;
+ if (LVDSVRE > LVDSVT) LVDSVRE -= LVDSVT ;
+
+ LVDSVBE = LVDSVBS + LVDSVT - pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE ;
+
+ temp = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , temp & 0x7f ) ; /* Unlock CRTC */
+
+ if (!( modeflag & Charx8Dot ))
+ {
+ XGINew_SetRegOR( pVBInfo->P3c4 , 0x1 , 0x1 ) ;
+ }
+
+ /* HT SR0B[1:0] CR00 */
+ value = ( LVDSHT >> 3 ) - 5;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0B , ~0x03 , ( value & 0x300 ) >> 8 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x0 , (value & 0xFF) ) ;
+
+ /* HBS SR0B[5:4] CR02 */
+ value = ( LVDSHBS >> 3 ) - 1;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0B , ~0x30 , ( value & 0x300 ) >> 4 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x2 , (value & 0xFF) ) ;
+
+ /* HBE SR0C[1:0] CR05[7] CR03[4:0] */
+ value = ( LVDSHBE >> 3 ) - 1;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0C , ~0x03 , ( value & 0xC0 ) >> 6 ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x05 , ~0x80 , ( value & 0x20 ) << 2 ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x03 , ~0x1F , value & 0x1F ) ;
+
+ /* HRS SR0B[7:6] CR04 */
+ value = ( LVDSHRS >> 3 ) + 2;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0B , ~0xC0 , ( value & 0x300 ) >> 2 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x4 , (value & 0xFF) ) ;
+
+ /* Panel HRS SR2F[1:0] SR2E[7:0] */
+ value--;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x2F , ~0x03 , ( value & 0x300 ) >> 8 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , (value & 0xFF) ) ;
+
+ /* HRE SR0C[2] CR05[4:0] */
+ value = ( LVDSHRE >> 3 ) + 2;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0C , ~0x04 , ( value & 0x20 ) >> 3 ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x05 , ~0x1F , value & 0x1F ) ;
+
+ /* Panel HRE SR2F[7:2] */
+ value--;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x2F , ~0xFC , value << 2 ) ;
+
+ /* VT SR0A[0] CR07[5][0] CR06 */
+ value = LVDSVT - 2 ;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x01 , ( value & 0x400 ) >> 10 ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x20 , ( value & 0x200 ) >> 4 ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x01 , ( value & 0x100 ) >> 8 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x06 , (value & 0xFF) ) ;
+
+ /* VBS SR0A[2] CR09[5] CR07[3] CR15 */
+ value = LVDSVBS - 1 ;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x04 , ( value & 0x400 ) >> 8 ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x09 , ~0x20 , ( value & 0x200 ) >> 4 ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x08 , ( value & 0x100 ) >> 5 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x15 , (value & 0xFF) ) ;
+
+ /* VBE SR0A[4] CR16 */
+ value = LVDSVBE - 1;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x10 , ( value & 0x100 ) >> 4 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x16 , (value & 0xFF) ) ;
+
+ /* VRS SR0A[3] CR7[7][2] CR10 */
+ value = LVDSVRS - 1 ;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x08 , ( value & 0x400 ) >> 7 ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x80 , ( value & 0x200 ) >> 2 ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x04 , ( value & 0x100 ) >> 6 ) ;
+ XGINew_SetReg1( pVBInfo->P3d4 , 0x10 , (value & 0xFF) ) ;
+
+ /* Panel VRS SR35[2:0] SR34[7:0] */
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x07 , ( value & 0x700 ) >> 8 ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , value & 0xFF ) ;
+
+ /* VRE SR0A[5] CR11[3:0] */
+ value = LVDSVRE - 1;
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x20 , ( value & 0x10 ) << 1 ) ;
+ XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x11 , ~0x0F , value & 0x0F ) ;
+
+ /* Panel VRE SR3F[7:2] */
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x3F , ~0xFC , ( value << 2 ) & 0xFC ) ;
+
+ for ( temp=0, value = 0; temp < 3; temp++)
+ {
+
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x31 , ~0x30 , value ) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData1) ;
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData2) ;
+ value += 0x10;
+ }
+
+ if (!( modeflag & Charx8Dot ))
+ {
+ XGINew_GetReg2( pVBInfo->P3da ) ; /* reset 3da */
+ XGINew_SetReg3( pVBInfo->P3c0 , 0x13 ) ; /* set index */
+ XGINew_SetReg3( pVBInfo->P3c0 , 0x00 ) ; /* set data, panning = 0, shift left 1 dot*/
+
+ XGINew_GetReg2( pVBInfo->P3da ) ; /* Enable Attribute */
+ XGINew_SetReg3( pVBInfo->P3c0 , 0x20 ) ;
+
+ XGINew_GetReg2( pVBInfo->P3da ) ; /* reset 3da */
+ }
+
+
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_IsLCDON */
+/* Input : */
+/* Output : FALSE : Skip PSC Control */
+/* TRUE: Disable PSC */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_IsLCDON(PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT tempax ;
+
+ tempax = pVBInfo->VBInfo ;
+ if ( tempax & SetCRT2ToDualEdge )
+ return FALSE ;
+ else if ( tempax & ( DisableCRT2Display | SwitchToCRT2 | SetSimuScanMode ) )
+ return TRUE ;
+
+ return FALSE ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_EnablePWD */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_EnablePWD( PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT index ,
+ temp ;
+
+ index = XGI_GetLCDCapPtr(pVBInfo) ;
+ temp = pVBInfo->LCDCapList[ index ].PWD_2B ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x2B , temp ) ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x2C , pVBInfo->LCDCapList[ index ].PWD_2C ) ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x2D , pVBInfo->LCDCapList[ index ].PWD_2D ) ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x2E , pVBInfo->LCDCapList[ index ].PWD_2E ) ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x2F , pVBInfo->LCDCapList[ index ].PWD_2F ) ;
+ XGINew_SetRegOR( pVBInfo->Part4Port , 0x27 , 0x80 ) ; /* enable PWD */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_DisablePWD */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_DisablePWD( PVB_DEVICE_INFO pVBInfo )
+{
+ XGINew_SetRegAND( pVBInfo->Part4Port , 0x27 , 0x7F ) ; /* disable PWD */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_DisableChISLCD */
+/* Input : */
+/* Output : FALSE -> Not LCD Mode */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_DisableChISLCD(PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT tempbx ,
+ tempah ;
+
+ tempbx = pVBInfo->SetFlag & ( DisableChA | DisableChB ) ;
+ tempah = ~( ( USHORT )XGINew_GetReg1( pVBInfo->Part1Port , 0x2E ) ) ;
+
+ if ( tempbx & ( EnableChA | DisableChA ) )
+ {
+ if ( !( tempah & 0x08 ) ) /* Chk LCDA Mode */
+ return FALSE ;
+ }
+
+ if ( !( tempbx & ( EnableChB | DisableChB ) ) )
+ return FALSE ;
+
+ if ( tempah & 0x01 ) /* Chk LCDB Mode */
+ return TRUE ;
+
+ return FALSE ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_EnableChISLCD */
+/* Input : */
+/* Output : 0 -> Not LCD mode */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_EnableChISLCD(PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT tempbx ,
+ tempah ;
+
+
+ tempbx = pVBInfo->SetFlag & ( EnableChA | EnableChB ) ;
+ tempah = ~( ( USHORT )XGINew_GetReg1( pVBInfo->Part1Port , 0x2E ) ) ;
+
+ if ( tempbx & ( EnableChA | DisableChA ) )
+ {
+ if ( !( tempah & 0x08 ) ) /* Chk LCDA Mode */
+ return FALSE ;
+ }
+
+ if ( !( tempbx & ( EnableChB | DisableChB ) ) )
+ return FALSE ;
+
+ if ( tempah & 0x01 ) /* Chk LCDB Mode */
+ return TRUE ;
+
+ return FALSE ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetLCDCapPtr */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+USHORT XGI_GetLCDCapPtr( PVB_DEVICE_INFO pVBInfo )
+{
+ UCHAR tempal ,
+ tempah ,
+ tempbl ,
+ i ;
+
+ tempah = XGINew_GetReg1( pVBInfo->P3d4 , 0x36 ) ;
+ tempal = tempah & 0x0F ;
+ tempah = tempah & 0xF0 ;
+ i = 0 ;
+ tempbl = pVBInfo->LCDCapList[ i ].LCD_ID ;
+
+ while( tempbl != 0xFF )
+ {
+ if ( tempbl & 0x80 ) /* OEMUtil */
+ {
+ tempal = tempah ;
+ tempbl = tempbl & ~( 0x80 ) ;
+ }
+
+ if ( tempal == tempbl )
+ break ;
+
+ i++ ;
+
+ tempbl = pVBInfo->LCDCapList[ i ].LCD_ID ;
+ }
+
+ return i ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetLCDCapPtr1 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+USHORT XGI_GetLCDCapPtr1( PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT tempah ,
+ tempal ,
+ tempbl ,
+ i ;
+
+ tempal = pVBInfo->LCDResInfo ;
+ tempah = pVBInfo->LCDTypeInfo ;
+
+ i = 0 ;
+ tempbl = pVBInfo->LCDCapList[ i ].LCD_ID;
+
+ while( tempbl != 0xFF )
+ {
+ if ( ( tempbl & 0x80 ) && ( tempbl != 0x80 ) )
+ {
+ tempal = tempah ;
+ tempbl &= ~0x80 ;
+ }
+
+ if ( tempal == tempbl )
+ break ;
+
+ i++ ;
+ tempbl = pVBInfo->LCDCapList[ i ].LCD_ID ;
+ }
+
+ if ( tempbl == 0xFF )
+ {
+ pVBInfo->LCDResInfo = Panel1024x768 ;
+ pVBInfo->LCDTypeInfo = 0 ;
+ i = 0 ;
+ }
+
+ return i ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetLCDSync */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetLCDSync( USHORT* HSyncWidth , USHORT* VSyncWidth, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT Index ;
+
+ Index = XGI_GetLCDCapPtr(pVBInfo) ;
+ *HSyncWidth = pVBInfo->LCDCapList[ Index ].LCD_HSyncWidth ;
+ *VSyncWidth = pVBInfo->LCDCapList[ Index ].LCD_VSyncWidth ;
+
+ return ;
+}
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_EnableBridge */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_EnableBridge( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT tempbl ,
+ tempah ;
+
+ if ( pVBInfo->SetFlag == Win9xDOSMode )
+ {
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ XGI_DisplayOn( HwDeviceExtension, pVBInfo) ;
+ return ;
+ }
+ else /* LVDS or CH7017 */
+ return ;
+ }
+
+
+ if ( HwDeviceExtension->jChipType < XG40 )
+ {
+ if ( !XGI_DisableChISLCD(pVBInfo) )
+ {
+ if ( ( XGI_EnableChISLCD(pVBInfo) ) || ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) )
+ {
+ if ( pVBInfo->LCDInfo & SetPWDEnable )
+ {
+ XGI_EnablePWD( pVBInfo);
+ }
+ else
+ {
+ pVBInfo->LCDInfo &= ( ~SetPWDEnable ) ;
+ if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ tempbl = 0xFD ;
+ tempah = 0x02 ;
+ }
+ else
+ {
+ tempbl = 0xFB ;
+ tempah = 0x00 ;
+ }
+
+ XGI_SetPanelPower( tempah , tempbl, pVBInfo ) ;
+ XGI_SetPanelDelay( 1,pVBInfo ) ;
+ }
+ }
+ }
+ } /* Not 340 */
+
+
+
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ if ( !( pVBInfo->SetFlag & DisableChA ) )
+ {
+ if ( pVBInfo->SetFlag & EnableChA )
+ {
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x1E , 0x20 ) ; /* Power on */
+ }
+ else
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToDualEdge ) /* SetCRT2ToLCDA ) */
+ {
+ XGINew_SetReg1(pVBInfo->Part1Port,0x1E,0x20); /* Power on */
+ }
+ }
+ }
+
+ if ( !( pVBInfo->SetFlag & DisableChB ) )
+ {
+ if ( ( pVBInfo->SetFlag & EnableChB ) || ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToTV | SetCRT2ToRAMDAC ) ) )
+ {
+ tempah = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x32 ) ;
+ tempah &= 0xDF;
+ if ( pVBInfo->VBInfo & SetInSlaveMode )
+ {
+ if ( !( pVBInfo->VBInfo & SetCRT2ToRAMDAC ) )
+ tempah |= 0x20 ;
+ }
+ XGINew_SetReg1( pVBInfo->P3c4 , 0x32 , tempah ) ;
+ XGINew_SetRegOR( pVBInfo->P3c4 , 0x1E , 0x20 ) ;
+
+
+ tempah = ( UCHAR )XGINew_GetReg1( pVBInfo->Part1Port , 0x2E ) ;
+
+ if ( !( tempah & 0x80 ) )
+ XGINew_SetRegOR( pVBInfo->Part1Port , 0x2E , 0x80 ) ; /* BVBDOENABLE = 1 */
+
+ XGINew_SetRegAND( pVBInfo->Part1Port , 0x00 , 0x7F ) ; /* BScreenOFF = 0 */
+ }
+ }
+
+ if ( ( pVBInfo->SetFlag & ( EnableChA | EnableChB ) ) || ( !( pVBInfo->VBInfo & DisableCRT2Display ) ) )
+ {
+ XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x00 , ~0xE0 , 0x20 ) ; /* shampoo 0129 */
+ if ( pVBInfo->VBType & ( VB_XGI302LV | VB_XGI301C ) )
+ {
+ if ( !XGI_DisableChISLCD(pVBInfo) )
+ {
+ if ( XGI_EnableChISLCD( pVBInfo) || ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) )
+ XGINew_SetRegAND( pVBInfo->Part4Port ,0x2A , 0x7F ) ; /* LVDS PLL power on */
+ }
+ XGINew_SetRegAND( pVBInfo->Part4Port , 0x30 , 0x7F ) ; /* LVDS Driver power on */
+ }
+ }
+
+ tempah = 0x00 ;
+
+ if ( !( pVBInfo->VBInfo & DisableCRT2Display ) )
+ {
+ tempah = 0xc0 ;
+
+ if ( !( pVBInfo->VBInfo & SetSimuScanMode ) )
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToDualEdge )
+ {
+ tempah = tempah & 0x40;
+ if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+ tempah = tempah ^ 0xC0 ;
+
+ if ( pVBInfo->SetFlag & DisableChB )
+ tempah &= 0xBF ;
+
+ if ( pVBInfo->SetFlag & DisableChA )
+ tempah &= 0x7F ;
+
+ if ( pVBInfo->SetFlag & EnableChB )
+ tempah |= 0x40 ;
+
+ if ( pVBInfo->SetFlag & EnableChA )
+ tempah |= 0x80 ;
+ }
+ }
+ }
+ }
+
+ XGINew_SetRegOR( pVBInfo->Part4Port , 0x1F , tempah ) ; /* EnablePart4_1F */
+
+ if ( pVBInfo->SetFlag & Win9xDOSMode )
+ {
+ XGI_DisplayOn( HwDeviceExtension, pVBInfo) ;
+ return ;
+ }
+
+ if ( !( pVBInfo->SetFlag & DisableChA ) )
+ {
+ XGI_VBLongWait( pVBInfo) ;
+ if ( !( pVBInfo->SetFlag & GatingCRT ) )
+ {
+ XGI_DisableGatingCRT( HwDeviceExtension, pVBInfo ) ;
+ XGI_DisplayOn( HwDeviceExtension, pVBInfo) ;
+ XGI_VBLongWait( pVBInfo) ;
+ }
+ }
+ } /* 301 */
+ else /* LVDS */
+ {
+ if ( pVBInfo->VBInfo & ( SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA ) )
+ XGINew_SetRegOR( pVBInfo->Part1Port , 0x1E , 0x20 ) ; /* enable CRT2 */
+
+
+
+ tempah = ( UCHAR )XGINew_GetReg1( pVBInfo->Part1Port , 0x2E ) ;
+ if ( !( tempah & 0x80 ) )
+ XGINew_SetRegOR( pVBInfo->Part1Port , 0x2E , 0x80 ) ; /* BVBDOENABLE = 1 */
+
+ XGINew_SetRegAND(pVBInfo->Part1Port,0x00,0x7F);
+ XGI_DisplayOn( HwDeviceExtension, pVBInfo);
+ } /* End of VB */
+
+
+ if ( HwDeviceExtension->jChipType < XG40 )
+ {
+ if ( !XGI_EnableChISLCD(pVBInfo) )
+ {
+ if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+ {
+ if ( XGI_BacklightByDrv(pVBInfo) )
+ return ;
+ }
+ else
+ return ;
+ }
+
+ if ( pVBInfo->LCDInfo & SetPWDEnable )
+ {
+ XGI_FirePWDEnable(pVBInfo) ;
+ return ;
+ }
+
+ XGI_SetPanelDelay( 2,pVBInfo ) ;
+
+ if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ tempah = 0x01 ;
+ tempbl = 0xFE ; /* turn on backlght */
+ }
+ else
+ {
+ tempbl = 0xF7 ;
+ tempah = 0x00 ;
+ }
+ XGI_SetPanelPower( tempah , tempbl , pVBInfo) ;
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_DisableBridge */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_DisableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT tempax ,
+ tempbx ,
+ tempah = 0 ,
+ tempbl = 0 ;
+
+ if ( pVBInfo->SetFlag == Win9xDOSMode )
+ return ;
+
+
+ if ( HwDeviceExtension->jChipType < XG40 )
+ {
+ if ( ( !( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) ) || ( XGI_DisableChISLCD(pVBInfo) ) )
+ {
+ if ( !XGI_IsLCDON(pVBInfo) )
+ {
+ if ( pVBInfo->LCDInfo & SetPWDEnable )
+ XGI_EnablePWD( pVBInfo) ;
+ else
+ {
+ pVBInfo->LCDInfo &= ~SetPWDEnable ;
+ XGI_DisablePWD(pVBInfo) ;
+ if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ tempbx = 0xFE ; /* not 01h */
+ tempax = 0 ;
+ }
+ else
+ {
+ tempbx = 0xF7 ; /* not 08h */
+ tempax = 0x08 ;
+ }
+ XGI_SetPanelPower( tempax , tempbx , pVBInfo) ;
+ XGI_SetPanelDelay( 3,pVBInfo ) ;
+ }
+ } /* end if(!XGI_IsLCDON(pVBInfo)) */
+ }
+ }
+
+/* if ( CH7017 )
+ {
+ if ( !( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2toLCDA ) ) || ( XGI_DisableChISLCD(pVBInfo) ) )
+ {
+ if ( !XGI_IsLCDON(pVBInfo) )
+ {
+ if ( DISCHARGE )
+ {
+ tempbx = XGINew_GetCH7005( 0x61 ) ;
+ if ( tempbx < 0x01 ) //first time we power up
+ XGINew_SetCH7005( 0x0066 ) ; //and disable power sequence
+ else
+ XGINew_SetCH7005( 0x5f66 ) ; //leave VDD on - disable power
+ }
+ }
+ }
+ } */
+
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B| VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ tempah = 0x3F ;
+ if ( !( pVBInfo->VBInfo & ( DisableCRT2Display | SetSimuScanMode ) ) )
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToDualEdge )
+ {
+ tempah = 0x7F; /* Disable Channel A */
+ if ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) )
+ tempah = 0xBF ; /* Disable Channel B */
+
+ if ( pVBInfo->SetFlag & DisableChB )
+ tempah &= 0xBF ; /* force to disable Cahnnel */
+
+ if ( pVBInfo->SetFlag & DisableChA )
+ tempah &= 0x7F ; /* Force to disable Channel B */
+ }
+ }
+ }
+
+ XGINew_SetRegAND( pVBInfo->Part4Port , 0x1F , tempah ) ; /* disable part4_1f */
+
+ if ( pVBInfo->VBType & ( VB_XGI302LV | VB_XGI301C ) )
+ {
+ if ( ( ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) ) || ( XGI_DisableChISLCD(pVBInfo) ) || ( XGI_IsLCDON(pVBInfo) ) )
+ XGINew_SetRegOR( pVBInfo->Part4Port , 0x30 , 0x80 ) ; /* LVDS Driver power down */
+ }
+
+ if ( ( pVBInfo->SetFlag & DisableChA ) || ( pVBInfo->VBInfo & ( DisableCRT2Display | SetCRT2ToLCDA | SetSimuScanMode ) ) )
+ {
+ if ( pVBInfo->SetFlag & GatingCRT )
+ XGI_EnableGatingCRT( HwDeviceExtension, pVBInfo ) ;
+ XGI_DisplayOff( HwDeviceExtension, pVBInfo) ;
+ }
+
+ if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+ {
+ if ( ( pVBInfo->SetFlag & DisableChA ) || ( pVBInfo->VBInfo & SetCRT2ToLCDA ) )
+ XGINew_SetRegAND( pVBInfo->Part1Port , 0x1e , 0xdf ) ; /* Power down */
+ }
+
+ XGINew_SetRegAND( pVBInfo->P3c4 , 0x32 , 0xdf ) ; /* disable TV as primary VGA swap */
+
+ if ( ( pVBInfo->VBInfo & ( SetSimuScanMode | SetCRT2ToDualEdge ) ) )
+ XGINew_SetRegAND(pVBInfo->Part2Port,0x00,0xdf);
+
+ if ( ( pVBInfo->SetFlag & DisableChB ) || ( pVBInfo->VBInfo & ( DisableCRT2Display | SetSimuScanMode ) )
+ || ( ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) ) && ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV ) ) ) )
+ XGINew_SetRegOR( pVBInfo->Part1Port , 0x00 , 0x80 ) ; /* BScreenOff=1 */
+
+ if ( ( pVBInfo->SetFlag & DisableChB ) || ( pVBInfo->VBInfo & ( DisableCRT2Display | SetSimuScanMode ) )
+ || ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) ) || ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV ) ) )
+ {
+ tempah= XGINew_GetReg1( pVBInfo->Part1Port , 0x00 ) ; /* save Part1 index 0 */
+ XGINew_SetRegOR( pVBInfo->Part1Port , 0x00 , 0x10 ) ; /* BTDAC = 1, avoid VB reset */
+ XGINew_SetRegAND( pVBInfo->Part1Port , 0x1E , 0xDF ) ; /* disable CRT2 */
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x00 , tempah ) ; /* restore Part1 index 0 */
+ }
+ }
+ else /* {301} */
+ {
+ if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToTV ) )
+ {
+ XGINew_SetRegOR( pVBInfo->Part1Port , 0x00 , 0x80 ) ; /* BScreenOff=1 */
+ XGINew_SetRegAND( pVBInfo->Part1Port , 0x1E , 0xDF ) ; /* Disable CRT2 */
+ XGINew_SetRegAND( pVBInfo->P3c4 , 0x32 , 0xDF ) ; /* Disable TV asPrimary VGA swap */
+ }
+
+ if ( pVBInfo->VBInfo & ( DisableCRT2Display | SetCRT2ToLCDA | SetSimuScanMode ) )
+ XGI_DisplayOff( HwDeviceExtension, pVBInfo) ;
+ }
+
+
+
+
+ if ( HwDeviceExtension->jChipType < XG40 )
+ {
+ if ( !( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) || ( XGI_DisableChISLCD(pVBInfo) ) || ( XGI_IsLCDON(pVBInfo) ) )
+ {
+ if ( pVBInfo->LCDInfo & SetPWDEnable )
+ {
+ if ( pVBInfo->LCDInfo & SetPWDEnable )
+ XGI_BacklightByDrv(pVBInfo) ;
+ else
+ {
+ XGI_SetPanelDelay( 4 ,pVBInfo) ;
+ if ( pVBInfo->VBType & VB_XGI301LV )
+ {
+ tempbl = 0xFD ;
+ tempah = 0x00 ;
+ }
+ else
+ {
+ tempbl = 0xFB ;
+ tempah = 0x04 ;
+ }
+ }
+ }
+ XGI_SetPanelPower( tempah , tempbl , pVBInfo) ;
+ }
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetTVPtrIndex */
+/* Input : */
+/* Output : */
+/* Description : bx 0 : ExtNTSC */
+/* 1 : StNTSC */
+/* 2 : ExtPAL */
+/* 3 : StPAL */
+/* 4 : ExtHiTV */
+/* 5 : StHiTV */
+/* 6 : Ext525i */
+/* 7 : St525i */
+/* 8 : Ext525p */
+/* 9 : St525p */
+/* A : Ext750p */
+/* B : St750p */
+/* --------------------------------------------------------------------- */
+USHORT XGI_GetTVPtrIndex( PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT tempbx = 0 ;
+
+ if ( pVBInfo->TVInfo & SetPALTV )
+ tempbx = 2 ;
+ if ( pVBInfo->TVInfo & SetYPbPrMode1080i )
+ tempbx = 4 ;
+ if ( pVBInfo->TVInfo & SetYPbPrMode525i )
+ tempbx = 6 ;
+ if ( pVBInfo->TVInfo & SetYPbPrMode525p )
+ tempbx = 8 ;
+ if ( pVBInfo->TVInfo & SetYPbPrMode750p )
+ tempbx = 10 ;
+ if ( pVBInfo->TVInfo & TVSimuMode )
+ tempbx++ ;
+
+ return tempbx ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_OEM310Setting */
+/* Input : */
+/* Output : */
+/* Description : Customized Param. for 301 */
+/* --------------------------------------------------------------------- */
+void XGI_OEM310Setting( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+{
+ if ( pVBInfo->SetFlag & Win9xDOSMode )
+ return ;
+
+ /* GetPart1IO(); */
+ XGI_SetDelayComp(pVBInfo) ;
+
+ if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+ XGI_SetLCDCap(pVBInfo) ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToTV )
+ {
+ /* GetPart2IO() */
+ XGI_SetPhaseIncr(pVBInfo) ;
+ XGI_SetYFilter( ModeNo , ModeIdIndex,pVBInfo ) ;
+ XGI_SetAntiFlicker( ModeNo , ModeIdIndex,pVBInfo ) ;
+
+ if ( pVBInfo->VBType&VB_XGI301)
+ XGI_SetEdgeEnhance( ModeNo , ModeIdIndex ,pVBInfo) ;
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetDelayComp */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetDelayComp( PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT index ;
+
+ UCHAR tempah ,
+ tempbl ,
+ tempbh ;
+
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToTV | SetCRT2ToRAMDAC ) )
+ {
+ tempbl = 0;
+ tempbh = 0;
+
+ index = XGI_GetTVPtrIndex(pVBInfo ) ; /* Get TV Delay */
+ tempbl = pVBInfo->XGI_TVDelayList[ index ] ;
+
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ tempbl = pVBInfo->XGI_TVDelayList2[ index ] ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToDualEdge )
+ tempbl = tempbl >> 4 ;
+/*
+ if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC )
+ tempbl = CRT2Delay1 ; // Get CRT2 Delay
+
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ tempbl = CRT2Delay2 ;
+*/
+ if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
+ {
+ index = XGI_GetLCDCapPtr(pVBInfo) ; /* Get LCD Delay */
+ tempbh=pVBInfo->LCDCapList[ index ].LCD_DelayCompensation ;
+
+ if ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) )
+ tempbl = tempbh ;
+ }
+
+ tempbl &= 0x0F ;
+ tempbh &= 0xF0 ;
+ tempah = XGINew_GetReg1( pVBInfo->Part1Port , 0x2D ) ;
+
+ if ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV ) ) /* Channel B */
+ {
+ tempah &= 0xF0 ;
+ tempah |= tempbl ;
+ }
+
+ if ( pVBInfo->VBInfo & SetCRT2ToLCDA ) /* Channel A */
+ {
+ tempah &= 0x0F ;
+ tempah |= tempbh ;
+ }
+ XGINew_SetReg1(pVBInfo->Part1Port,0x2D,tempah);
+ }
+ }
+ else if ( pVBInfo->IF_DEF_LVDS == 1 )
+ {
+ tempbl = 0;
+ tempbh = 0;
+ if ( pVBInfo->VBInfo & SetCRT2ToLCD )
+ {
+ tempah = pVBInfo->LCDCapList[ XGI_GetLCDCapPtr(pVBInfo) ].LCD_DelayCompensation ; /* / Get LCD Delay */
+ tempah &= 0x0f ;
+ tempah = tempah << 4 ;
+ XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2D , 0x0f , tempah ) ;
+ }
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetLCDCap */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetLCDCap( PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT tempcx ;
+
+ tempcx = pVBInfo->LCDCapList[ XGI_GetLCDCapPtr(pVBInfo) ].LCD_Capability ;
+
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ { /* 301LV/302LV only */
+ /* Set 301LV Capability */
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x24 , ( UCHAR )( tempcx & 0x1F ) ) ;
+ }
+ /* VB Driving */
+ XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x0D , ~( ( EnableVBCLKDRVLOW | EnablePLLSPLOW ) >> 8 ) , ( USHORT )( ( tempcx & ( EnableVBCLKDRVLOW | EnablePLLSPLOW ) ) >> 8 ) ) ;
+ }
+
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToLCD )
+ XGI_SetLCDCap_B( tempcx,pVBInfo ) ;
+ else if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+ XGI_SetLCDCap_A( tempcx,pVBInfo ) ;
+
+ if ( pVBInfo->VBType & ( VB_XGI302LV | VB_XGI301C ) )
+ {
+ if ( tempcx & EnableSpectrum )
+ SetSpectrum( pVBInfo) ;
+ }
+ }
+ else /* LVDS,CH7017 */
+ XGI_SetLCDCap_A( tempcx, pVBInfo ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetLCDCap_A */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetLCDCap_A(USHORT tempcx,PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT temp ;
+
+ temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x37 ) ;
+
+ if ( temp & LCDRGB18Bit )
+ {
+ XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x19 , 0x0F , ( USHORT )( 0x20 | ( tempcx & 0x00C0 ) ) ) ; /* Enable Dither */
+ XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x1A , 0x7F , 0x80 ) ;
+ }
+ else
+ {
+ XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x19 , 0x0F , ( USHORT )( 0x30 | ( tempcx & 0x00C0 ) ) ) ;
+ XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x1A , 0x7F , 0x00 ) ;
+ }
+
+/*
+ if ( tempcx & EnableLCD24bpp ) // 24bits
+ {
+ XGINew_SetRegANDOR(pVBInfo->Part1Port,0x19, 0x0F,(USHORT)(0x30|(tempcx&0x00C0)) );
+ XGINew_SetRegANDOR(pVBInfo->Part1Port,0x1A,0x7F,0x00);
+ }
+ else
+ {
+ XGINew_SetRegANDOR(pVBInfo->Part1Port,0x19, 0x0F,(USHORT)(0x20|(tempcx&0x00C0)) );//Enable Dither
+ XGINew_SetRegANDOR(pVBInfo->Part1Port,0x1A,0x7F,0x80);
+ }
+*/
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetLCDCap_B */
+/* Input : cx -> LCD Capability */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetLCDCap_B(USHORT tempcx,PVB_DEVICE_INFO pVBInfo)
+{
+ if ( tempcx & EnableLCD24bpp ) /* 24bits */
+ XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x1A , 0xE0 , ( USHORT )( ( ( tempcx & 0x00ff ) >> 6 ) | 0x0c ) ) ;
+ else
+ XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x1A , 0xE0 , ( USHORT )( ( ( tempcx & 0x00ff ) >> 6 ) | 0x18 ) ) ; /* Enable Dither */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : SetSpectrum */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void SetSpectrum( PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT index ;
+
+ index = XGI_GetLCDCapPtr(pVBInfo) ;
+
+ XGINew_SetRegAND( pVBInfo->Part4Port , 0x30 , 0x8F ) ; /* disable down spectrum D[4] */
+ XGI_LongWait(pVBInfo) ;
+ XGINew_SetRegOR( pVBInfo->Part4Port , 0x30 , 0x20 ) ; /* reset spectrum */
+ XGI_LongWait(pVBInfo) ;
+
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x31 , pVBInfo->LCDCapList[ index ].Spectrum_31 ) ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x32 , pVBInfo->LCDCapList[ index ].Spectrum_32 ) ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x33 , pVBInfo->LCDCapList[ index ].Spectrum_33 ) ;
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x34 , pVBInfo->LCDCapList[ index ].Spectrum_34 ) ;
+ XGI_LongWait(pVBInfo) ;
+ XGINew_SetRegOR( pVBInfo->Part4Port , 0x30 , 0x40 ) ; /* enable spectrum */
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetAntiFlicker */
+/* Input : */
+/* Output : */
+/* Description : Set TV Customized Param. */
+/* --------------------------------------------------------------------- */
+void XGI_SetAntiFlicker( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT tempbx ,
+ index ;
+
+ UCHAR tempah ;
+
+ if (pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) )
+ return ;
+
+ tempbx = XGI_GetTVPtrIndex(pVBInfo ) ;
+ tempbx &= 0xFE ;
+
+ if ( ModeNo <= 0x13 )
+ {
+ index = pVBInfo->SModeIDTable[ ModeIdIndex ].VB_StTVFlickerIndex ;
+ }
+ else
+ {
+ index = pVBInfo->EModeIDTable[ ModeIdIndex ].VB_ExtTVFlickerIndex ;
+ }
+
+ tempbx += index ;
+ tempah = TVAntiFlickList[ tempbx ] ;
+ tempah = tempah << 4 ;
+
+ XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x0A , 0x8F , tempah ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetEdgeEnhance */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetEdgeEnhance( USHORT ModeNo , USHORT ModeIdIndex , PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT tempbx ,
+ index ;
+
+ UCHAR tempah ;
+
+
+ tempbx = XGI_GetTVPtrIndex(pVBInfo ) ;
+ tempbx &= 0xFE ;
+
+ if ( ModeNo <= 0x13 )
+ {
+ index = pVBInfo->SModeIDTable[ ModeIdIndex ].VB_StTVEdgeIndex ;
+ }
+ else
+ {
+ index = pVBInfo->EModeIDTable[ ModeIdIndex ].VB_ExtTVEdgeIndex ;
+ }
+
+ tempbx += index ;
+ tempah = TVEdgeList[ tempbx ] ;
+ tempah = tempah << 5 ;
+
+ XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x3A , 0x1F , tempah ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetPhaseIncr */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetPhaseIncr( PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT tempbx ;
+
+ UCHAR tempcl ,
+ tempch ;
+
+ ULONG tempData ;
+
+ XGI_GetTVPtrIndex2( &tempbx , &tempcl , &tempch, pVBInfo ) ; /* bx, cl, ch */
+ tempData = TVPhaseList[ tempbx ] ;
+
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x31 , ( USHORT )( tempData & 0x000000FF ) ) ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x32 , ( USHORT )( ( tempData & 0x0000FF00 ) >> 8 ) ) ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x33 , ( USHORT )( ( tempData & 0x00FF0000 ) >> 16 ) ) ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x34 , ( USHORT )( ( tempData & 0xFF000000 ) >> 24 ) ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetYFilter */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_SetYFilter( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT tempbx ,
+ index ;
+
+ UCHAR tempcl ,
+ tempch ,
+ tempal ,
+ *filterPtr ;
+
+ XGI_GetTVPtrIndex2( &tempbx , &tempcl , &tempch, pVBInfo ) ; /* bx, cl, ch */
+
+ switch( tempbx )
+ {
+ case 0x00:
+ case 0x04:
+ filterPtr = NTSCYFilter1 ;
+ break ;
+
+ case 0x01:
+ filterPtr = PALYFilter1 ;
+ break ;
+
+ case 0x02:
+ case 0x05:
+ case 0x0D:
+ filterPtr = PALMYFilter1 ;
+ break ;
+
+ case 0x03:
+ filterPtr = PALNYFilter1 ;
+ break ;
+
+ case 0x08:
+ case 0x0C:
+ filterPtr = NTSCYFilter2 ;
+ break ;
+
+ case 0x0A:
+ filterPtr = PALMYFilter2 ;
+ break ;
+
+ case 0x0B:
+ filterPtr = PALNYFilter2 ;
+ break ;
+
+ case 0x09:
+ filterPtr = PALYFilter2 ;
+ break ;
+
+ default:
+ return ;
+ }
+
+ if ( ModeNo <= 0x13 )
+ tempal = pVBInfo->SModeIDTable[ ModeIdIndex ].VB_StTVYFilterIndex ;
+ else
+ tempal = pVBInfo->EModeIDTable[ ModeIdIndex ].VB_ExtTVYFilterIndex ;
+
+ if ( tempcl == 0 )
+ index = tempal * 4;
+ else
+ index = tempal * 7;
+
+ if ( ( tempcl == 0 ) && ( tempch == 1 ) )
+ {
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x35 , 0 ) ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x36 , 0 ) ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x37 , 0 ) ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x38 , filterPtr[ index++ ] ) ;
+ }
+ else
+ {
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x35 , filterPtr[ index++ ] ) ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x36 , filterPtr[ index++ ] ) ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x37 , filterPtr[ index++ ] ) ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x38 , filterPtr[ index++ ] ) ;
+ }
+
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x48 , filterPtr[ index++ ] ) ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x49 , filterPtr[ index++ ] ) ;
+ XGINew_SetReg1( pVBInfo->Part2Port , 0x4A , filterPtr[ index++ ] ) ;
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetTVPtrIndex2 */
+/* Input : */
+/* Output : bx 0 : NTSC */
+/* 1 : PAL */
+/* 2 : PALM */
+/* 3 : PALN */
+/* 4 : NTSC1024x768 */
+/* 5 : PAL-M 1024x768 */
+/* 6-7: reserved */
+/* cl 0 : YFilter1 */
+/* 1 : YFilter2 */
+/* ch 0 : 301A */
+/* 1 : 301B/302B/301LV/302LV */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetTVPtrIndex2(USHORT* tempbx,UCHAR* tempcl,UCHAR* tempch, PVB_DEVICE_INFO pVBInfo)
+{
+ *tempbx = 0 ;
+ *tempcl = 0 ;
+ *tempch = 0 ;
+
+ if ( pVBInfo->TVInfo & SetPALTV )
+ *tempbx = 1 ;
+
+ if ( pVBInfo->TVInfo & SetPALMTV )
+ *tempbx = 2 ;
+
+ if ( pVBInfo->TVInfo & SetPALNTV )
+ *tempbx = 3 ;
+
+ if ( pVBInfo->TVInfo & NTSC1024x768 )
+ {
+ *tempbx = 4 ;
+ if ( pVBInfo->TVInfo & SetPALMTV )
+ *tempbx = 5 ;
+ }
+
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ if ( ( !( pVBInfo->VBInfo & SetInSlaveMode ) ) || ( pVBInfo->TVInfo & TVSimuMode ) )
+ {
+ *tempbx += 8 ;
+ *tempcl += 1 ;
+ }
+ }
+
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ (*tempch)++ ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT2ModeRegs */
+/* Input : */
+/* Output : */
+/* Description : Origin code for crt2group */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT2ModeRegs(USHORT ModeNo,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT tempbl ;
+ SHORT tempcl ;
+
+ UCHAR tempah ;
+
+ /* XGINew_SetReg1( pVBInfo->Part1Port , 0x03 , 0x00 ) ; // fix write part1 index 0 BTDRAM bit Bug */
+ tempah=0;
+ if ( !( pVBInfo->VBInfo & DisableCRT2Display ) )
+ {
+ tempah=XGINew_GetReg1( pVBInfo->Part1Port , 0x00 ) ;
+ tempah &= ~0x10 ; /* BTRAMDAC */
+ tempah |= 0x40 ; /* BTRAM */
+
+ if ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD ) )
+ {
+ tempah=0x40; /* BTDRAM */
+ if ( ModeNo > 0x13 )
+ {
+ tempcl = pVBInfo->ModeType ;
+ tempcl -= ModeVGA ;
+ if ( tempcl >= 0 )
+ {
+ tempah = ( 0x008 >> tempcl ) ; /* BT Color */
+ if ( tempah == 0 )
+ tempah = 1 ;
+ tempah |= 0x040 ;
+ }
+ }
+ if ( pVBInfo->VBInfo & SetInSlaveMode )
+ tempah ^= 0x50 ; /* BTDAC */
+ }
+ }
+
+/* 0210 shampoo
+ if ( pVBInfo->VBInfo & DisableCRT2Display )
+ {
+ tempah = 0 ;
+ }
+
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x00 , tempah ) ;
+ if ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD ) )
+ {
+ tempcl = pVBInfo->ModeType ;
+ if ( ModeNo > 0x13 )
+ {
+ tempcl -= ModeVGA ;
+ if ( ( tempcl > 0 ) || ( tempcl == 0 ) )
+ {
+ tempah=(0x008>>tempcl) ;
+ if ( tempah == 0 )
+ tempah = 1 ;
+ tempah |= 0x040;
+ }
+ }
+ else
+ {
+ tempah = 0x040 ;
+ }
+
+ if ( pVBInfo->VBInfo & SetInSlaveMode )
+ {
+ tempah = ( tempah ^ 0x050 ) ;
+ }
+ }
+*/
+
+ XGINew_SetReg1( pVBInfo->Part1Port , 0x00 , tempah ) ;
+ tempah = 0x08 ;
+ tempbl = 0xf0 ;
+
+ if ( pVBInfo->VBInfo & DisableCRT2Display )
+ XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2e , tempbl , tempah ) ;
+ else
+ {
+ tempah = 0x00 ;
+ tempbl = 0xff ;
+
+ if ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA ) )
+ {
+ if ( ( pVBInfo->VBInfo & SetCRT2ToLCDA ) && ( !( pVBInfo->VBInfo & SetSimuScanMode ) ) )
+ {
+ tempbl &= 0xf7 ;
+ tempah |= 0x01 ;
+ XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2e , tempbl , tempah ) ;
+ }
+ else
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+ {
+ tempbl &= 0xf7 ;
+ tempah |= 0x01 ;
+ }
+
+ if ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD ) )
+ {
+ tempbl &= 0xf8 ;
+ tempah = 0x01 ;
+
+ if ( !( pVBInfo->VBInfo & SetInSlaveMode ) )
+ tempah |= 0x02 ;
+
+ if ( !( pVBInfo->VBInfo & SetCRT2ToRAMDAC ) )
+ {
+ tempah = tempah ^ 0x05 ;
+ if ( !( pVBInfo->VBInfo & SetCRT2ToLCD ) )
+ tempah = tempah ^ 0x01 ;
+ }
+
+ if ( !( pVBInfo->VBInfo & SetCRT2ToDualEdge ) )
+ tempah |= 0x08 ;
+ XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2e , tempbl , tempah ) ;
+ }
+ else
+ XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2e , tempbl , tempah ) ;
+ }
+ }
+ else
+ XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2e , tempbl , tempah ) ;
+ }
+
+ if ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA ) )
+ {
+ tempah &= ( ~0x08 ) ;
+ if ( ( pVBInfo->ModeType == ModeVGA ) && ( !( pVBInfo->VBInfo & SetInSlaveMode ) ) )
+ {
+ tempah |= 0x010 ;
+ }
+ tempah |= 0x080 ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToTV )
+ {
+ /* if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) ) ) */
+ /* { */
+ tempah |= 0x020 ;
+ if ( ModeNo > 0x13 )
+ {
+ if ( pVBInfo->VBInfo & DriverMode )
+ tempah = tempah ^ 0x20 ;
+ }
+ /* } */
+ }
+
+ XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x0D , ~0x0BF , tempah ) ;
+ tempah = 0 ;
+
+ if ( pVBInfo->LCDInfo & SetLCDDualLink )
+ tempah |= 0x40 ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToTV )
+ {
+ /* if ( ( !( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) ) && ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) ) ) ) */
+ /* { */
+ if ( pVBInfo->TVInfo & RPLLDIV2XO )
+ tempah |= 0x40 ;
+ /* } */
+ }
+
+ if ( ( pVBInfo->LCDResInfo == Panel1280x1024 ) || ( pVBInfo->LCDResInfo == Panel1280x1024x75 ) )
+ tempah |= 0x80 ;
+
+ if ( pVBInfo->LCDResInfo == Panel1280x960 )
+ tempah |= 0x80 ;
+
+ XGINew_SetReg1( pVBInfo->Part4Port , 0x0C , tempah ) ;
+ }
+
+ if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
+ {
+ tempah = 0 ;
+ tempbl = 0xfb ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToDualEdge )
+ {
+ tempbl=0xff;
+ if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+ tempah |= 0x04 ; /* shampoo 0129 */
+ }
+
+ XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x13 , tempbl , tempah ) ;
+ tempah = 0x00 ;
+ tempbl = 0xcf ;
+ if ( !( pVBInfo->VBInfo & DisableCRT2Display ) )
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToDualEdge )
+ tempah |= 0x30 ;
+ }
+
+ XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2c , tempbl , tempah ) ;
+ tempah = 0 ;
+ tempbl = 0x3f ;
+
+ if ( !( pVBInfo->VBInfo & DisableCRT2Display ) )
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToDualEdge )
+ tempah |= 0xc0 ;
+ }
+ XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x21 , tempbl , tempah ) ;
+ }
+
+ tempah = 0 ;
+ tempbl = 0x7f ;
+ if ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) )
+ {
+ tempbl = 0xff ;
+ if ( !( pVBInfo->VBInfo & SetCRT2ToDualEdge ) )
+ tempah |= 0x80 ;
+ }
+
+ XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x23 , tempbl , tempah ) ;
+
+ if ( pVBInfo->VBType & ( VB_XGI302LV | VB_XGI301C ) )
+ {
+ if ( pVBInfo->LCDInfo & SetLCDDualLink )
+ {
+ XGINew_SetRegOR( pVBInfo->Part4Port , 0x27 , 0x20 ) ;
+ XGINew_SetRegOR( pVBInfo->Part4Port , 0x34 , 0x10 ) ;
+ }
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_CloseCRTC */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_CloseCRTC( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT tempbx ;
+
+ tempbx = 0 ;
+
+ if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
+ tempbx = 0x08A0 ;
+
+
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_OpenCRTC */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_OpenCRTC( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT tempbx ;
+
+ tempbx = 0 ;
+
+
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetRAMDAC2DATA */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_GetRAMDAC2DATA(USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT tempax ,
+ tempbx ,
+ temp1 ,
+ temp2 ,
+ modeflag = 0 ,
+ tempcx ,
+ StandTableIndex ,
+ CRT1Index ;
+
+ pVBInfo->RVBHCMAX = 1 ;
+ pVBInfo->RVBHCFACT = 1 ;
+
+ if ( ModeNo <= 0x13 )
+ {
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+ StandTableIndex = XGI_GetModePtr( ModeNo , ModeIdIndex, pVBInfo ) ;
+ tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 0 ] ;
+ tempbx = pVBInfo->StandTable[StandTableIndex ].CRTC[ 6 ] ;
+ temp1 = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 7 ] ;
+ }
+ else
+ {
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+ CRT1Index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ;
+ CRT1Index &= IndexMask ;
+ temp1 = ( USHORT )pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 0 ] ;
+ temp2 = ( USHORT )pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 5 ] ;
+ tempax = ( temp1 & 0xFF ) | ( ( temp2 & 0x03 ) << 8 ) ;
+ tempbx = ( USHORT )pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 8 ] ;
+ tempcx = ( USHORT )pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 14 ] << 8 ;
+ tempcx &= 0x0100 ;
+ tempcx = tempcx << 2 ;
+ tempbx |= tempcx;
+ temp1 = ( USHORT )pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 9 ] ;
+ }
+
+ if ( temp1 & 0x01 )
+ tempbx |= 0x0100 ;
+
+ if ( temp1 & 0x20 )
+ tempbx |= 0x0200 ;
+ tempax += 5 ;
+
+ if ( modeflag & Charx8Dot )
+ tempax *= 8 ;
+ else
+ tempax *= 9 ;
+
+ pVBInfo->VGAHT = tempax ;
+ pVBInfo->HT = tempax ;
+ tempbx++ ;
+ pVBInfo->VGAVT = tempbx ;
+ pVBInfo->VT = tempbx ;
+}
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetColorDepth */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+USHORT XGI_GetColorDepth(USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT ColorDepth[ 6 ] = { 1 , 2 , 4 , 4 , 6 , 8 } ;
+ SHORT index ;
+ USHORT modeflag ;
+
+ if ( ModeNo <= 0x13 )
+ {
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
+ }
+ else
+ {
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
+ }
+
+ index=(modeflag&ModeInfoFlag)-ModeEGA;
+
+ if ( index < 0 )
+ index = 0 ;
+
+ return( ColorDepth[ index ] ) ;
+}
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_UnLockCRT2 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_UnLockCRT2( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
+{
+
+ XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2f , 0xFF , 0x01 ) ;
+
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_LockCRT2 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_LockCRT2( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
+{
+
+ XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2F , 0xFE , 0x00 ) ;
+
+
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_EnableCRT2 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_EnableCRT2( PVB_DEVICE_INFO pVBInfo)
+{
+ XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x1E , 0xFF , 0x20 ) ;
+}
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_LCD_Wait_Time(UCHAR DelayTime, PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT i ,
+ j ;
+
+ ULONG temp ,
+ flag ;
+
+ flag = 0 ;
+//printk("XGINew_LCD_Wait_Time");
+//return;
+ for( i = 0 ; i < DelayTime ; i++ )
+ {
+ for( j = 0 ; j < 66 ; j++ )
+ {
+
+ temp = XGINew_GetReg3( 0x61 ) ;
+
+ //temp &= 0x10000000;
+ temp &= 0x10;
+ if ( temp == flag )
+ continue ;
+
+ flag = temp ;
+ }
+ }
+}
+
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_BridgeIsOn */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+BOOLEAN XGI_BridgeIsOn( PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT flag ;
+
+ if ( pVBInfo->IF_DEF_LVDS == 1 )
+ {
+ return( 1 ) ;
+ }
+ else
+ {
+ flag = XGINew_GetReg1( pVBInfo->Part4Port , 0x00 ) ;
+ if ( ( flag == 1 ) || ( flag == 2 ) )
+ return( 1 ) ; /* 301b */
+ else
+ return( 0 ) ;
+ }
+}
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_LongWait */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_LongWait(PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT i ;
+
+ i = XGINew_GetReg1( pVBInfo->P3c4 , 0x1F ) ;
+
+ if ( !( i & 0xC0 ) )
+ {
+ for( i = 0 ; i < 0xFFFF ; i++ )
+ {
+ if ( !( XGINew_GetReg2( pVBInfo->P3da ) & 0x08 ) )
+ break ;
+ }
+
+ for( i = 0 ; i < 0xFFFF ; i++ )
+ {
+ if ( ( XGINew_GetReg2( pVBInfo->P3da ) & 0x08 ) )
+ break ;
+ }
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_VBLongWait */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGI_VBLongWait( PVB_DEVICE_INFO pVBInfo )
+{
+ USHORT tempal ,
+ temp ,
+ i ,
+ j ;
+return ;
+ if ( !( pVBInfo->VBInfo & SetCRT2ToTV ) )
+ {
+ temp = 0 ;
+ for( i = 0 ; i < 3 ; i++ )
+ {
+ for( j = 0 ; j < 100 ; j++ )
+ {
+ tempal = XGINew_GetReg2( pVBInfo->P3da ) ;
+ if ( temp & 0x01 )
+ { /* VBWaitMode2 */
+ if ( ( tempal & 0x08 ) )
+ {
+ continue ;
+ }
+
+ if ( !( tempal & 0x08 ) )
+ {
+ break ;
+ }
+ }
+ else
+ { /* VBWaitMode1 */
+ if ( !( tempal & 0x08 ) )
+ {
+ continue ;
+ }
+
+ if ( ( tempal & 0x08 ) )
+ {
+ break ;
+ }
+ }
+ }
+ temp = temp ^ 0x01 ;
+ }
+ }
+ else
+ {
+ XGI_LongWait(pVBInfo) ;
+ }
+ return ;
+}
+
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetVGAHT2 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+USHORT XGI_GetVGAHT2( PVB_DEVICE_INFO pVBInfo )
+{
+ ULONG tempax ,
+ tempbx ;
+
+ tempbx = ( ( pVBInfo->VGAVT - pVBInfo->VGAVDE ) * pVBInfo->RVBHCMAX ) & 0xFFFF ;
+ tempax = ( pVBInfo->VT - pVBInfo->VDE ) * pVBInfo->RVBHCFACT ;
+ tempax = ( tempax * pVBInfo->HT ) /tempbx ;
+
+ return( ( USHORT )tempax ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetVCLK2Ptr */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+USHORT XGI_GetVCLK2Ptr( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension ,PVB_DEVICE_INFO pVBInfo)
+{
+ USHORT tempbx ;
+
+ USHORT LCDXlat1VCLK[ 4 ] = { VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 } ;
+ USHORT LCDXlat2VCLK[ 4 ] = { VCLK108_2 + 5 , VCLK108_2 + 5 , VCLK108_2 + 5 , VCLK108_2 + 5 } ;
+ USHORT LVDSXlat1VCLK[ 4 ] = { VCLK40 , VCLK40 , VCLK40 , VCLK40 } ;
+ USHORT LVDSXlat2VCLK[ 4 ] = { VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 } ;
+ USHORT LVDSXlat3VCLK[ 4 ] = { VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 } ;
+
+ USHORT CRT2Index , VCLKIndex ;
+ USHORT modeflag , resinfo ;
+ UCHAR *CHTVVCLKPtr = NULL ;
+
+ if ( ModeNo <= 0x13 )
+ {
+ modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ResInfo */
+ resinfo = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ;
+ CRT2Index = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ;
+ }
+ else
+ {
+ modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; /* si+Ext_ResInfo */
+ resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;
+ CRT2Index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT2CRTC ;
+ }
+
+ if ( pVBInfo->IF_DEF_LVDS == 0 )
+ {
+ CRT2Index = CRT2Index >> 6 ; /* for LCD */
+ if ( ( ( pVBInfo->VBInfo & SetCRT2ToLCD ) | SetCRT2ToLCDA ) ) /*301b*/
+ {
+ if ( pVBInfo->LCDResInfo != Panel1024x768 )
+ {
+ VCLKIndex = LCDXlat2VCLK[ CRT2Index ] ;
+ }
+ else
+ {
+ VCLKIndex = LCDXlat1VCLK[ CRT2Index ] ;
+ }
+ }
+ else /* for TV */
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToTV )
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
+ {
+ if ( pVBInfo->SetFlag & RPLLDIV2XO )
+ {
+ VCLKIndex = HiTVVCLKDIV2 ;
+
+
+ VCLKIndex += 25 ;
+
+ }
+ else
+ {
+ VCLKIndex = HiTVVCLK ;
+
+
+ VCLKIndex += 25 ;
+
+ }
+
+ if ( pVBInfo->SetFlag & TVSimuMode )
+ {
+ if( modeflag & Charx8Dot )
+ {
+ VCLKIndex = HiTVSimuVCLK ;
+
+
+ VCLKIndex += 25 ;
+
+ }
+ else
+ {
+ VCLKIndex = HiTVTextVCLK ;
+
+
+ VCLKIndex += 25 ;
+
+ }
+ }
+
+ if ( pVBInfo->VBType & VB_XGI301LV ) /* 301lv */
+ {
+ if ( !( pVBInfo->VBExtInfo == VB_YPbPr1080i ) )
+ {
+ VCLKIndex = YPbPr750pVCLK ;
+ if ( !( pVBInfo->VBExtInfo == VB_YPbPr750p ) )
+ {
+ VCLKIndex = YPbPr525pVCLK ;
+ if ( !( pVBInfo->VBExtInfo == VB_YPbPr525p ) )
+ {
+ VCLKIndex = YPbPr525iVCLK_2 ;
+ if ( !( pVBInfo->SetFlag & RPLLDIV2XO ) )
+ VCLKIndex = YPbPr525iVCLK ;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( pVBInfo->VBInfo & SetCRT2ToTV )
+ {
+ if ( pVBInfo->SetFlag & RPLLDIV2XO )
+ {
+ VCLKIndex = TVVCLKDIV2 ;
+
+
+ VCLKIndex += 25 ;
+
+ }
+ else
+ {
+ VCLKIndex = TVVCLK ;
+
+
+ VCLKIndex += 25 ;
+
+ }
+ }
+ }
+ }
+ else
+ { /* for CRT2 */
+ VCLKIndex = ( UCHAR )XGINew_GetReg2( ( pVBInfo->P3ca + 0x02 ) ) ; /* Port 3cch */
+ VCLKIndex = ( ( VCLKIndex >> 2 ) & 0x03 ) ;
+ if ( ModeNo > 0x13 )
+ {
+ VCLKIndex = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRTVCLK ; /* di+Ext_CRTVCLK */
+ VCLKIndex &= IndexMask ;
+ }
+ }
+ }
+ }
+ else
+ { /* LVDS */
+ if ( ModeNo <= 0x13 )
+ VCLKIndex = CRT2Index ;
+ else
+ VCLKIndex = CRT2Index ;
+
+ if ( pVBInfo->IF_DEF_CH7005 == 1 )
+ {
+ if ( !( pVBInfo->VBInfo & SetCRT2ToLCD ) )
+ {
+ VCLKIndex &= 0x1f ;
+ tempbx = 0 ;
+
+ if ( pVBInfo->VBInfo & SetPALTV )
+ tempbx += 2 ;
+
+ if ( pVBInfo->VBInfo & SetCHTVOverScan )
+ tempbx += 1 ;
+
+ switch( tempbx )
+ {
+ case 0:
+ CHTVVCLKPtr = pVBInfo->CHTVVCLKUNTSC ;
+ break ;
+ case 1:
+ CHTVVCLKPtr = pVBInfo->CHTVVCLKONTSC ;
+ break;
+ case 2:
+ CHTVVCLKPtr = pVBInfo->CHTVVCLKUPAL ;
+ break ;
+ case 3:
+ CHTVVCLKPtr = pVBInfo->CHTVVCLKOPAL ;
+ break ;
+ default:
+ break ;
+ }
+
+ VCLKIndex = CHTVVCLKPtr[ VCLKIndex ] ;
+ }
+ }
+ else
+ {
+ VCLKIndex = VCLKIndex >> 6 ;
+ if ( ( pVBInfo->LCDResInfo == Panel800x600 ) || ( pVBInfo->LCDResInfo == Panel320x480 ) )
+ VCLKIndex = LVDSXlat1VCLK[ VCLKIndex ] ;
+ else if ( ( pVBInfo->LCDResInfo == Panel1024x768 ) || ( pVBInfo->LCDResInfo == Panel1024x768x75 ) )
+ VCLKIndex = LVDSXlat2VCLK[ VCLKIndex ] ;
+ else
+ VCLKIndex = LVDSXlat3VCLK[ VCLKIndex ] ;
+ }
+ }
+ /* VCLKIndex = VCLKIndex&IndexMask ; */
+
+
+
+ return( VCLKIndex ) ;
+}
+
diff --git a/drivers/staging/xgifb/vb_setmode.h b/drivers/staging/xgifb/vb_setmode.h
new file mode 100644
index 0000000..09753d7
--- /dev/null
+++ b/drivers/staging/xgifb/vb_setmode.h
@@ -0,0 +1,40 @@
+#ifndef _VBSETMODE_
+#define _VBSETMODE_
+
+extern void InitTo330Pointer(UCHAR,PVB_DEVICE_INFO);
+extern void XGI_UnLockCRT2(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+extern void XGI_LockCRT2(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+extern void XGI_LongWait( PVB_DEVICE_INFO );
+extern void XGI_SetCRT2ModeRegs(USHORT ModeNo,PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO );
+extern void XGI_DisableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+extern void XGI_EnableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+extern void XGI_DisplayOff( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO );
+extern void XGI_DisplayOn( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO );
+extern void XGI_GetVBType(PVB_DEVICE_INFO);
+extern void XGI_SenseCRT1(PVB_DEVICE_INFO );
+extern void XGI_GetVGAType(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+extern void XGI_GetVBInfo(USHORT ModeNo,USHORT ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+extern void XGI_GetTVInfo(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO );
+extern void XGI_SetCRT1Offset(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+extern void XGI_SetLCDAGroup(USHORT ModeNo,USHORT ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
+extern void XGI_WaitDisply( PVB_DEVICE_INFO );
+extern USHORT XGI_GetResInfo(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
+
+extern BOOLEAN XGISetModeNew( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo ) ;
+
+extern BOOLEAN XGI_SearchModeID( USHORT ModeNo,USHORT *ModeIdIndex, PVB_DEVICE_INFO );
+extern BOOLEAN XGI_GetLCDInfo(USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO );
+extern BOOLEAN XGI_BridgeIsOn( PVB_DEVICE_INFO );
+extern BOOLEAN XGI_SetCRT2Group301(USHORT ModeNo, PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO);
+extern USHORT XGI_GetRatePtrCRT2( PXGI_HW_DEVICE_INFO pXGIHWDE, USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO );
+
+extern void XGI_SetXG21FPBits(PVB_DEVICE_INFO pVBInfo);
+extern void XGI_SetXG27FPBits(PVB_DEVICE_INFO pVBInfo);
+extern void XGI_XG21BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
+extern void XGI_XG27BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
+extern void XGI_XG21SetPanelDelay(USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
+extern BOOLEAN XGI_XG21CheckLVDSMode(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
+extern void XGI_SetXG21LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
+extern USHORT XGI_GetLVDSOEMTableIndex(PVB_DEVICE_INFO pVBInfo);
+
+#endif
diff --git a/drivers/staging/xgifb/vb_struct.h b/drivers/staging/xgifb/vb_struct.h
new file mode 100644
index 0000000..bb25c0e
--- /dev/null
+++ b/drivers/staging/xgifb/vb_struct.h
@@ -0,0 +1,534 @@
+#ifndef _VB_STRUCT_
+#define _VB_STRUCT_
+
+#ifdef _INITNEW_
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+
+
+
+typedef struct _XGI_PanelDelayTblStruct
+{
+ UCHAR timer[2];
+} XGI_PanelDelayTblStruct;
+
+typedef struct _XGI_LCDDataStruct
+{
+ USHORT RVBHCMAX;
+ USHORT RVBHCFACT;
+ USHORT VGAHT;
+ USHORT VGAVT;
+ USHORT LCDHT;
+ USHORT LCDVT;
+} XGI_LCDDataStruct;
+
+
+typedef struct _XGI_LVDSCRT1HDataStruct
+{
+ UCHAR Reg[8];
+} XGI_LVDSCRT1HDataStruct;
+typedef struct _XGI_LVDSCRT1VDataStruct
+{
+ UCHAR Reg[7];
+} XGI_LVDSCRT1VDataStruct;
+
+
+typedef struct _XGI_TVDataStruct
+{
+ USHORT RVBHCMAX;
+ USHORT RVBHCFACT;
+ USHORT VGAHT;
+ USHORT VGAVT;
+ USHORT TVHDE;
+ USHORT TVVDE;
+ USHORT RVBHRS;
+ UCHAR FlickerMode;
+ USHORT HALFRVBHRS;
+ UCHAR RY1COE;
+ UCHAR RY2COE;
+ UCHAR RY3COE;
+ UCHAR RY4COE;
+} XGI_TVDataStruct;
+
+typedef struct _XGI_LVDSDataStruct
+{
+ USHORT VGAHT;
+ USHORT VGAVT;
+ USHORT LCDHT;
+ USHORT LCDVT;
+} XGI_LVDSDataStruct;
+
+typedef struct _XGI_LVDSDesStruct
+{
+ USHORT LCDHDES;
+ USHORT LCDVDES;
+} XGI_LVDSDesStruct;
+
+typedef struct _XGI_LVDSCRT1DataStruct
+{
+ UCHAR CR[15];
+} XGI_LVDSCRT1DataStruct;
+
+/*add for LCDA*/
+
+
+typedef struct _XGI_StStruct
+{
+ UCHAR St_ModeID;
+ USHORT St_ModeFlag;
+ UCHAR St_StTableIndex;
+ UCHAR St_CRT2CRTC;
+ UCHAR St_CRT2CRTC2;
+ UCHAR St_ResInfo;
+ UCHAR VB_StTVFlickerIndex;
+ UCHAR VB_StTVEdgeIndex;
+ UCHAR VB_StTVYFilterIndex;
+} XGI_StStruct;
+
+typedef struct _XGI_StandTableStruct
+{
+ UCHAR CRT_COLS;
+ UCHAR ROWS;
+ UCHAR CHAR_HEIGHT;
+ USHORT CRT_LEN;
+ UCHAR SR[4];
+ UCHAR MISC;
+ UCHAR CRTC[0x19];
+ UCHAR ATTR[0x14];
+ UCHAR GRC[9];
+} XGI_StandTableStruct;
+
+typedef struct _XGI_ExtStruct
+{
+ UCHAR Ext_ModeID;
+ USHORT Ext_ModeFlag;
+ USHORT Ext_ModeInfo;
+ USHORT Ext_Point;
+ USHORT Ext_VESAID;
+ UCHAR Ext_VESAMEMSize;
+ UCHAR Ext_RESINFO;
+ UCHAR VB_ExtTVFlickerIndex;
+ UCHAR VB_ExtTVEdgeIndex;
+ UCHAR VB_ExtTVYFilterIndex;
+ UCHAR REFindex;
+} XGI_ExtStruct;
+
+typedef struct _XGI_Ext2Struct
+{
+ USHORT Ext_InfoFlag;
+ UCHAR Ext_CRT1CRTC;
+ UCHAR Ext_CRTVCLK;
+ UCHAR Ext_CRT2CRTC;
+ UCHAR Ext_CRT2CRTC2;
+ UCHAR ModeID;
+ USHORT XRes;
+ USHORT YRes;
+ /* USHORT ROM_OFFSET; */
+} XGI_Ext2Struct;
+
+
+typedef struct _XGI_MCLKDataStruct
+{
+ UCHAR SR28,SR29,SR2A;
+ USHORT CLOCK;
+} XGI_MCLKDataStruct;
+
+typedef struct _XGI_ECLKDataStruct
+{
+ UCHAR SR2E,SR2F,SR30;
+ USHORT CLOCK;
+} XGI_ECLKDataStruct;
+
+typedef struct _XGI_VCLKDataStruct
+{
+ UCHAR SR2B,SR2C;
+ USHORT CLOCK;
+} XGI_VCLKDataStruct;
+
+typedef struct _XGI_VBVCLKDataStruct
+{
+ UCHAR Part4_A,Part4_B;
+ USHORT CLOCK;
+} XGI_VBVCLKDataStruct;
+
+typedef struct _XGI_StResInfoStruct
+{
+ USHORT HTotal;
+ USHORT VTotal;
+} XGI_StResInfoStruct;
+
+typedef struct _XGI_ModeResInfoStruct
+{
+ USHORT HTotal;
+ USHORT VTotal;
+ UCHAR XChar;
+ UCHAR YChar;
+} XGI_ModeResInfoStruct;
+
+typedef struct _XGI_LCDNBDesStruct
+{
+ UCHAR NB[12];
+} XGI_LCDNBDesStruct;
+ /*add for new UNIVGABIOS*/
+typedef struct _XGI_LCDDesStruct
+{
+ USHORT LCDHDES;
+ USHORT LCDHRS;
+ USHORT LCDVDES;
+ USHORT LCDVRS;
+} XGI_LCDDesStruct;
+
+typedef struct _XGI_LCDDataTablStruct
+{
+ UCHAR PANELID;
+ USHORT MASK;
+ USHORT CAP;
+ USHORT DATAPTR;
+} XGI_LCDDataTablStruct;
+
+typedef struct _XGI_TVTablDataStruct
+{
+ USHORT MASK;
+ USHORT CAP;
+ USHORT DATAPTR;
+} XGI_TVDataTablStruct;
+
+typedef struct _XGI330_LCDDesDataStruct
+{
+ USHORT LCDHDES;
+ USHORT LCDHRS;
+ USHORT LCDVDES;
+ USHORT LCDVRS;
+} XGI330_LCDDataDesStruct;
+
+
+typedef struct _XGI330_LVDSDataStruct
+{
+ USHORT VGAHT;
+ USHORT VGAVT;
+ USHORT LCDHT;
+ USHORT LCDVT;
+} XGI330_LVDSDataStruct;
+
+typedef struct _XGI330_LCDDesDataStruct2
+{
+ USHORT LCDHDES;
+ USHORT LCDHRS;
+ USHORT LCDVDES;
+ USHORT LCDVRS;
+ USHORT LCDHSync;
+ USHORT LCDVSync;
+} XGI330_LCDDataDesStruct2;
+
+typedef struct _XGI330_LCDDataStruct
+{
+ USHORT RVBHCMAX;
+ USHORT RVBHCFACT;
+ USHORT VGAHT;
+ USHORT VGAVT;
+ USHORT LCDHT;
+ USHORT LCDVT;
+} XGI330_LCDDataStruct;
+
+
+typedef struct _XGI330_TVDataStruct
+{
+ USHORT RVBHCMAX;
+ USHORT RVBHCFACT;
+ USHORT VGAHT;
+ USHORT VGAVT;
+ USHORT TVHDE;
+ USHORT TVVDE;
+ USHORT RVBHRS;
+ UCHAR FlickerMode;
+ USHORT HALFRVBHRS;
+} XGI330_TVDataStruct;
+
+typedef struct _XGI330_LCDDataTablStruct
+{
+ UCHAR PANELID;
+ USHORT MASK;
+ USHORT CAP;
+ USHORT DATAPTR;
+} XGI330_LCDDataTablStruct;
+
+typedef struct _XGI330_TVDataTablStruct
+{
+ USHORT MASK;
+ USHORT CAP;
+ USHORT DATAPTR;
+} XGI330_TVDataTablStruct;
+
+
+typedef struct _XGI330_CHTVDataStruct
+{
+ USHORT VGAHT;
+ USHORT VGAVT;
+ USHORT LCDHT;
+ USHORT LCDVT;
+} XGI330_CHTVDataStruct;
+
+typedef struct _XGI_TimingHStruct
+{
+ UCHAR data[8];
+} XGI_TimingHStruct;
+
+typedef struct _XGI_TimingVStruct
+{
+ UCHAR data[7];
+} XGI_TimingVStruct;
+
+typedef struct _XGI_CH7007TV_TimingHStruct
+{
+ UCHAR data[10];
+} XGI_CH7007TV_TimingHStruct;
+
+typedef struct _XGI_CH7007TV_TimingVStruct
+{
+ UCHAR data[10];
+} XGI_CH7007TV_TimingVStruct;
+
+typedef struct _XGI_XG21CRT1Struct
+{
+ UCHAR ModeID,CR02,CR03,CR15,CR16;
+} XGI_XG21CRT1Struct;
+
+typedef struct _XGI330_CHTVRegDataStruct
+{
+ UCHAR Reg[16];
+} XGI330_CHTVRegDataStruct;
+
+typedef struct _XGI330_LCDCapStruct
+{
+ UCHAR LCD_ID;
+ USHORT LCD_Capability;
+ UCHAR LCD_SetFlag;
+ UCHAR LCD_DelayCompensation;
+ UCHAR LCD_HSyncWidth;
+ UCHAR LCD_VSyncWidth;
+ UCHAR LCD_VCLK;
+ UCHAR LCDA_VCLKData1;
+ UCHAR LCDA_VCLKData2;
+ UCHAR LCUCHAR_VCLKData1;
+ UCHAR LCUCHAR_VCLKData2;
+ UCHAR PSC_S1;
+ UCHAR PSC_S2;
+ UCHAR PSC_S3;
+ UCHAR PSC_S4;
+ UCHAR PSC_S5;
+ UCHAR PWD_2B;
+ UCHAR PWD_2C;
+ UCHAR PWD_2D;
+ UCHAR PWD_2E;
+ UCHAR PWD_2F;
+ UCHAR Spectrum_31;
+ UCHAR Spectrum_32;
+ UCHAR Spectrum_33;
+ UCHAR Spectrum_34;
+} XGI330_LCDCapStruct;
+
+typedef struct _XGI21_LVDSCapStruct
+{
+ USHORT LVDS_Capability;
+ USHORT LVDSHT;
+ USHORT LVDSVT;
+ USHORT LVDSHDE;
+ USHORT LVDSVDE;
+ USHORT LVDSHFP;
+ USHORT LVDSVFP;
+ USHORT LVDSHSYNC;
+ USHORT LVDSVSYNC;
+ UCHAR VCLKData1;
+ UCHAR VCLKData2;
+ UCHAR PSC_S1;
+ UCHAR PSC_S2;
+ UCHAR PSC_S3;
+ UCHAR PSC_S4;
+ UCHAR PSC_S5;
+} XGI21_LVDSCapStruct;
+
+typedef struct _XGI_CRT1TableStruct
+{
+ UCHAR CR[16];
+} XGI_CRT1TableStruct;
+
+
+typedef struct _XGI330_VCLKDataStruct
+{
+ UCHAR SR2B,SR2C;
+ USHORT CLOCK;
+} XGI330_VCLKDataStruct;
+
+typedef struct _XGI301C_Tap4TimingStruct
+{
+ USHORT DE;
+ UCHAR Reg[64]; /* C0-FF */
+} XGI301C_Tap4TimingStruct;
+
+typedef struct _XGI_New_StandTableStruct
+{
+ UCHAR CRT_COLS;
+ UCHAR ROWS;
+ UCHAR CHAR_HEIGHT;
+ USHORT CRT_LEN;
+ UCHAR SR[4];
+ UCHAR MISC;
+ UCHAR CRTC[0x19];
+ UCHAR ATTR[0x14];
+ UCHAR GRC[9];
+} XGI_New_StandTableStruct;
+
+typedef UCHAR DRAM8Type[8];
+typedef UCHAR DRAM4Type[4];
+typedef UCHAR DRAM32Type[32];
+typedef UCHAR DRAM2Type[2];
+
+typedef struct _VB_DEVICE_INFO VB_DEVICE_INFO;
+typedef VB_DEVICE_INFO * PVB_DEVICE_INFO;
+
+struct _VB_DEVICE_INFO
+{
+ BOOLEAN ISXPDOS;
+ ULONG P3c4,P3d4,P3c0,P3ce,P3c2,P3cc;
+ ULONG P3ca,P3c6,P3c7,P3c8,P3c9,P3da;
+ ULONG Part0Port,Part1Port,Part2Port;
+ ULONG Part3Port,Part4Port,Part5Port;
+ USHORT RVBHCFACT,RVBHCMAX,RVBHRS;
+ USHORT VGAVT,VGAHT,VGAVDE,VGAHDE;
+ USHORT VT,HT,VDE,HDE;
+ USHORT LCDHRS,LCDVRS,LCDHDES,LCDVDES;
+
+ USHORT ModeType;
+ USHORT IF_DEF_LVDS,IF_DEF_TRUMPION,IF_DEF_DSTN;/* ,IF_DEF_FSTN; add for dstn */
+ USHORT IF_DEF_CRT2Monitor,IF_DEF_VideoCapture;
+ USHORT IF_DEF_LCDA,IF_DEF_CH7017,IF_DEF_YPbPr,IF_DEF_ScaleLCD,IF_DEF_OEMUtil,IF_DEF_PWD;
+ USHORT IF_DEF_ExpLink;
+ USHORT IF_DEF_CH7005,IF_DEF_HiVision;
+ USHORT IF_DEF_CH7007; /* Billy 2007/05/03 */
+ USHORT LCDResInfo,LCDTypeInfo, VBType;/*301b*/
+ USHORT VBInfo,TVInfo,LCDInfo, Set_VGAType;
+ USHORT VBExtInfo;/*301lv*/
+ USHORT SetFlag;
+ USHORT NewFlickerMode;
+ USHORT SelectCRT2Rate;
+
+ PUCHAR ROMAddr;
+ PUCHAR FBAddr;
+ ULONG BaseAddr;
+ ULONG RelIO;
+
+ DRAM4Type *CR6B;
+ DRAM4Type *CR6E;
+ DRAM32Type *CR6F;
+ DRAM2Type *CR89;
+
+ DRAM8Type *SR15; /* pointer : point to array */
+ DRAM8Type *CR40;
+ UCHAR *pSoftSetting;
+ UCHAR *pOutputSelect;
+
+ USHORT *pRGBSenseData;
+ USHORT *pRGBSenseData2; /*301b*/
+ USHORT *pVideoSenseData;
+ USHORT *pVideoSenseData2;
+ USHORT *pYCSenseData;
+ USHORT *pYCSenseData2;
+
+ UCHAR *pSR07;
+ UCHAR *CR49;
+ UCHAR *pSR1F;
+ UCHAR *AGPReg;
+ UCHAR *SR16;
+ UCHAR *pSR21;
+ UCHAR *pSR22;
+ UCHAR *pSR23;
+ UCHAR *pSR24;
+ UCHAR *SR25;
+ UCHAR *pSR31;
+ UCHAR *pSR32;
+ UCHAR *pSR33;
+ UCHAR *pSR36; /* alan 12/07/2006 */
+ UCHAR *pCRCF;
+ UCHAR *pCRD0; /* alan 12/07/2006 */
+ UCHAR *pCRDE; /* alan 12/07/2006 */
+ UCHAR *pCR8F; /* alan 12/07/2006 */
+ UCHAR *pSR40; /* alan 12/07/2006 */
+ UCHAR *pSR41; /* alan 12/07/2006 */
+ UCHAR *pDVOSetting;
+ UCHAR *pCR2E;
+ UCHAR *pCR2F;
+ UCHAR *pCR46;
+ UCHAR *pCR47;
+ UCHAR *pCRT2Data_1_2;
+ UCHAR *pCRT2Data_4_D;
+ UCHAR *pCRT2Data_4_E;
+ UCHAR *pCRT2Data_4_10;
+ XGI_MCLKDataStruct *MCLKData;
+ XGI_ECLKDataStruct *ECLKData;
+
+ UCHAR *XGI_TVDelayList;
+ UCHAR *XGI_TVDelayList2;
+ UCHAR *CHTVVCLKUNTSC;
+ UCHAR *CHTVVCLKONTSC;
+ UCHAR *CHTVVCLKUPAL;
+ UCHAR *CHTVVCLKOPAL;
+ UCHAR *NTSCTiming;
+ UCHAR *PALTiming;
+ UCHAR *HiTVExtTiming;
+ UCHAR *HiTVSt1Timing;
+ UCHAR *HiTVSt2Timing;
+ UCHAR *HiTVTextTiming;
+ UCHAR *YPbPr750pTiming;
+ UCHAR *YPbPr525pTiming;
+ UCHAR *YPbPr525iTiming;
+ UCHAR *HiTVGroup3Data;
+ UCHAR *HiTVGroup3Simu;
+ UCHAR *HiTVGroup3Text;
+ UCHAR *Ren525pGroup3;
+ UCHAR *Ren750pGroup3;
+ UCHAR *ScreenOffset;
+ UCHAR *pXGINew_DRAMTypeDefinition;
+ UCHAR *pXGINew_I2CDefinition ;
+ UCHAR *pXGINew_CR97 ;
+
+ XGI330_LCDCapStruct *LCDCapList;
+ XGI21_LVDSCapStruct *XG21_LVDSCapList;
+
+ XGI_TimingHStruct *TimingH;
+ XGI_TimingVStruct *TimingV;
+
+ XGI_StStruct *SModeIDTable;
+ XGI_StandTableStruct *StandTable;
+ XGI_ExtStruct *EModeIDTable;
+ XGI_Ext2Struct *RefIndex;
+ /* XGINew_CRT1TableStruct *CRT1Table; */
+ XGI_CRT1TableStruct *XGINEWUB_CRT1Table;
+ XGI_VCLKDataStruct *VCLKData;
+ XGI_VBVCLKDataStruct *VBVCLKData;
+ XGI_StResInfoStruct *StResInfo;
+ XGI_ModeResInfoStruct *ModeResInfo;
+ XGI_XG21CRT1Struct *UpdateCRT1;
+}; /* _VB_DEVICE_INFO */
+
+
+typedef struct
+{
+ USHORT Horizontal_ACTIVE;
+ USHORT Horizontal_FP;
+ USHORT Horizontal_SYNC;
+ USHORT Horizontal_BP;
+ USHORT Vertical_ACTIVE;
+ USHORT Vertical_FP;
+ USHORT Vertical_SYNC;
+ USHORT Vertical_BP;
+ double DCLK;
+ UCHAR FrameRate;
+ UCHAR Interlace;
+ USHORT Margin;
+} TimingInfo;
+
+#define _VB_STRUCT_
+#endif /* _VB_STRUCT_ */
diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h
new file mode 100644
index 0000000..781caef
--- /dev/null
+++ b/drivers/staging/xgifb/vb_table.h
@@ -0,0 +1,4406 @@
+#define Tap4
+
+
+XGI_MCLKDataStruct XGI330New_MCLKData[]=
+{
+ { 0x5c,0x23,0x01,166},
+ { 0x5c,0x23,0x01,166},
+ { 0x7C,0x08,0x80,200},
+ { 0x79,0x06,0x80,250},
+ { 0x29,0x01,0x81,300},
+ { 0x29,0x01,0x81,300},
+ { 0x29,0x01,0x81,300},
+ { 0x29,0x01,0x81,300}
+};
+//yilin modify for xgi20
+XGI_MCLKDataStruct XGI340New_MCLKData[]=
+{
+ { 0x16,0x01,0x01,166},
+ { 0x19,0x02,0x01,124},
+ { 0x7C,0x08,0x01,200},
+ { 0x79,0x06,0x01,250},
+ { 0x29,0x01,0x81,301},
+ { 0x5c,0x23,0x01,166},
+ { 0x5c,0x23,0x01,166},
+ { 0x5c,0x23,0x01,166}
+};
+
+XGI_MCLKDataStruct XGI27New_MCLKData[]=
+{
+ { 0x5c,0x23,0x01,166},
+ { 0x19,0x02,0x01,124},
+ { 0x7C,0x08,0x80,200},
+ { 0x79,0x06,0x80,250},
+ { 0x29,0x01,0x81,300},
+ { 0x5c,0x23,0x01,166},
+ { 0x5c,0x23,0x01,166},
+ { 0x5c,0x23,0x01,166}
+};
+
+XGI_ECLKDataStruct XGI330_ECLKData[]=
+{
+ { 0x7c,0x08,0x01,200},
+ { 0x7c,0x08,0x01,200},
+ { 0x7C,0x08,0x80,200},
+ { 0x79,0x06,0x80,250},
+ { 0x29,0x01,0x81,300},
+ { 0x29,0x01,0x81,300},
+ { 0x29,0x01,0x81,300},
+ { 0x29,0x01,0x81,300}
+};
+//yilin modify for xgi20
+XGI_ECLKDataStruct XGI340_ECLKData[]=
+{
+ { 0x5c,0x23,0x01,166},
+ { 0x55,0x84,0x01,123},
+ { 0x7C,0x08,0x01,200},
+ { 0x79,0x06,0x01,250},
+ { 0x29,0x01,0x81,301},
+ { 0x5c,0x23,0x01,166},
+ { 0x5c,0x23,0x01,166},
+ { 0x5c,0x23,0x01,166}
+};
+
+
+
+UCHAR XGI340_SR13[4][8]={
+{0x35,0x45,0xb1,0x00,0x00,0x00,0x00,0x00},/* SR13 */
+{0x41,0x51,0x5c,0x00,0x00,0x00,0x00,0x00},/* SR14 */
+{0x31,0x42,0x42,0x00,0x00,0x00,0x00,0x00},/* SR18 */
+{0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00}/* SR1B */
+};
+
+UCHAR XGI340_cr41[24][8]=
+{{0x20,0x50,0x60,0x00,0x00,0x00,0x00,0x00},/* 0 CR41 */
+{0xc4,0x40,0x84,0x00,0x00,0x00,0x00,0x00},/* 1 CR8A */
+{0xc4,0x40,0x84,0x00,0x00,0x00,0x00,0x00},/* 2 CR8B */
+{0xb5,0xa4,0xa4,0x00,0x00,0x00,0x00,0x00},
+{0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00},
+{0x90,0x90,0x24,0x00,0x00,0x00,0x00,0x00},/* 5 CR68 */
+{0x77,0x77,0x44,0x00,0x00,0x00,0x00,0x00},/* 6 CR69 */
+{0x77,0x77,0x44,0x00,0x00,0x00,0x00,0x00},/* 7 CR6A */
+{0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00},/* 8 CR6D */
+{0x55,0x55,0x55,0x00,0x00,0x00,0x00,0x00},/* 9 CR80 */
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/* 10 CR81 */
+{0x88,0xa8,0x48,0x00,0x00,0x00,0x00,0x00},/* 11 CR82 */
+{0x44,0x44,0x77,0x00,0x00,0x00,0x00,0x00},/* 12 CR85 */
+{0x48,0x48,0x88,0x00,0x00,0x00,0x00,0x00},/* 13 CR86 */
+{0x54,0x54,0x44,0x00,0x00,0x00,0x00,0x00},/* 14 CR90 */
+{0x54,0x54,0x44,0x00,0x00,0x00,0x00,0x00},/* 15 CR91 */
+{0x0a,0x0a,0x07,0x00,0x00,0x00,0x00,0x00},/* 16 CR92 */
+{0x44,0x44,0x44,0x00,0x00,0x00,0x00,0x00},/* 17 CR93 */
+{0x10,0x10,0x0A,0x00,0x00,0x00,0x00,0x00},/* 18 CR94 */
+{0x11,0x11,0x0a,0x00,0x00,0x00,0x00,0x00},/* 19 CR95 */
+{0x05,0x05,0x05,0x00,0x00,0x00,0x00,0x00},/* 20 CR96 */
+{0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00},/* 21 CRC3 */
+{0x05,0x00,0x02,0x00,0x00,0x00,0x00,0x00},/* 22 CRC4 */
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}/* 23 CRC5 */
+};
+
+
+UCHAR XGI27_cr41[24][8]=
+{
+{0x20,0x40,0x60,0x00,0x00,0x00,0x00,0x00},/* 0 CR41 */
+{0xC4,0x40,0x84,0x00,0x00,0x00,0x00,0x00},/* 1 CR8A */
+{0xC4,0x40,0x84,0x00,0x00,0x00,0x00,0x00},/* 2 CR8B */
+{0xB5,0x13,0xa4,0x00,0x00,0x00,0x00,0x00},/* 3 CR40[7],CR99[2:0],CR45[3:0]*/
+{0xf0,0xf5,0xf0,0x00,0x00,0x00,0x00,0x00},/* 4 CR59 */
+{0x90,0x90,0x24,0x00,0x00,0x00,0x00,0x00},/* 5 CR68 */
+{0x77,0x67,0x44,0x00,0x00,0x00,0x00,0x00},/* 6 CR69 */
+{0x77,0x77,0x44,0x00,0x00,0x00,0x00,0x00},/* 7 CR6A */
+{0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00},/* 8 CR6D */
+{0x55,0x55,0x55,0x00,0x00,0x00,0x00,0x00},/* 9 CR80 */
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/* 10 CR81 */
+{0x88,0xcc,0x48,0x00,0x00,0x00,0x00,0x00},/* 11 CR82 */
+{0x44,0x88,0x77,0x00,0x00,0x00,0x00,0x00},/* 12 CR85 */
+{0x48,0x88,0x88,0x00,0x00,0x00,0x00,0x00},/* 13 CR86 */
+{0x54,0x32,0x44,0x00,0x00,0x00,0x00,0x00},/* 14 CR90 */
+{0x54,0x33,0x44,0x00,0x00,0x00,0x00,0x00},/* 15 CR91 */
+{0x0a,0x07,0x07,0x00,0x00,0x00,0x00,0x00},/* 16 CR92 */
+{0x44,0x63,0x44,0x00,0x00,0x00,0x00,0x00},/* 17 CR93 */
+{0x10,0x14,0x0A,0x00,0x00,0x00,0x00,0x00},/* 18 CR94 */
+{0x11,0x0B,0x0C,0x00,0x00,0x00,0x00,0x00},/* 19 CR95 */
+{0x05,0x22,0x05,0x00,0x00,0x00,0x00,0x00},/* 20 CR96 */
+{0xf0,0xf0,0x00,0x00,0x00,0x00,0x00,0x00},/* 21 CRC3 */
+{0x05,0x00,0x02,0x00,0x00,0x00,0x00,0x00},/* 22 CRC4 */
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}/* 23 CRC5 */
+};
+
+
+#if 0
+UCHAR XGI27_cr41[24][8]=
+{
+{0x20,0x60,0x60,0x00,0x00,0x00,0x00,0x00},/* 0 CR41 */
+{0x04,0x44,0x84,0x00,0x00,0x00,0x00,0x00},/* 1 CR8A */
+{0x04,0x40,0x84,0x00,0x00,0x00,0x00,0x00},/* 2 CR8B */
+{0xb5,0x03,0xa4,0x00,0x00,0x00,0x00,0x00},/* 3 CR40[7],CR99[2:0],CR45[3:0]*/
+{0xf0,0xf5,0xf0,0x00,0x00,0x00,0x00,0x00},/* 4 CR59 */
+{0xa4,0x1C,0x24,0x00,0x00,0x00,0x00,0x00},/* 5 CR68 */
+{0x77,0x77,0x44,0x00,0x00,0x00,0x00,0x00},/* 6 CR69 */
+{0x77,0x77,0x44,0x00,0x00,0x00,0x00,0x00},/* 7 CR6A */
+{0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00},/* 8 CR6D */
+{0x55,0x55,0x55,0x00,0x00,0x00,0x00,0x00},/* 9 CR80 */
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/* 10 CR81 */
+{0x48,0xa8,0x48,0x00,0x00,0x00,0x00,0x00},/* 11 CR82 */
+{0x77,0x88,0x77,0x00,0x00,0x00,0x00,0x00},/* 12 CR85 */
+{0x88,0x88,0x88,0x00,0x00,0x00,0x00,0x00},/* 13 CR86 */
+{0x44,0x32,0x44,0x00,0x00,0x00,0x00,0x00},/* 14 CR90 */
+{0x44,0x33,0x44,0x00,0x00,0x00,0x00,0x00},/* 15 CR91 */
+{0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00},/* 16 CR92 */
+{0x44,0x63,0x44,0x00,0x00,0x00,0x00,0x00},/* 17 CR93 */
+{0x0A,0x14,0x0A,0x00,0x00,0x00,0x00,0x00},/* 18 CR94 */
+{0x0C,0x0B,0x0C,0x00,0x00,0x00,0x00,0x00},/* 19 CR95 */
+{0x05,0x22,0x05,0x00,0x00,0x00,0x00,0x00},/* 20 CR96 */
+{0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00},/* 21 CRC3 */
+{0x03,0x00,0x02,0x00,0x00,0x00,0x00,0x00},/* 22 CRC4 */
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}/* 23 CRC5 */
+};
+#endif
+UCHAR XGI340_CR6B[8][4]={
+{0xaa,0xaa,0xaa,0xaa},
+{0xaa,0xaa,0xaa,0xaa},
+{0xaa,0xaa,0xaa,0xaa},
+{0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00}
+};
+
+UCHAR XGI340_CR6E[8][4]={
+{0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00}
+};
+
+UCHAR XGI340_CR6F[8][32]={
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
+};
+
+UCHAR XGI340_CR89[8][2]={
+{0x00,0x00},
+{0x00,0x00},
+{0x00,0x00},
+{0x00,0x00},
+{0x00,0x00},
+{0x00,0x00},
+{0x00,0x00},
+{0x00,0x00}
+};
+ /* CR47,CR48,CR49,CR4A,CR4B,CR4C,CR70,CR71,CR74,CR75,CR76,CR77 */
+UCHAR XGI340_AGPReg[12]={0x28,0x23,0x00,0x20,0x00,0x20,0x00,0x05,0xd0,0x10,0x10,0x00};
+
+UCHAR XGI340_SR16[4]={0x03,0x83,0x03,0x83};
+
+UCHAR XGI330_SR15_1[8][8]={
+{0x0,0x0,0x00,0x00,0x20,0x20,0x00,0x00},
+{0x5,0x15,0x15,0x15,0x15,0x15,0x00,0x00},
+{0xba,0xba,0xba,0xba,0xBA,0xBA,0x00,0x00},
+{0x55,0x57,0x57,0xAB,0xAB,0xAB,0x00,0x00},
+{0x60,0x34,0x34,0x34,0x34,0x34,0x00,0x00},
+{0x0,0x80,0x80,0x80,0x83,0x83,0x00,0x00},
+{0x50,0x50,0x50,0x3C,0x3C,0x3C,0x00,0x00},
+{0x0,0xa5,0xfb,0xf6,0xF6,0xF6,0x00,0x00}
+};
+
+UCHAR XGI330_cr40_1[15][8]={
+{0x66,0x40,0x40,0x28,0x24,0x24,0x00,0x00},
+{0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x0F,0x0F,0x00,0x00},
+{0x00,0xf0,0xf0,0xf0,0xF0,0xF0,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x10,0x10,0x10,0x10,0x20,0x20,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x88,0x88,0x88,0xAA,0xAC,0xAC,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x77,0x77,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+{0x00,0xA2,0x00,0x00,0xA2,0xA2,0x00,0x00},
+};
+
+UCHAR XGI330_sr25[]={0x00,0x0};
+UCHAR XGI330_sr31=0xc0;
+UCHAR XGI330_sr32=0x11;
+UCHAR XGI330_SR33=0x00;
+UCHAR XG40_CRCF=0x13;
+UCHAR XG40_DRAMTypeDefinition=0xFF ;
+
+XGI_StStruct XGI330_SModeIDTable[]=
+{
+ {0x01,0x9208,0x01,0x00,0x10,0x00,0x00,0x01,0x00},
+ {0x01,0x1210,0x14,0x01,0x00,0x01,0x00,0x01,0x00},
+ {0x01,0x1010,0x17,0x02,0x11,0x00,0x00,0x01,0x01},
+ {0x03,0x8208,0x03,0x00,0x14,0x00,0x00,0x01,0x02},
+ {0x03,0x0210,0x16,0x01,0x04,0x01,0x00,0x01,0x02},
+ {0x03,0x0010,0x18,0x02,0x15,0x00,0x00,0x01,0x03},
+ {0x05,0x9209,0x05,0x00,0x10,0x00,0x00,0x00,0x04},
+ {0x06,0x8209,0x06,0x00,0x14,0x00,0x00,0x00,0x05},
+ {0x07,0x0000,0x07,0x03,0x05,0x03,0x00,0x01,0x03},
+ {0x07,0x0000,0x19,0x02,0x15,0x02,0x00,0x01,0x03},
+ {0x0d,0x920a,0x0d,0x00,0x10,0x00,0x00,0x00,0x04},
+ {0x0e,0x820a,0x0e,0x00,0x14,0x00,0x00,0x00,0x05},
+ {0x0f,0x0202,0x11,0x01,0x04,0x01,0x00,0x00,0x05},
+ {0x10,0x0212,0x12,0x01,0x04,0x01,0x00,0x00,0x05},
+ {0x11,0x0212,0x1a,0x04,0x24,0x04,0x00,0x00,0x05},
+ {0x12,0x0212,0x1b,0x04,0x24,0x04,0x00,0x00,0x05},
+ {0x13,0x021b,0x1c,0x00,0x14,0x00,0x00,0x00,0x04},
+ {0x12,0x0010,0x18,0x02,0x24,0x02,0x00,0x00,0x05},/* St_CRT2CRTC2 not sure */
+ {0x12,0x0210,0x18,0x01,0x24,0x01,0x00,0x00,0x05},/* St_CRT2CRTC2 not sure */
+ {0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
+};
+
+
+XGI_ExtStruct XGI330_EModeIDTable[]=
+{
+ {0x6a,0x2212,0x0407,0x3a81,0x0102,0x08,0x07,0x00,0x00,0x07,0x0e},
+ {0x2e,0x0a1b,0x0306,0x3a57,0x0101,0x08,0x06,0x00,0x00,0x05,0x06},
+ {0x2f,0x0a1b,0x0305,0x3a50,0x0100,0x08,0x05,0x00,0x00,0x05,0x05},
+ {0x30,0x2a1b,0x0407,0x3a81,0x0103,0x08,0x07,0x00,0x00,0x07,0x0e},
+ {0x31,0x0a1b,0x030d,0x3b85,0x0000,0x08,0x0d,0x00,0x00,0x06,0x3d},
+ {0x32,0x0a1b,0x0a0e,0x3b8c,0x0000,0x08,0x0e,0x00,0x00,0x06,0x3e},
+ {0x33,0x0a1d,0x0a0d,0x3b85,0x0000,0x08,0x0d,0x00,0x00,0x06,0x3d},
+ {0x34,0x2a1d,0x0a0e,0x3b8c,0x0000,0x08,0x0e,0x00,0x00,0x06,0x3e},
+ {0x35,0x0a1f,0x0a0d,0x3b85,0x0000,0x08,0x0d,0x00,0x00,0x06,0x3d},
+ {0x36,0x2a1f,0x0a0e,0x3b8c,0x0000,0x08,0x0e,0x00,0x00,0x06,0x3e},
+ {0x37,0x0212,0x0508,0x3aab,0x0104,0x08,0x08,0x00,0x00,0x00,0x16},
+ {0x38,0x0a1b,0x0508,0x3aab,0x0105,0x08,0x08,0x00,0x00,0x00,0x16},
+ {0x3a,0x0e3b,0x0609,0x3adc,0x0107,0x08,0x09,0x00,0x00,0x00,0x1e},
+ {0x3c,0x0e3b,0x070a,0x3af2,0x0130,0x08,0x0a,0x00,0x00,0x00,0x22}, /* mode 1600x1200 add CRT2MODE [2003/10/07] */
+ {0x3d,0x0e7d,0x070a,0x3af2,0x0131,0x08,0x0a,0x00,0x00,0x00,0x22}, /* mode 1600x1200 add CRT2MODE */
+ {0x40,0x9a1c,0x0000,0x3a34,0x010d,0x08,0x00,0x00,0x00,0x04,0x00},
+ {0x41,0x9a1d,0x0000,0x3a34,0x010e,0x08,0x00,0x00,0x00,0x04,0x00}, /* ModeIdIndex = 0x10 */
+ {0x43,0x0a1c,0x0306,0x3a57,0x0110,0x08,0x06,0x00,0x00,0x05,0x06},
+ {0x44,0x0a1d,0x0306,0x3a57,0x0111,0x08,0x06,0x00,0x00,0x05,0x06},
+ {0x46,0x2a1c,0x0407,0x3a81,0x0113,0x08,0x07,0x00,0x00,0x07,0x0e},
+ {0x47,0x2a1d,0x0407,0x3a81,0x0114,0x08,0x07,0x00,0x00,0x07,0x0e},
+ {0x49,0x0a3c,0x0508,0x3aab,0x0116,0x08,0x08,0x00,0x00,0x00,0x16},
+ {0x4a,0x0a3d,0x0508,0x3aab,0x0117,0x08,0x08,0x00,0x00,0x00,0x16},
+ {0x4c,0x0e7c,0x0609,0x3adc,0x0119,0x08,0x09,0x00,0x00,0x00,0x1e},
+ {0x4d,0x0e7d,0x0609,0x3adc,0x011a,0x08,0x09,0x00,0x00,0x00,0x1e},
+ {0x50,0x9a1b,0x0001,0x3a3b,0x0132,0x08,0x01,0x00,0x00,0x04,0x02},
+ {0x51,0xba1b,0x0103,0x3a42,0x0133,0x08,0x03,0x00,0x00,0x07,0x03},
+ {0x52,0x9a1b,0x0204,0x3a49,0x0134,0x08,0x04,0x00,0x00,0x00,0x04},
+ {0x56,0x9a1d,0x0001,0x3a3b,0x0135,0x08,0x01,0x00,0x00,0x04,0x02},
+ {0x57,0xba1d,0x0103,0x3a42,0x0136,0x08,0x03,0x00,0x00,0x07,0x03},
+ {0x58,0x9a1d,0x0204,0x3a49,0x0137,0x08,0x04,0x00,0x00,0x00,0x04},
+ {0x59,0x9a1b,0x0000,0x3a34,0x0138,0x08,0x00,0x00,0x00,0x04,0x00},
+ {0x5A,0x021b,0x0014,0x3b83,0x0138,0x08,0x01,0x00,0x00,0x04,0x3f}, /* ModeIdIndex = 0x20 */
+ {0x5B,0x0a1d,0x0014,0x3b83,0x0135,0x08,0x01,0x00,0x00,0x04,0x3f},
+ {0x5d,0x0a1d,0x0305,0x3a50,0x0139,0x08,0x05,0x00,0x00,0x07,0x05},
+ {0x62,0x0a3f,0x0306,0x3a57,0x013a,0x08,0x06,0x00,0x00,0x05,0x06},
+ {0x63,0x2a3f,0x0407,0x3a81,0x013b,0x08,0x07,0x00,0x00,0x07,0x0e},
+ {0x64,0x0a7f,0x0508,0x3aab,0x013c,0x08,0x08,0x00,0x00,0x00,0x16},
+ {0x65,0x0eff,0x0609,0x3adc,0x013d,0x08,0x09,0x00,0x00,0x00,0x1e},
+ {0x66,0x0eff,0x070a,0x3af2,0x013e,0x08,0x0a,0x00,0x00,0x00,0x22}, /* mode 1600x1200 add CRT2MODE */
+ {0x68,0x067b,0x080b,0x3b17,0x013f,0x08,0x0b,0x00,0x00,0x00,0x29},
+ {0x69,0x06fd,0x080b,0x3b17,0x0140,0x08,0x0b,0x00,0x00,0x00,0x29},
+ {0x6b,0x07ff,0x080b,0x3b17,0x0141,0x10,0x0b,0x00,0x00,0x00,0x29},
+ {0x6c,0x067b,0x090c,0x3b37,0x0000,0x08,0x0c,0x00,0x00,0x00,0x2f},
+ {0x6d,0x06fd,0x090c,0x3b37,0x0000,0x10,0x0c,0x00,0x00,0x00,0x2f},
+ {0x6e,0x07ff,0x090c,0x3b37,0x0000,0x10,0x0c,0x00,0x00,0x00,0x2f},
+ {0x70,0x2a1b,0x0410,0x3b52,0x0000,0x08,0x10,0x00,0x00,0x07,0x34},
+ {0x71,0x0a1b,0x0511,0x3b63,0x0000,0x08,0x11,0x00,0x00,0x00,0x37},
+ {0x74,0x0a1d,0x0511,0x3b63,0x0000,0x08,0x11,0x00,0x00,0x00,0x37}, /* ModeIdIndex = 0x30 */
+ {0x75,0x0a3d,0x0612,0x3b74,0x0000,0x08,0x12,0x00,0x00,0x00,0x3a},
+ {0x76,0x2a1f,0x0410,0x3b52,0x0000,0x08,0x10,0x00,0x00,0x07,0x34},
+ {0x77,0x0a1f,0x0511,0x3b63,0x0000,0x08,0x11,0x00,0x00,0x00,0x37},
+ {0x78,0x0a3f,0x0612,0x3b74,0x0000,0x08,0x12,0x00,0x00,0x00,0x3a},
+ {0x79,0x0a3b,0x0612,0x3b74,0x0000,0x08,0x12,0x00,0x00,0x00,0x3a},
+ {0x7a,0x2a1d,0x0410,0x3b52,0x0000,0x08,0x10,0x00,0x00,0x07,0x34},
+ {0x7b,0x0e3b,0x060f,0x3ad0,0x0000,0x08,0x0f,0x00,0x00,0x00,0x1d},
+ {0x7c,0x0e7d,0x060f,0x3ad0,0x0000,0x08,0x0f,0x00,0x00,0x00,0x1d},
+ {0x7d,0x0eff,0x060f,0x3ad0,0x0000,0x08,0x0f,0x00,0x00,0x00,0x1d},
+ {0x20,0x0e3b,0x0D16,0x49e0,0x0000,0x08,0x16,0x00,0x00,0x00,0x43},
+ {0x21,0x0e7d,0x0D16,0x49e0,0x0000,0x08,0x16,0x00,0x00,0x00,0x43},
+ {0x22,0x0eff,0x0D16,0x49e0,0x0000,0x08,0x16,0x00,0x00,0x00,0x43},
+ {0x23,0x0e3b,0x0614,0x49d5,0x0000,0x08,0x14,0x00,0x00,0x00,0x41},
+ {0x24,0x0e7d,0x0614,0x49d5,0x0000,0x08,0x14,0x00,0x00,0x00,0x41},
+ {0x25,0x0eff,0x0614,0x49d5,0x0000,0x08,0x14,0x00,0x00,0x00,0x41},
+ {0x26,0x063b,0x0c15,0x49dc,0x0000,0x08,0x15,0x00,0x00,0x00,0x42}, /* ModeIdIndex = 0x40 */
+ {0x27,0x067d,0x0c15,0x49dc,0x0000,0x08,0x15,0x00,0x00,0x00,0x42},
+ {0x28,0x06ff,0x0c15,0x49dc,0x0000,0x08,0x15,0x00,0x00,0x00,0x42},
+ {0xff,0x0000,0x0000,0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00}
+};
+
+XGI_StandTableStruct XGI330_StandTable[]=
+{
+/* MD_0_200 */
+ {
+ 0x28,0x18,0x08,0x0800,
+ {0x09,0x03,0x00,0x02},
+ 0x63,
+ {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+ 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
+ 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,
+ 0xff},
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x08,0x00,0x0f,0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+ 0xff}
+ },
+/* MD_1_200 */
+ {
+ 0x28,0x18,0x08,0x0800,
+ {0x09,0x03,0x00,0x02},
+ 0x63,
+ {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+ 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
+ 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,
+ 0xff},
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x08,0x00,0x0f,0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+ 0xff}
+ },
+/* MD_2_200 */
+ {
+ 0x50,0x18,0x08,0x1000,
+ {0x01,0x03,0x00,0x02},
+ 0x63,
+ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+ 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
+ 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
+ 0xff},
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x08,0x00,0x0f,0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+ 0xff}
+ },
+/* MD_3_200 */
+ {
+ 0x50,0x18,0x08,0x1000,
+ {0x01,0x03,0x00,0x02},
+ 0x63,
+ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+ 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
+ 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
+ 0xff},
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x08,0x00,0x0f,0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+ 0xff}
+ },
+/* MD_4 */
+ {
+ 0x28,0x18,0x08,0x4000,
+ {0x09,0x03,0x00,0x02},
+ 0x63,
+ {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
+ 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2,
+ 0xff},
+ {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x01,0x00,0x03,0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x00,
+ 0xff}
+ },
+/* MD_5 */
+ {
+ 0x28,0x18,0x08,0x4000,
+ {0x09,0x03,0x00,0x02},
+ 0x63,
+ {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
+ 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2,
+ 0xff},
+ {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x01,0x00,0x03,0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x00,
+ 0xff}
+ },
+/* MD_6 */
+ {
+ 0x50,0x18,0x08,0x4000,
+ {0x01,0x01,0x00,0x06},
+ 0x63,
+ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+ 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xc2,
+ 0xff},
+ {0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
+ 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
+ 0x01,0x00,0x01,0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x00,
+ 0xff}
+ },
+/* MD_7 */
+ {
+ 0x50,0x18,0x0e,0x1000,
+ {0x00,0x03,0x00,0x03},
+ 0xa6,
+ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+ 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
+ 0x83,0x85,0x5d,0x28,0x0d,0x63,0xba,0xa3,
+ 0xff},
+ {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+ 0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+ 0x0e,0x00,0x0f,0x08},
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x00,
+ 0xff}
+ },
+/* MDA_DAC */
+ {
+ 0x00,0x00,0x00,0x0000,
+ {0x00,0x00,0x00,0x15},
+ 0x15,
+ {0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+ 0x15,0x15,0x15,0x15,0x15,0x15,0x3f,0x3f,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x00,0x00,
+ 0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x15,0x15,0x15,
+ 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+ 0x15,0x15,0x15,0x15},
+ {0x15,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x3f}
+ },
+/* CGA_DAC */
+ {
+ 0x00,0x10,0x04,0x0114,
+ {0x11,0x09,0x15,0x00},
+ 0x10,
+ {0x04,0x14,0x01,0x11,0x09,0x15,0x2a,0x3a,
+ 0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x2a,0x3a,
+ 0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x00,0x10,
+ 0x04},
+ {0x14,0x01,0x11,0x09,0x15,0x00,0x10,0x04,
+ 0x14,0x01,0x11,0x09,0x15,0x2a,0x3a,0x2e,
+ 0x3e,0x2b,0x3b,0x2f},
+ {0x3f,0x2a,0x3a,0x2e,0x3e,0x2b,0x3b,0x2f,
+ 0x3f}
+ },
+/* EGA_DAC */
+ {
+ 0x00,0x10,0x04,0x0114,
+ {0x11,0x05,0x15,0x20},
+ 0x30,
+ {0x24,0x34,0x21,0x31,0x25,0x35,0x08,0x18,
+ 0x0c,0x1c,0x09,0x19,0x0d,0x1d,0x28,0x38,
+ 0x2c,0x3c,0x29,0x39,0x2d,0x3d,0x02,0x12,
+ 0x06},
+ {0x16,0x03,0x13,0x07,0x17,0x22,0x32,0x26,
+ 0x36,0x23,0x33,0x27,0x37,0x0a,0x1a,0x0e,
+ 0x1e,0x0b,0x1b,0x0f},
+ {0x1f,0x2a,0x3a,0x2e,0x3e,0x2b,0x3b,0x2f,
+ 0x3f}
+ },
+/* VGA_DAC */
+ {
+ 0x00,0x10,0x04,0x0114,
+ {0x11,0x09,0x15,0x2a},
+ 0x3a,
+ {0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x00,0x05,
+ 0x08,0x0b,0x0e,0x11,0x14,0x18,0x1c,0x20,
+ 0x24,0x28,0x2d,0x32,0x38,0x3f,0x00,0x10,
+ 0x1f},
+ {0x2f,0x3f,0x1f,0x27,0x2f,0x37,0x3f,0x2d,
+ 0x31,0x36,0x3a,0x3f,0x00,0x07,0x0e,0x15,
+ 0x1c,0x0e,0x11,0x15},
+ {0x18,0x1c,0x14,0x16,0x18,0x1a,0x1c,0x00,
+ 0x04}
+ },
+ {
+ 0x08,0x0c,0x10,0x0a08,
+ {0x0c,0x0e,0x10,0x0b},
+ 0x0c,
+ {0x0d,0x0f,0x10,0x10,0x01,0x08,0x00,0x00,
+ 0x00,0x00,0x01,0x00,0x02,0x02,0x01,0x00,
+ 0x04,0x04,0x01,0x00,0x05,0x02,0x05,0x00,
+ 0x06},
+ {0x01,0x06,0x05,0x06,0x00,0x08,0x01,0x08,
+ 0x00,0x07,0x02,0x07,0x06,0x07,0x00,0x00,
+ 0x00,0x00,0x00,0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00}
+ },
+/* MD_D */
+ {
+ 0x28,0x18,0x08,0x2000,
+ {0x09,0x0f,0x00,0x06},
+ 0x63,
+ {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
+ 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xe3,
+ 0xff},
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x01,0x00,0x0f,0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
+ 0xff}
+ },
+/* MD_E */
+ {
+ 0x50,0x18,0x08,0x4000,
+ {0x01,0x0f,0x00,0x06},
+ 0x63,
+ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+ 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xe3,
+ 0xff},
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x01,0x00,0x0f,0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
+ 0xff}
+ },
+/* ExtVGATable */
+ {
+ 0x00,0x00,0x00,0x0000,
+ {0x01,0x0f,0x00,0x0e},
+ 0x23,
+ {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
+ 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
+ 0xff},
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
+ 0x01,0x00,0x00,0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
+ 0xff}
+ },
+/* ROM_SAVEPTR */
+ {
+ 0x9f,0x3b,0x00,0x00c0,
+ {0x00,0x00,0x00,0x00},
+ 0x00,
+ {0x00,0x00,0x00,0x00,0x00,0x00,0xbb,0x3f,
+ 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x1a,0x00,0xac,0x3e,0x00,0xc0,
+ 0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00}
+ },
+/* MD_F */
+ {
+ 0x50,0x18,0x0e,0x8000,
+ {0x01,0x0f,0x00,0x06},
+ 0xa2,
+ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+ 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x82,0x84,0x5d,0x28,0x0f,0x63,0xba,0xe3,
+ 0xff},
+ {0x00,0x08,0x00,0x00,0x18,0x18,0x00,0x00,
+ 0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,
+ 0x0b,0x00,0x05,0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x05,
+ 0xff}
+ },
+/* MD_10 */
+ {
+ 0x50,0x18,0x0e,0x8000,
+ {0x01,0x0f,0x00,0x06},
+ 0xa3,
+ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+ 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x82,0x84,0x5d,0x28,0x0f,0x63,0xba,0xe3,
+ 0xff},
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+ 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+ 0x01,0x00,0x0f,0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
+ 0xff}
+ },
+/* MD_0_350 */
+ {
+ 0x28,0x18,0x0e,0x0800,
+ {0x09,0x03,0x00,0x02},
+ 0xa3,
+ {0x2d,0x27,0x28,0x90,0x2b,0xb1,0xbf,0x1f,
+ 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
+ 0x83,0x85,0x5d,0x14,0x1f,0x63,0xba,0xa3,
+ 0xff},
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+ 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+ 0x08,0x00,0x0f,0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+ 0xff}
+ },
+/* MD_1_350 */
+ {
+ 0x28,0x18,0x0e,0x0800,
+ {0x09,0x03,0x00,0x02},
+ 0xa3,
+ {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+ 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
+ 0x83,0x85,0x5d,0x14,0x1f,0x63,0xba,0xa3,
+ 0xff},
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+ 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+ 0x08,0x00,0x0f,0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+ 0xff}
+ },
+/* MD_2_350 */
+ {
+ 0x50,0x18,0x0e,0x1000,
+ {0x01,0x03,0x00,0x02},
+ 0xa3,
+ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+ 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
+ 0x83,0x85,0x5d,0x28,0x1f,0x63,0xba,0xa3,
+ 0xff},
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+ 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+ 0x08,0x00,0x0f,0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+ 0xff}
+ },
+/* MD_3_350 */
+ {
+ 0x50,0x18,0x0e,0x1000,
+ {0x01,0x03,0x00,0x02},
+ 0xa3,
+ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+ 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
+ 0x83,0x85,0x5d,0x28,0x1f,0x63,0xba,0xa3,
+ 0xff},
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+ 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+ 0x08,0x00,0x0f,0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+ 0xff}
+ },
+/* MD_0_1_400 */
+ {
+ 0x28,0x18,0x10,0x0800,
+ {0x08,0x03,0x00,0x02},
+ 0x67,
+ {0x2d,0x27,0x28,0x90,0x2b,0xb1,0xbf,0x1f,
+ 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
+ 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,
+ 0xff},
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+ 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+ 0x0c,0x00,0x0f,0x08},
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+ 0xff}
+ },
+/* MD_2_3_400 */
+ {
+ 0x50,0x18,0x10,0x1000,
+ {0x00,0x03,0x00,0x02},
+ 0x67,
+ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+ 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
+ 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
+ 0xff},
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+ 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+ 0x0c,0x00,0x0f,0x08},
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+ 0xff}
+ },
+/* MD_7_400 */
+ {
+ 0x50,0x18,0x10,0x1000,
+ {0x00,0x03,0x00,0x02},
+ 0x66,
+ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+ 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
+ 0x9c,0x8e,0x8f,0x28,0x0f,0x96,0xb9,0xa3,
+ 0xff},
+ {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+ 0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+ 0x0e,0x00,0x0f,0x08},
+ {0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x00,
+ 0xff}
+ },
+/* MD_11 */
+ {
+ 0x50,0x1d,0x10,0xa000,
+ {0x01,0x0f,0x00,0x06},
+ 0xe3,
+ {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e,
+ 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xc3,
+ 0xff},
+ {0x00,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+ 0x01,0x00,0x0f,0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x01,
+ 0xff}
+ },
+/* ExtEGATable */
+ {
+ 0x50,0x1d,0x10,0xa000,
+ {0x01,0x0f,0x00,0x06},
+ 0xe3,
+ {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e,
+ 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xe3,
+ 0xff},
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+ 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+ 0x01,0x00,0x0f,0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
+ 0xff}
+ },
+/* MD_13 */
+ {
+ 0x28,0x18,0x08,0x2000,
+ {0x01,0x0f,0x00,0x0e},
+ 0x63,
+ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+ 0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x9c,0x8e,0x8f,0x28,0x40,0x96,0xb9,0xa3,
+ 0xff},
+ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
+ 0x41,0x00,0x0f,0x00},
+ {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
+ 0xff}
+ }
+};
+
+XGI_TimingHStruct XGI_TimingH[]=
+{{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}};
+
+XGI_TimingVStruct XGI_TimingV[]=
+{{{0x00,0x00,0x00,0x00,0x00,0x00,0x00}}};
+
+XGI_XG21CRT1Struct XGI_UpdateCRT1Table[]=
+{
+ {0x01,0x27,0x91,0x8f,0xc0}, /* 00 */
+ {0x03,0x4f,0x83,0x8f,0xc0}, /* 01 */
+ {0x05,0x27,0x91,0x8f,0xc0}, /* 02 */
+ {0x06,0x4f,0x83,0x8f,0xc0}, /* 03 */
+ {0x07,0x4f,0x83,0x8f,0xc0}, /* 04 */
+ {0x0d,0x27,0x91,0x8f,0xc0}, /* 05 */
+ {0x0e,0x4f,0x83,0x8f,0xc0}, /* 06 */
+ {0x0f,0x4f,0x83,0x5d,0xc0}, /* 07 */
+ {0x10,0x4f,0x83,0x5d,0xc0}, /* 08 */
+ {0x11,0x4f,0x83,0xdf,0x0c}, /* 09 */
+ {0x12,0x4f,0x83,0xdf,0x0c}, /* 10 */
+ {0x13,0x4f,0x83,0x8f,0xc0}, /* 11 */
+ {0x2e,0x4f,0x83,0xdf,0x0c}, /* 12 */
+ {0x2e,0x4f,0x87,0xdf,0xc0}, /* 13 */
+ {0x2f,0x4f,0x83,0x8f,0xc0}, /* 14 */
+ {0x50,0x27,0x91,0xdf,0x0c}, /* 15 */
+ {0x59,0x27,0x91,0x8f,0xc0} /* 16 */
+};
+
+XGI_CRT1TableStruct XGI_CRT1Table[]=
+{
+ {{0x2d,0x28,0x90,0x2c,0x90,0x00,0x04,0x00,
+ 0xbf,0x1f,0x9c,0x8e,0x96,0xb9,0x30}}, /* 0x0 */
+ {{0x2d,0x28,0x90,0x2c,0x90,0x00,0x04,0x00,
+ 0x0b,0x3e,0xe9,0x8b,0xe7,0x04,0x00}}, /* 0x1 */
+ {{0x3D,0x31,0x81,0x37,0x1F,0x00,0x05,0x00,
+ 0x72,0xF0,0x58,0x8C,0x57,0x73,0xA0}}, /* 0x2 */
+ {{0x4F,0x3F,0x93,0x45,0x0D,0x00,0x01,0x00,
+ 0x24,0xF5,0x02,0x88,0xFF,0x25,0x90}}, /* 0x3 */
+ {{0x5F,0x50,0x82,0x55,0x81,0x00,0x05,0x00,
+ 0xBF,0x1F,0x9C,0x8E,0x96,0xB9,0x30}}, /* 0x4 */
+ {{0x5F,0x50,0x82,0x55,0x81,0x00,0x05,0x00,
+ 0x0B,0x3E,0xE9,0x8B,0xE7,0x04,0x00}}, /* 0x5 */
+ {{0x63,0x50,0x86,0x56,0x9B,0x00,0x01,0x00,
+ 0x06,0x3E,0xE8,0x8B,0xE7,0xFF,0x10}}, /* 0x6 */
+ {{0x64,0x4F,0x88,0x55,0x9D,0x00,0x01,0x00,
+ 0xF2,0x1F,0xE0,0x83,0xDF,0xF3,0x10}}, /* 0x7 */
+ {{0x63,0x4F,0x87,0x5A,0x81,0x00,0x05,0x00,
+ 0xFB,0x1F,0xE0,0x83,0xDF,0xFC,0x10}}, /* 0x8 */
+ {{0x65,0x4F,0x89,0x58,0x80,0x00,0x05,0x60,
+ 0xFB,0x1F,0xE0,0x83,0xDF,0xFC,0x80}}, /* 0x9 */
+ {{0x65,0x4F,0x89,0x58,0x80,0x00,0x05,0x60,
+ 0x01,0x3E,0xE0,0x83,0xDF,0x02,0x80}}, /* 0xa */
+ {{0x67,0x4F,0x8B,0x58,0x81,0x00,0x05,0x60,
+ 0x0D,0x3E,0xE0,0x83,0xDF,0x0E,0x90}}, /* 0xb */
+ {{0x65,0x4F,0x89,0x57,0x9F,0x00,0x01,0x00,
+ 0xFB,0x1F,0xE6,0x8A,0xDF,0xFC,0x10}}, /* 0xc */
+ {{0x7B,0x63,0x9F,0x6A,0x93,0x00,0x05,0x00, /* ; 0D (800x600,56Hz) */
+ 0x6F,0xF0,0x58,0x8A,0x57,0x70,0xA0}}, /* ; (VCLK 36.0MHz) */
+ {{0x7F,0x63,0x83,0x6C,0x1C,0x00,0x06,0x00, /* ; 0E (800x600,60Hz) */
+ 0x72,0xF0,0x58,0x8C,0x57,0x73,0xA0}}, /* ; (VCLK 40.0MHz) */
+ {{0x7D,0x63,0x81,0x6E,0x1D,0x00,0x06,0x00, /* ; 0F (800x600,72Hz) */
+ 0x98,0xF0,0x7C,0x82,0x57,0x99,0x80}}, /* ; (VCLK 50.0MHz) */
+ {{0x7F,0x63,0x83,0x69,0x13,0x00,0x06,0x00, /* ; 10 (800x600,75Hz) */
+ 0x6F,0xF0,0x58,0x8B,0x57,0x70,0xA0}}, /* ; (VCLK 49.5MHz) */
+ {{0x7E,0x63,0x82,0x6B,0x13,0x00,0x06,0x00, /* ; 11 (800x600,85Hz) */
+ 0x75,0xF0,0x58,0x8B,0x57,0x76,0xA0}}, /* ; (VCLK 56.25MHz) */
+ {{0x81,0x63,0x85,0x6D,0x18,0x00,0x06,0x60, /* ; 12 (800x600,100Hz) */
+ 0x7A,0xF0,0x58,0x8B,0x57,0x7B,0xA0}}, /* ; (VCLK 75.8MHz) */
+ {{0x83,0x63,0x87,0x6E,0x19,0x00,0x06,0x60, /* ; 13 (800x600,120Hz) */
+ 0x81,0xF0,0x58,0x8B,0x57,0x82,0xA0}}, /* ; (VCLK 79.411MHz) */
+ {{0x85,0x63,0x89,0x6F,0x1A,0x00,0x06,0x60, /* ; 14 (800x600,160Hz) */
+ 0x91,0xF0,0x58,0x8B,0x57,0x92,0xA0}}, /* ; (VCLK 105.822MHz) */
+ {{0x99,0x7F,0x9D,0x84,0x1A,0x00,0x02,0x00,
+ 0x96,0x1F,0x7F,0x83,0x7F,0x97,0x10}}, /* 0x15 */
+ {{0xA3,0x7F,0x87,0x86,0x97,0x00,0x02,0x00,
+ 0x24,0xF5,0x02,0x88,0xFF,0x25,0x90}}, /* 0x16 */
+ {{0xA1,0x7F,0x85,0x86,0x97,0x00,0x02,0x00,
+ 0x24,0xF5,0x02,0x88,0xFF,0x25,0x90}}, /* 0x17 */
+ {{0x9F,0x7F,0x83,0x85,0x91,0x00,0x02,0x00,
+ 0x1E,0xF5,0x00,0x83,0xFF,0x1F,0x90}}, /* 0x18 */
+ {{0xA7,0x7F,0x8B,0x89,0x95,0x00,0x02,0x00,
+ 0x26,0xF5,0x00,0x83,0xFF,0x27,0x90}}, /* 0x19 */
+ {{0xA9,0x7F,0x8D,0x8C,0x9A,0x00,0x02,0x62,
+ 0x2C,0xF5,0x00,0x83,0xFF,0x2D,0x14}}, /* 0x1a */
+ {{0xAB,0x7F,0x8F,0x8D,0x9B,0x00,0x02,0x62,
+ 0x35,0xF5,0x00,0x83,0xFF,0x36,0x14}}, /* 0x1b */
+ {{0xCF,0x9F,0x93,0xB2,0x01,0x00,0x03,0x00,
+ 0x14,0xBA,0x00,0x83,0xFF,0x15,0x00}}, /* 0x1c */
+ {{0xCE,0x9F,0x92,0xA9,0x17,0x00,0x07,0x00,
+ 0x28,0x5A,0x00,0x83,0xFF,0x29,0x89}}, /* 0x1d */
+ {{0xCE,0x9F,0x92,0xA5,0x17,0x00,0x07,0x00,
+ 0x28,0x5A,0x00,0x83,0xFF,0x29,0x89}}, /* 0x1e */
+ {{0xD3,0x9F,0x97,0xAB,0x1F,0x00,0x07,0x00,
+ 0x2E,0x5A,0x00,0x83,0xFF,0x2F,0x89}}, /* 0x1f */
+ {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00,
+ 0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x20 */
+ {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00,
+ 0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x21 */
+ {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00,
+ 0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x22 */
+ {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00,
+ 0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x23 */
+ {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00,
+ 0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x24 */
+ {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00,
+ 0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x25 */
+ {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00,
+ 0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x26 */
+ {{0x40,0xEF,0x84,0x03,0x1D,0x41,0x01,0x00,
+ 0xDA,0x1F,0xA0,0x83,0x9F,0xDB,0x1F}}, /* 0x27 */
+ {{0x43,0xEF,0x87,0x06,0x00,0x41,0x05,0x62,
+ 0xD4,0x1F,0xA0,0x83,0x9F,0xD5,0x9F}}, /* 0x28 */
+ {{0x45,0xEF,0x89,0x07,0x01,0x41,0x05,0x62,
+ 0xD9,0x1F,0xA0,0x83,0x9F,0xDA,0x9F}}, /* 0x29 */
+ {{0x40,0xEF,0x84,0x03,0x1D,0x41,0x01,0x00,
+ 0xDA,0x1F,0xA0,0x83,0x9F,0xDB,0x1F}}, /* 0x2a */
+ {{0x40,0xEF,0x84,0x03,0x1D,0x41,0x01,0x00,
+ 0xDA,0x1F,0xA0,0x83,0x9F,0xDB,0x1F}}, /* 0x2b */
+ {{0x40,0xEF,0x84,0x03,0x1D,0x41,0x01,0x00,
+ 0xDA,0x1F,0xA0,0x83,0x9F,0xDB,0x1F}}, /* 0x2c */
+ {{0x59,0xFF,0x9D,0x17,0x13,0x41,0x05,0x44,
+ 0x33,0xBA,0x00,0x83,0xFF,0x34,0x0F}}, /* 0x2d */
+ {{0x5B,0xFF,0x9F,0x18,0x14,0x41,0x05,0x44,
+ 0x38,0xBA,0x00,0x83,0xFF,0x39,0x0F}}, /* 0x2e */
+ {{0x5B,0xFF,0x9F,0x18,0x14,0x41,0x05,0x44,
+ 0x3D,0xBA,0x00,0x83,0xFF,0x3E,0x0F}}, /* 0x2f */
+ {{0x5D,0xFF,0x81,0x19,0x95,0x41,0x05,0x44,
+ 0x41,0xBA,0x00,0x84,0xFF,0x42,0x0F}}, /* 0x30 */
+ {{0x55,0xFF,0x99,0x0D,0x0C,0x41,0x05,0x00,
+ 0x3E,0xBA,0x00,0x84,0xFF,0x3F,0x0F}}, /* 0x31 */
+ {{0x7F,0x63,0x83,0x6C,0x1C,0x00,0x06,0x00,
+ 0x72,0xBA,0x27,0x8B,0xDF,0x73,0x80}}, /* 0x32 */
+ {{0x7F,0x63,0x83,0x69,0x13,0x00,0x06,0x00,
+ 0x6F,0xBA,0x26,0x89,0xDF,0x6F,0x80}}, /* 0x33 */
+ {{0x7F,0x63,0x82,0x6B,0x13,0x00,0x06,0x00,
+ 0x75,0xBA,0x29,0x8C,0xDF,0x75,0x80}}, /* 0x34 */
+ {{0xA3,0x7F,0x87,0x86,0x97,0x00,0x02,0x00,
+ 0x24,0xF1,0xAF,0x85,0x3F,0x25,0xB0}}, /* 0x35 */
+ {{0x9F,0x7F,0x83,0x85,0x91,0x00,0x02,0x00,
+ 0x1E,0xF1,0xAD,0x81,0x3F,0x1F,0xB0}}, /* 0x36 */
+ {{0xA7,0x7F,0x88,0x89,0x15,0x00,0x02,0x00,
+ 0x26,0xF1,0xB1,0x85,0x3F,0x27,0xB0}}, /* 0x37 */
+ {{0xCE,0x9F,0x92,0xA9,0x17,0x00,0x07,0x00,
+ 0x28,0xC4,0x7A,0x8E,0xCF,0x29,0xA1}}, /* 0x38 */
+ {{0xCE,0x9F,0x92,0xA5,0x17,0x00,0x07,0x00,
+ 0x28,0xD4,0x7A,0x8E,0xCF,0x29,0xA1}}, /* 0x39 */
+ {{0xD3,0x9F,0x97,0xAB,0x1F,0x00,0x07,0x00,
+ 0x2E,0xD4,0x7D,0x81,0xCF,0x2F,0xA1}}, /* 0x3a */
+ {{0xDC,0x9F,0x00,0xAB,0x19,0x00,0x07,0x00,
+ 0xE6,0xEF,0xC0,0xC3,0xBF,0xE7,0x90}}, /* 0x3b */
+ {{0x6B,0x59,0x8F,0x5E,0x8C,0x00,0x05,0x00,
+ 0x0B,0x3E,0xE9,0x8B,0xE7,0x04,0x00}}, /* 0x3c */
+ {{0x7B,0x63,0x9F,0x6A,0x93,0x00,0x05,0x00,
+ 0x6F,0xF0,0x58,0x8A,0x57,0x70,0xA0}}, /* 0x3d */
+ {{0x86,0x6A,0x8a,0x74,0x06,0x00,0x02,0x00,
+ 0x8c,0x15,0x4f,0x83,0xef,0x8d,0x30}}, /* 0x3e */
+ {{0x81,0x6A,0x85,0x70,0x00,0x00,0x02,0x00,
+ 0x0f,0x3e,0xeb,0x8e,0xdf,0x10,0x00}}, /* 0x3f */
+ {{0xCE,0x9F,0x92,0xA9,0x17,0x00,0x07,0x00,
+ 0x20,0xF5,0x03,0x88,0xFF,0x21,0x90}}, /* 0x40 */
+ {{0xE6,0xAE,0x8A,0xBD,0x90,0x00,0x03,0x00,
+ 0x3D,0x10,0x1A,0x8D,0x19,0x3E,0x2F}}, /* 0x41 */
+ {{0xB9,0x8F,0x9D,0x9B,0x8A,0x00,0x06,0x00,
+ 0x7D,0xFF,0x60,0x83,0x5F,0x7E,0x90}}, /* 0x42 */
+ {{0xC3,0x8F,0x87,0x9B,0x0B,0x00,0x07,0x00,
+ 0x82,0xFF,0x60,0x83,0x5F,0x83,0x90}}, /* 0x43 */
+ {{0xAD,0x7F,0x91,0x8E,0x9C,0x00,0x02,0x82,
+ 0x49,0xF5,0x00,0x83,0xFF,0x4A,0x90}}, /* 0x44 */
+ {{0xCD,0x9F,0x91,0xA7,0x19,0x00,0x07,0x60,
+ 0xE6,0xFF,0xC0,0x83,0xBF,0xE7,0x90}}, /* 0x45 */
+ {{0xD3,0x9F,0x97,0xAB,0x1F,0x00,0x07,0x60,
+ 0xF1,0xFF,0xC0,0x83,0xBF,0xF2,0x90}}, /* 0x46 */
+ {{0xD7,0x9F,0x9B,0xAC,0x1E,0x00,0x07,0x00,
+ 0x03,0xDE,0xC0,0x84,0xBF,0x04,0x90}} /* 0x47 */
+};
+
+XGI330_CHTVRegDataStruct XGI_CHTVRegUNTSC[] = {
+ /* Index:000h,001h,002h,004h,003h,005h,006h,007h,008h,015h,01Fh,00Ch,00Dh,00Eh,00Fh,010h */
+ {{ 0x4A,0x77,0xBB,0x94,0x84,0x48,0xFE,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 00 (640x200,640x400) */
+ {{ 0x4A,0x77,0xBB,0x94,0x84,0x48,0xFE,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 01 (640x350) */
+ {{ 0x4A,0x77,0xBB,0x94,0x84,0x48,0xFE,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 02 (720x400) */
+ {{ 0x4A,0x77,0xBB,0x94,0x84,0x48,0xFE,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 03 (720x350) */
+ {{ 0x6A,0x77,0xBB,0x6E,0x84,0x2E,0x02,0x5A,0x04,0x00,0x80,0x20,0x7E,0x80,0x97,0x00 }},/* 04 (640x480) ;;5/6/02 */
+ {{ 0xCF,0x77,0xB7,0xC8,0x84,0x3B,0x02,0x5A,0x04,0x00,0x80,0x19,0x88,0xAE,0xA3,0x00 }},/* 05 (800x600) ;;1/12/02 */
+ {{ 0xEE,0x77,0xBB,0x66,0x87,0x32,0x01,0x5A,0x04,0x00,0x80,0x1B,0xD4,0x2F,0x6F,0x00 }}/* 06 (1024x768) ;;5/6/02 */
+ };
+
+XGI330_CHTVRegDataStruct XGI_CHTVRegONTSC[]= {
+ /* Index:000h,001h,002h,004h,003h,005h,006h,007h,008h,015h,01Fh,00Ch,00Dh,00Eh,00Fh,010h */
+ {{ 0x49,0x77,0xBB,0x7B,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 00 (640x200,640x400) */
+ {{ 0x49,0x77,0xBB,0x7B,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 01 (640x350) */
+ {{ 0x49,0x77,0xBB,0x7B,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 02 (720x400) */
+ {{ 0x49,0x77,0xBB,0x7B,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 03 (720x350) */
+ {{ 0x69,0x77,0xBB,0x6E,0x84,0x1E,0x00,0x5A,0x04,0x00,0x80,0x25,0x1A,0x80,0x26,0x00 }},/* 04 (640x480) ;;5/6/02 */
+ {{ 0xCE,0x77,0xB7,0xB6,0x83,0x2C,0x02,0x5A,0x04,0x00,0x80,0x1C,0x00,0x82,0x97,0x00 }},/* 05 (800x600) ;;5/6/02 */
+ {{ 0xED,0x77,0xBB,0x66,0x8C,0x21,0x02,0x5A,0x04,0x00,0x80,0x1F,0xA0,0x7E,0x73,0x00 }}/* 06 (1024x768) ;;5/6/02 */
+ };
+
+XGI330_CHTVRegDataStruct XGI_CHTVRegUPAL[]= {
+ /* Index:000h,001h,002h,004h,003h,005h,006h,007h,008h,015h,01Fh,00Ch,00Dh,00Eh,00Fh,010h */
+ {{ 0x41,0x7F,0xB7,0x34,0xAD,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* ; 00 (640x200,640x400) */
+ {{ 0x41,0x7F,0xB7,0x80,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* ; 01 (640x350) */
+ {{ 0x41,0x7F,0xB7,0x34,0xAD,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* ; 02 (720x400) */
+ {{ 0x41,0x7F,0xB7,0x12,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* ; 03 (720x350) */
+ {{ 0x61,0x7F,0xB7,0x99,0x84,0x35,0x04,0x5A,0x05,0x00,0x80,0x26,0x2A,0x55,0x5D,0x00 }},/* ; 04 (640x480) */
+ {{ 0xC3,0x7F,0xB7,0x7A,0x84,0x40,0x02,0x5A,0x05,0x00,0x80,0x1F,0x84,0x3D,0x28,0x00 }},/* ; 05 (800x600) ;;1/12/02 */
+ {{ 0xE5,0x7F,0xB7,0x1D,0xA7,0x3E,0x04,0x5A,0x05,0x00,0x80,0x20,0x3E,0xE4,0x22,0x00 }}/* ; 06 (1024x768) ;;1/12/02 */
+ };
+
+XGI330_CHTVRegDataStruct XGI_CHTVRegOPAL[]={
+ /* Index:000,0x01,0x02,0x04,0x03,0x05,0x06,0x07,0x08,0x15,0x1F,0x0C,0x0D,0x0E,0x0F,0x10h */
+ {{ 0x41,0x7F,0xB7,0x36,0xAD,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 00 (640x200,640x400) */
+ {{ 0x41,0x7F,0xB7,0x86,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 01 (640x350) */
+ {{ 0x41,0x7F,0xB7,0x36,0xAD,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 02 (720x400) */
+ {{ 0x41,0x7F,0xB7,0x86,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 03 (720x350) */
+ {{ 0x61,0x7F,0xB7,0x99,0x84,0x35,0x04,0x5A,0x05,0x00,0x80,0x26,0x2A,0x55,0x5D,0x00 }},/* 04 (640x480) */
+ {{ 0xC1,0x7F,0xB7,0x4D,0x8C,0x1E,0x31,0x5A,0x05,0x00,0x80,0x26,0x78,0x19,0x34,0x00 }},/* 05 (800x600) ;;1/12/02 */
+ {{ 0xE4,0x7F,0xB7,0x1E,0xAF,0x29,0x37,0x5A,0x05,0x00,0x80,0x25,0x8C,0xB2,0x2A,0x00 }}/* 06 (1024x768) ;;1/12/02 */
+ };
+
+UCHAR XGI_CH7017LV1024x768[]={0x60,0x02,0x00,0x07,0x40,0xED,0xA3,
+ 0xC8,0xC7,0xAC,0xE0,0x02};
+UCHAR XGI_CH7017LV1400x1050[]={0x60,0x03,0x11,0x00,0x40,0xE3,0xAD,
+ 0xDB,0xF6,0xAC,0xE0,0x02};
+
+
+/*add for new UNIVGABIOS*/
+XGI330_LCDDataStruct XGI_StLCD1024x768Data[]=
+{
+ { 62, 25, 800, 546,1344, 806},
+ { 32, 15, 930, 546,1344, 806},
+ { 62, 25, 800, 546,1344, 806}, /* chiawen for dot9 -> dot8 */
+ { 104, 45, 945, 496,1344, 806},
+ { 62, 25, 800, 546,1344, 806},
+ { 31, 18,1008, 624,1344, 806},
+ { 1, 1,1344, 806,1344, 806}
+};
+
+XGI330_LCDDataStruct XGI_ExtLCD1024x768Data[]=
+{
+ { 42, 25,1536, 419,1344, 806}, /* { 12, 5, 896, 512,1344, 806}, // alan 09/12/2003 */
+ { 48, 25,1536, 369,1344, 806}, /* { 12, 5, 896, 510,1344, 806}, // alan 09/12/2003 */
+ { 42, 25,1536, 419,1344, 806}, /* { 32, 15,1008, 505,1344, 806}, // alan 09/12/2003 */
+ { 48, 25,1536, 369,1344, 806}, /* { 32, 15,1008, 514,1344, 806}, // alan 09/12/2003 */
+ { 12, 5, 896, 500,1344, 806},
+ { 42, 25,1024, 625,1344, 806},
+ { 1, 1,1344, 806,1344, 806},
+ { 12, 5, 896, 500,1344, 806},
+ { 42, 25,1024, 625,1344, 806},
+ { 1, 1,1344, 806,1344, 806},
+ { 12, 5, 896, 500,1344, 806},
+ { 42, 25,1024, 625,1344, 806},
+ { 1, 1,1344, 806,1344, 806}
+};
+
+/*XGI330_LCDDataStruct XGI_St2LCD1024x768Data[]=
+{
+ { 62, 25, 800, 546,1344, 806},
+ { 32, 15, 930, 546,1344, 806},
+ { 62, 25, 800, 546,1344, 806},
+ { 104, 45, 945, 496,1344, 806},
+ { 62, 25, 800, 546,1344, 806},
+ { 31, 18,1008, 624,1344, 806},
+ { 1, 1,1344, 806,1344, 806}
+};*/
+
+XGI330_LCDDataStruct XGI_CetLCD1024x768Data[]=
+{
+ { 1,1,1344,806,1344,806 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+ { 1,1,1344,806,1344,806 }, /* 01 (320x350,640x350) */
+ { 1,1,1344,806,1344,806 }, /* 02 (360x400,720x400) */
+ { 1,1,1344,806,1344,806 }, /* 03 (720x350) */
+ { 1,1,1344,806,1344,806 }, /* 04 (640x480x60Hz) */
+ { 1,1,1344,806,1344,806 }, /* 05 (800x600x60Hz) */
+ { 1,1,1344,806,1344,806 } /* 06 (1024x768x60Hz) */
+};
+
+XGI330_LCDDataStruct XGI_StLCD1280x1024Data[]=
+{
+ { 22, 5, 800, 510,1650,1088},
+ { 22, 5, 800, 510,1650,1088},
+ { 176, 45, 900, 510,1650,1088},
+ { 176, 45, 900, 510,1650,1088},
+ { 22, 5, 800, 510,1650,1088},
+ { 13, 5,1024, 675,1560,1152},
+ { 16, 9,1266, 804,1688,1072},
+ { 1, 1,1688,1066,1688,1066}
+};
+
+XGI330_LCDDataStruct XGI_ExtLCD1280x1024Data[]=
+{
+ { 211, 60,1024, 501,1688,1066},
+ { 211, 60,1024, 508,1688,1066},
+ { 211, 60,1024, 501,1688,1066},
+ { 211, 60,1024, 508,1688,1066},
+ { 211, 60,1024, 500,1688,1066},
+ { 211, 75,1024, 625,1688,1066},
+ { 211, 120,1280, 798,1688,1066},
+ { 1, 1,1688,1066,1688,1066}
+};
+
+XGI330_LCDDataStruct XGI_St2LCD1280x1024Data[]=
+{
+ { 22, 5, 800, 510,1650,1088},
+ { 22, 5, 800, 510,1650,1088},
+ { 176, 45, 900, 510,1650,1088},
+ { 176, 45, 900, 510,1650,1088},
+ { 22, 5, 800, 510,1650,1088},
+ { 13, 5,1024, 675,1560,1152},
+ { 16, 9,1266, 804,1688,1072},
+ { 1, 1,1688,1066,1688,1066}
+};
+
+XGI330_LCDDataStruct XGI_CetLCD1280x1024Data[]=
+{
+ { 1,1,1688,1066,1688,1066 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 1,1,1688,1066,1688,1066 }, /* 01 (320x350,640x350) */
+ { 1,1,1688,1066,1688,1066 }, /* 02 (360x400,720x400) */
+ { 1,1,1688,1066,1688,1066 }, /* 03 (720x350) */
+ { 1,1,1688,1066,1688,1066 }, /* 04 (640x480x60Hz) */
+ { 1,1,1688,1066,1688,1066 }, /* 05 (800x600x60Hz) */
+ { 1,1,1688,1066,1688,1066 }, /* 06 (1024x768x60Hz) */
+ { 1,1,1688,1066,1688,1066 }, /* 07 (1280x1024x60Hz) */
+ { 1,1,1688,1066,1688,1066 } /* 08 (1400x1050x60Hz) */
+};
+
+XGI330_LCDDataStruct XGI_StLCD1400x1050Data[]=
+{
+ { 211,100,2100,408,1688,1066 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 211,64,1536,358,1688,1066 }, /* 01 (320x350,640x350) */
+ { 211,100,2100,408,1688,1066 }, /* 02 (360x400,720x400) */
+ { 211,64,1536,358,1688,1066 }, /* 03 (720x350) */
+ { 211,48,840,488,1688,1066 }, /* 04 (640x480x60Hz) */
+ { 211,72,1008,609,1688,1066 }, /* 05 (800x600x60Hz) */
+ { 211,128,1400,776,1688,1066 }, /* 06 (1024x768x60Hz) */
+ { 1,1,1688,1066,1688,1066 }, /* 07 (1280x1024x60Hz w/o Scaling) */
+ { 1,1,1688,1066,1688,1066 } /* 08 (1400x1050x60Hz) */
+};
+
+XGI330_LCDDataStruct XGI_ExtLCD1400x1050Data[]=
+{
+ { 211,100,2100,408,1688,1066 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 211,64,1536,358,1688,1066 }, /* 01 (320x350,640x350) */
+ { 211,100,2100,408,1688,1066 }, /* 02 (360x400,720x400) */
+ { 211,64,1536,358,1688,1066 }, /* 03 (720x350) */
+ { 211,48,840,488,1688,1066 }, /* 04 (640x480x60Hz) */
+ { 211,72,1008,609,1688,1066 }, /* 05 (800x600x60Hz) */
+ { 211,128,1400,776,1688,1066 }, /* 06 (1024x768x60Hz) */
+ { 1,1,1688,1066,1688,1066 }, /* 07 (1280x1024x60Hz w/o Scaling) */
+ { 1,1,1688,1066,1688,1066 } /* 08 (1400x1050x60Hz) */
+};
+
+XGI330_LCDDataStruct XGI_ExtLCD1600x1200Data[]=
+{
+ { 4,1,1620,420,2160,1250 }, /* { 3,1,2160,425,2160,1250 }, // 00 (320x200,320x400,640x200,640x400) // alan 10/14/2003 */
+ { 27,7,1920,375,2160,1250 }, /* 01 (320x350,640x350) */
+ { 4,1,1620,420,2160,1250 }, /* { 3,1,2160,425,2160,1250 }, // 02 (360x400,720x400) // alan 10/14/2003 */
+ { 27,7,1920,375,2160,1250 }, /* 03 (720x350) */
+ { 27,4,800,500,2160,1250 }, /* 04 (640x480x60Hz) */
+ { 4,1,1080,625,2160,1250 }, /* 05 (800x600x60Hz) */
+ { 5,2,1350,800,2160,1250 }, /* 06 (1024x768x60Hz) */
+ { 27,16,1500,1064,2160,1250 }, /* 07 (1280x1024x60Hz) */
+ { 9,7,1920,1106,2160,1250 }, /* 08 (1400x1050x60Hz) */
+ { 1,1,2160,1250,2160,1250 } /* 09 (1600x1200x60Hz) ;302lv */
+};
+
+XGI330_LCDDataStruct XGI_StLCD1600x1200Data[]=
+{
+ { 27,4,800,500,2160,1250 },/* 00 (320x200,320x400,640x200,640x400) */
+ { 27,4,800,500,2160,1250 },/* 01 (320x350,640x350) */
+ { 27,4,800,500,2160,1250 },/* 02 (360x400,720x400) */
+ { 27,4,800,500,2160,1250 },/* 03 (720x350) */
+ { 27,4,800,500,2160,1250 },/* 04 (320x240,640x480) */
+ { 4,1,1080,625,2160,1250 },/* 05 (400x300,800x600) */
+ { 5,2,1350,800,2160,1250 },/* 06 (512x384,1024x768) */
+ { 135,88,1600,1100,2160,1250 },/* 07 (1280x1024) */
+ { 1,1,1800,1500,2160,1250 },/* 08 (1400x1050) */
+ { 1,1,2160,1250,2160,1250 } /* 09 (1600x1200) */
+};
+
+XGI330_LCDDataStruct XGI_CetLCD1400x1050Data[]=
+{
+ { 1,1,1688,1066,1688,1066 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 1,1,1688,1066,1688,1066 }, /* 01 (320x350,640x350) */
+ { 1,1,1688,1066,1688,1066 }, /* 02 (360x400,720x400) */
+ { 1,1,1688,1066,1688,1066 }, /* 03 (720x350) */
+ { 1,1,1688,1066,1688,1066 }, /* 04 (640x480x60Hz) */
+ { 1,1,1688,1066,1688,1066 }, /* 05 (800x600x60Hz) */
+ { 1,1,1688,1066,1688,1066 }, /* 06 (1024x768x60Hz) */
+ { 1,1,1688,1066,1688,1066 }, /* 07 (1280x1024x60Hz) */
+ { 1,1,1688,1066,1688,1066 } /* 08 (1400x1050x60Hz) */
+};
+
+XGI330_LCDDataStruct XGI_NoScalingData[]=
+{
+ { 1, 1, 800, 449, 800, 449},
+ { 1, 1, 800, 449, 800, 449},
+ { 1, 1, 900, 449, 900, 449},
+ { 1, 1, 900, 449, 900, 449},
+ { 1, 1, 800, 525, 800, 525},
+ { 1, 1,1056, 628,1056, 628},
+ { 1, 1,1344, 806,1344, 806},
+ { 1, 1,1688,1066,1688,1066}
+};
+
+XGI330_LCDDataStruct XGI_ExtLCD1024x768x75Data[]=
+{
+ {42,25,1536,419,1344,806 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+ {48,25,1536,369,1344,806 }, /* ; 01 (320x350,640x350) */
+ {42,25,1536,419,1344,806 }, /* ; 02 (360x400,720x400) */
+ {48,25,1536,369,1344,806 }, /* ; 03 (720x350) */
+ {8,5,1312,500,1312,800 }, /* ; 04 (640x480x75Hz) */
+ {41,25,1024,625,1312,800 }, /* ; 05 (800x600x75Hz) */
+ {1,1,1312,800,1312,800 } /* ; 06 (1024x768x75Hz) */
+};
+
+XGI330_LCDDataStruct XGI_StLCD1024x768x75Data[]=
+{
+ {42,25,1536,419,1344,806 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+ {48,25,1536,369,1344,806 }, /* ; 01 (320x350,640x350) */
+ {42,25,1536,419,1344,806 }, /* ; 02 (360x400,720x400) */
+ {48,25,1536,369,1344,806 }, /* ; 03 (720x350) */
+ {8,5,1312,500,1312,800 }, /* ; 04 (640x480x75Hz) */
+ {41,25,1024,625,1312,800 }, /* ; 05 (800x600x75Hz) */
+ {1,1,1312,800,1312,800 } /* ; 06 (1024x768x75Hz) */
+};
+
+XGI330_LCDDataStruct XGI_CetLCD1024x768x75Data[]=
+{
+ {1,1,1312,800,1312,800}, /* ; 00 (320x200,320x400,640x200,640x400) */
+ {1,1,1312,800,1312,800}, /* ; 01 (320x350,640x350) */
+ {1,1,1312,800,1312,800}, /* ; 02 (360x400,720x400) */
+ {1,1,1312,800,1312,800}, /* ; 03 (720x350) */
+ {1,1,1312,800,1312,800}, /* ; 04 (640x480x75Hz) */
+ {1,1,1312,800,1312,800}, /* ; 05 (800x600x75Hz) */
+ {1,1,1312,800,1312,800} /* ; 06 (1024x768x75Hz) */
+};
+
+XGI330_LCDDataStruct XGI_ExtLCD1280x1024x75Data[]=
+{
+ {211,60,1024,501,1688,1066 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+ {211,60,1024,508,1688,1066 }, /* ; 01 (320x350,640x350) */
+ {211,60,1024,501,1688,1066 }, /* ; 02 (360x400,720x400) */
+ {211,60,1024,508,1688,1066 }, /* ; 03 (720x350) */
+ {211,45,768,498,1688,1066 }, /* ; 04 (640x480x75Hz) */
+ {211,75,1024,625,1688,1066 }, /* ; 05 (800x600x75Hz) */
+ {211,120,1280,798,1688,1066 }, /* ; 06 (1024x768x75Hz) */
+ {1,1,1688,1066,1688,1066 } /* ; 07 (1280x1024x75Hz) */
+};
+
+XGI330_LCDDataStruct XGI_StLCD1280x1024x75Data[]=
+{
+ {211,60,1024,501,1688,1066 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+ {211,60,1024,508,1688,1066 }, /* ; 01 (320x350,640x350) */
+ {211,60,1024,501,1688,1066 }, /* ; 02 (360x400,720x400) */
+ {211,60,1024,508,1688,1066 }, /* ; 03 (720x350) */
+ {211,45,768,498,1688,1066 }, /* ; 04 (640x480x75Hz) */
+ {211,75,1024,625,1688,1066 }, /* ; 05 (800x600x75Hz) */
+ {211,120,1280,798,1688,1066}, /* ; 06 (1024x768x75Hz) */
+ {1,1,1688,1066,1688,1066 } /* ; 07 (1280x1024x75Hz) */
+};
+
+XGI330_LCDDataStruct XGI_CetLCD1280x1024x75Data[]=
+{
+ {1,1,1688,1066,1688,1066}, /* ; 00 (320x200,320x400,640x200,640x400) */
+ {1,1,1688,1066,1688,1066}, /* ; 01 (320x350,640x350) */
+ {1,1,1688,1066,1688,1066}, /* ; 02 (360x400,720x400) */
+ {1,1,1688,1066,1688,1066}, /* ; 03 (720x350) */
+ {1,1,1688,1066,1688,1066}, /* ; 04 (640x480x75Hz) */
+ {1,1,1688,1066,1688,1066}, /* ; 05 (800x600x75Hz) */
+ {1,1,1688,1066,1688,1066}, /* ; 06 (1024x768x75Hz) */
+ {1,1,1688,1066,1688,1066} /* ; 07 (1280x1024x75Hz) */
+};
+
+XGI330_LCDDataStruct XGI_NoScalingDatax75[]=
+{
+ {1,1,800,449,800,449 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+ {1,1,800,449,800,449 }, /* ; 01 (320x350,640x350) */
+ {1,1,900,449,900,449 }, /* ; 02 (360x400,720x400) */
+ {1,1,900,449,900,449 }, /* ; 03 (720x350) */
+ {1,1,840,500,840,500 }, /* ; 04 (640x480x75Hz) */
+ {1,1,1056,625,1056,625 }, /* ; 05 (800x600x75Hz) */
+ {1,1,1312,800,1312,800 }, /* ; 06 (1024x768x75Hz) */
+ {1,1,1688,1066,1688,1066}, /* ; 07 (1280x1024x75Hz) */
+ {1,1,1688,1066,1688,1066}, /* ; 08 (1400x1050x75Hz) ;;[ycchen] 12/19/02 */
+ {1,1,2160,1250,2160,1250}, /* ; 09 (1600x1200x75Hz) */
+ {1,1,1688,806,1688,806 } /* ; 0A (1280x768x75Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_ExtLCDDes1024x768Data[]=
+{
+ { 9,1057,0, 771 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+ { 9,1057,0, 771 }, /* ; 01 (320x350,640x350) */
+ { 9,1057,0, 771 }, /* ; 02 (360x400,720x400) */
+ { 9,1057,0, 771 }, /* ; 03 (720x350) */
+ { 9,1057,0, 771 }, /* ; 04 (640x480x60Hz) */
+ { 9,1057,0, 771 }, /* ; 05 (800x600x60Hz) */
+ { 9,1057,805, 770 } /* ; 06 (1024x768x60Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_StLCDDes1024x768Data[]=
+{
+ { 9,1057,737,703 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+ { 9,1057,686,651 }, /* ; 01 (320x350,640x350) */
+ { 9,1057,737,703 }, /* ; 02 (360x400,720x400) */
+ { 9,1057,686,651 }, /* ; 03 (720x350) */
+ { 9,1057,776,741 }, /* ; 04 (640x480x60Hz) */
+ { 9,1057, 0 ,771 }, /* ; 05 (800x600x60Hz) */
+ { 9,1057,805,770 } /* ; 06 (1024x768x60Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_CetLCDDes1024x768Data[]=
+{
+ { 1152,856,622,587 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+ { 1152,856,597,562 }, /* ; 01 (320x350,640x350) */
+ { 1152,856,622,587 }, /* ; 02 (360x400,720x400) */
+ { 1152,856,597,562 }, /* ; 03 (720x350) */
+ { 1152,856,662,627 }, /* ; 04 (640x480x60Hz) */
+ { 1232,936,722,687 }, /* ; 05 (800x600x60Hz) */
+ { 0,1048,805,770 } /* ; 06 (1024x768x60Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_ExtLCDDLDes1280x1024Data[]=
+{
+ { 18,1346,981,940 },/* 00 (320x200,320x400,640x200,640x400) */
+ { 18,1346,926,865 },/* 01 (320x350,640x350) */
+ { 18,1346,981,940 },/* 02 (360x400,720x400) */
+ { 18,1346,926,865 },/* 03 (720x350) */
+ { 18,1346,0,1025 },/* 04 (640x480x60Hz) */
+ { 18,1346,0,1025 },/* 05 (800x600x60Hz) */
+ { 18,1346,1065,1024 },/* 06 (1024x768x60Hz) */
+ { 18,1346,1065,1024 }/* 07 (1280x1024x60Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_StLCDDLDes1280x1024Data[]=
+{
+ { 18,1346,970,907 },/* 00 (320x200,320x400,640x200,640x400) */
+ { 18,1346,917,854 },/* 01 (320x350,640x350) */
+ { 18,1346,970,907 },/* 02 (360x400,720x400) */
+ { 18,1346,917,854 },/* 03 (720x350) */
+ { 18,1346,0,1025 },/* 04 (640x480x60Hz) */
+ { 18,1346,0,1025 },/* 05 (800x600x60Hz) */
+ { 18,1346,1065,1024 },/* 06 (1024x768x60Hz) */
+ { 18,1346,1065,1024 }/* 07 (1280x1024x60Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_CetLCDDLDes1280x1024Data[]=
+{
+ { 1368,1008,752,711 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 1368,1008,729,688 }, /* 01 (320x350,640x350) */
+ { 1368,1008,752,711 }, /* 02 (360x400,720x400) */
+ { 1368,1008,729,688 }, /* 03 (720x350) */
+ { 1368,1008,794,753 }, /* 04 (640x480x60Hz) */
+ { 1448,1068,854,813 }, /* 05 (800x600x60Hz) */
+ { 1560,1200,938,897 }, /* 06 (1024x768x60Hz) */
+ { 18,1346,1065,1024 } /* 07 (1280x1024x60Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_ExtLCDDes1280x1024Data[]=
+{
+ { 9,1337,981,940 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+ { 9,1337,926,884 }, /* ; 01 (320x350,640x350) alan, 2003/09/30 */
+ { 9,1337,981,940 }, /* ; 02 (360x400,720x400) */
+ { 9,1337,926,884 }, /* ; 03 (720x350) alan, 2003/09/30 */
+ { 9,1337,0,1025 }, /* ; 04 (640x480x60Hz) */
+ { 9,1337,0,1025 }, /* ; 05 (800x600x60Hz) */
+ { 9,1337,1065,1024 }, /* ; 06 (1024x768x60Hz) */
+ { 9,1337,1065,1024 } /* ; 07 (1280x1024x60Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_StLCDDes1280x1024Data[]=
+{
+ { 9,1337,970,907 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+ { 9,1337,917,854 }, /* ; 01 (320x350,640x350) */
+ { 9,1337,970,907 }, /* ; 02 (360x400,720x400) */
+ { 9,1337,917,854 }, /* ; 03 (720x350) */
+ { 9,1337,0,1025 }, /* ; 04 (640x480x60Hz) */
+ { 9,1337,0,1025 }, /* ; 05 (800x600x60Hz) */
+ { 9,1337,1065,1024 }, /* ; 06 (1024x768x60Hz) */
+ { 9,1337,1065,1024 } /* ; 07 (1280x1024x60Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_CetLCDDes1280x1024Data[]=
+{
+ { 1368,1008,752,711 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 1368,1008,729,688 }, /* 01 (320x350,640x350) */
+ { 1368,1008,752,711 }, /* 02 (360x400,720x400) */
+ { 1368,1008,729,688 }, /* 03 (720x350) */
+ { 1368,1008,794,753 }, /* 04 (640x480x60Hz) */
+ { 1448,1068,854,813 }, /* 05 (800x600x60Hz) */
+ { 1560,1200,938,897 }, /* 06 (1024x768x60Hz) */
+ { 9,1337,1065,1024 } /* 07 (1280x1024x60Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_StLCDDLDes1400x1050Data[]=
+{
+ { 18,1464,0,1051 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 18,1464,0,1051 }, /* 01 (320x350,640x350) */
+ { 18,1464,0,1051 }, /* 02 (360x400,720x400) */
+ { 18,1464,0,1051 }, /* 03 (720x350) */
+ { 18,1464,0,1051 }, /* 04 (640x480x60Hz) */
+ { 18,1464,0,1051 }, /* 05 (800x600x60Hz) */
+ { 18,1464,0,1051 }, /* 06 (1024x768x60Hz) */
+ { 1646,1406,1053,1038 }, /* 07 (1280x1024x60Hz) */
+ { 18,1464,0,1051 } /* 08 (1400x1050x60Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_ExtLCDDLDes1400x1050Data[]=
+{
+ { 18,1464,0,1051 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 18,1464,0,1051 }, /* 01 (320x350,640x350) */
+ { 18,1464,0,1051 }, /* 02 (360x400,720x400) */
+ { 18,1464,0,1051 }, /* 03 (720x350) */
+ { 18,1464,0,1051 }, /* 04 (640x480x60Hz) */
+ { 18,1464,0,1051 }, /* 05 (800x600x60Hz) */
+ { 18,1464,0,1051 }, /* 06 (1024x768x60Hz) */
+ { 1646,1406,1053,1038 }, /* 07 (1280x1024x60Hz) */
+ { 18,1464,0,1051 } /* 08 (1400x1050x60Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_StLCDDes1400x1050Data[]=
+{
+ { 9,1455,0,1051 },/* 00 (320x200,320x400,640x200,640x400) */
+ { 9,1455,0,1051 },/* 01 (320x350,640x350) */
+ { 9,1455,0,1051 },/* 02 (360x400,720x400) */
+ { 9,1455,0,1051 },/* 03 (720x350) */
+ { 9,1455,0,1051 },/* 04 (640x480x60Hz) */
+ { 9,1455,0,1051 },/* 05 (800x600x60Hz) */
+ { 9,1455,0,1051 },/* 06 (1024x768x60Hz) */
+ { 1637,1397,1053,1038 },/* 07 (1280x1024x60Hz) */
+ { 9,1455,0,1051 } /* 08 (1400x1050x60Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_ExtLCDDes1400x1050Data[]=
+{
+ { 9,1455,0,1051 },/* 00 (320x200,320x400,640x200,640x400) */
+ { 9,1455,0,1051 },/* 01 (320x350,640x350) */
+ { 9,1455,0,1051 },/* 02 (360x400,720x400) */
+ { 9,1455,0,1051 },/* 03 (720x350) */
+ { 9,1455,0,1051 },/* 04 (640x480x60Hz) */
+ { 9,1455,0,1051 },/* 05 (800x600x60Hz) */
+ { 9,1455,0,1051 },/* 06 (1024x768x60Hz) */
+ { 1637,1397,1053,1038 },/* 07 (1280x1024x60Hz) */
+ { 9,1455,0,1051 } /* 08 (1400x1050x60Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_CetLCDDes1400x1050Data[]=
+{
+ { 1308,1068,781,766 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 1308,1068,781,766 }, /* 01 (320x350,640x350) */
+ { 1308,1068,781,766 }, /* 02 (360x400,720x400) */
+ { 1308,1068,781,766 }, /* 03 (720x350) */
+ { 1308,1068,781,766 }, /* 04 (640x480x60Hz) */
+ { 1388,1148,841,826 }, /* 05 (800x600x60Hz) */
+ { 1490,1250,925,910 }, /* 06 (1024x768x60Hz) */
+ { 1646,1406,1053,1038 }, /* 07 (1280x1024x60Hz) */
+ { 18,1464,0,1051 } /* 08 (1400x1050x60Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_CetLCDDes1400x1050Data2[]=
+{
+ { 0,1448,0,1051 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 0,1448,0,1051 }, /* 01 (320x350,640x350) */
+ { 0,1448,0,1051 }, /* 02 (360x400,720x400) */
+ { 0,1448,0,1051 }, /* 03 (720x350) */
+ { 0,1448,0,1051 } /* 04 (640x480x60Hz) */
+};
+
+
+
+XGI330_LCDDataDesStruct XGI_ExtLCDDLDes1600x1200Data[]=
+{
+ { 18,1682,0,1201 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 18,1682,0,1201 }, /* 01 (320x350,640x350) */
+ { 18,1682,0,1201 }, /* 02 (360x400,720x400) */
+ { 18,1682,0,1201 }, /* 03 (720x350) */
+ { 18,1682,0,1201 }, /* 04 (640x480x60Hz) */
+ { 18,1682,0,1201 }, /* 05 (800x600x60Hz) */
+ { 18,1682,0,1201 }, /* 06 (1024x768x60Hz) */
+ { 18,1682,0,1201 }, /* 07 (1280x1024x60Hz) */
+ { 18,1682,0,1201 }, /* 08 (1400x1050x60Hz) */
+ { 18,1682,0,1201 } /* 09 (1600x1200x60Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_StLCDDLDes1600x1200Data[]=
+{
+ { 18,1682,1150,1101 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 18,1682,1083,1034 }, /* 01 (320x350,640x350) */
+ { 18,1682,1150,1101 }, /* 02 (360x400,720x400) */
+ { 18,1682,1083,1034 }, /* 03 (720x350) */
+ { 18,1682,0,1201 }, /* 04 (640x480x60Hz) */
+ { 18,1682,0,1201 }, /* 05 (800x600x60Hz) */
+ { 18,1682,0,1201 }, /* 06 (1024x768x60Hz) */
+ { 18,1682,1232,1183 }, /* 07 (1280x1024x60Hz) */
+ { 18,1682,0,1201 }, /* 08 (1400x1050x60Hz) */
+ { 18,1682,0,1201 } /* 09 (1600x1200x60Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_ExtLCDDes1600x1200Data[]=
+{
+ { 9,1673,0,1201 },/* 00 (320x200,320x400,640x200,640x400) */
+ { 9,1673,0,1201 },/* 01 (320x350,640x350) */
+ { 9,1673,0,1201 },/* 02 (360x400,720x400) */
+ { 9,1673,0,1201 },/* 03 (720x350) */
+ { 9,1673,0,1201 },/* 04 (640x480x60Hz) */
+ { 9,1673,0,1201 },/* 05 (800x600x60Hz) */
+ { 9,1673,0,1201 },/* 06 (1024x768x60Hz) */
+ { 9,1673,0,1201 },/* 07 (1280x1024x60Hz) */
+ { 9,1673,0,1201 },/* 08 (1400x1050x60Hz) */
+ { 9,1673,0,1201 } /* 09 (1600x1200x60Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_StLCDDes1600x1200Data[]=
+{
+ { 9,1673,1150,1101 },/* 00 (320x200,320x400,640x200,640x400) */
+ { 9,1673,1083,1034 },/* 01 (320x350,640x350) */
+ { 9,1673,1150,1101 },/* 02 (360x400,720x400) */
+ { 9,1673,1083,1034 },/* 03 (720x350) */
+ { 9,1673,0,1201 },/* 04 (640x480x60Hz) */
+ { 9,1673,0,1201 },/* 05 (800x600x60Hz) */
+ { 9,1673,0,1201 },/* 06 (1024x768x60Hz) */
+ { 9,1673,1232,1183 },/* 07 (1280x1024x60Hz) */
+ { 9,1673,0,1201 },/* 08 (1400x1050x60Hz) */
+ { 9,1673,0,1201 } /* 09 (1600x1200x60Hz) */
+};
+
+XGI330_LCDDataDesStruct2 XGI_NoScalingDesData[]=
+{
+ { 9,657,448,405,96,2 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 9,657,448,355,96,2 }, /* 01 (320x350,640x350) */
+ { 9,657,448,405,96,2 }, /* 02 (360x400,720x400) */
+ { 9,657,448,355,96,2 }, /* 03 (720x350) */
+ { 9,657,1,483,96,2 }, /* 04 (640x480x60Hz) */
+ { 9,849,627,600,128,4 }, /* 05 (800x600x60Hz) */
+ { 9,1057,805,770,0136,6 }, /* 06 (1024x768x60Hz) */
+ { 9,1337,0,1025,112,3 }, /* 07 (1280x1024x60Hz) */
+ { 9,1457,0,1051,112,3 }, /* 08 (1400x1050x60Hz) }, //;[ycchen] 12/19/02 */
+ { 9,1673,0,1201,192,3 }, /* 09 (1600x1200x60Hz) */
+ { 9,1337,0,771,112,6 } /* 0A (1280x768x60Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_ExtLCDDes1024x768x75Data[]= /* ;;1024x768x75Hz */
+{
+ {9,1049,0,769}, /* ; 00 (320x200,320x400,640x200,640x400) */
+ {9,1049,0,769}, /* ; 01 (320x350,640x350) */
+ {9,1049,0,769}, /* ; 02 (360x400,720x400) */
+ {9,1049,0,769}, /* ; 03 (720x350) */
+ {9,1049,0,769}, /* ; 04 (640x480x75Hz) */
+ {9,1049,0,769}, /* ; 05 (800x600x75Hz) */
+ {9,1049,0,769} /* ; 06 (1024x768x75Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_StLCDDes1024x768x75Data[]=
+{
+ {9,1049,0,769}, /* ; 00 (320x200,320x400,640x200,640x400) */
+ {9,1049,0,769}, /* ; 01 (320x350,640x350) */
+ {9,1049,0,769}, /* ; 02 (360x400,720x400) */
+ {9,1049,0,769}, /* ; 03 (720x350) */
+ {9,1049,0,769}, /* ; 04 (640x480x75Hz) */
+ {9,1049,0,769}, /* ; 05 (800x600x75Hz) */
+ {9,1049,0,769} /* ; 06 (1024x768x75Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_CetLCDDes1024x768x75Data[]= /* ;;1024x768x75Hz */
+{
+ {1152,856,622,587}, /* ; 00 (320x200,320x400,640x200,640x400) */
+ {1152,856,597,562}, /* ; 01 (320x350,640x350) */
+ {1192,896,622,587}, /* ; 02 (360x400,720x400) */
+ {1192,896,597,562}, /* ; 03 (720x350) */
+ {1129,857,656,625}, /* ; 04 (640x480x75Hz) */
+ {1209,937,716,685}, /* ; 05 (800x600x75Hz) */
+ {9,1049,0,769} /* ; 06 (1024x768x75Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_ExtLCDDLDes1280x1024x75Data[]= /* ;;1280x1024x75Hz */
+{
+ {18,1314,0,1025 },/* ; 00 (320x200,320x400,640x200,640x400) */
+ {18,1314,0,1025 },/* ; 01 (320x350,640x350) */
+ {18,1314,0,1025 },/* ; 02 (360x400,720x400) */
+ {18,1314,0,1025 },/* ; 03 (720x350) */
+ {18,1314,0,1025 },/* ; 04 (640x480x60Hz) */
+ {18,1314,0,1025 },/* ; 05 (800x600x60Hz) */
+ {18,1314,0,1025 },/* ; 06 (1024x768x60Hz) */
+ {18,1314,0,1025 }/* ; 07 (1280x1024x60Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_StLCDDLDes1280x1024x75Data[]=
+{
+ {18,1314,0,1025 },/* ; 00 (320x200,320x400,640x200,640x400) */
+ {18,1314,0,1025 },/* ; 01 (320x350,640x350) */
+ {18,1314,0,1025 },/* ; 02 (360x400,720x400) */
+ {18,1314,0,1025 },/* ; 03 (720x350) */
+ {18,1314,0,1025 },/* ; 04 (640x480x60Hz) */
+ {18,1314,0,1025 },/* ; 05 (800x600x60Hz) */
+ {18,1314,0,1025 },/* ; 06 (1024x768x60Hz) */
+ {18,1314,0,1025 }/* ; 07 (1280x1024x60Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_CetLCDDLDes1280x1024x75Data[]= /* 1280x1024x75Hz */
+{
+ {1368,1008,752,711}, /* ; 00 (320x200,320x400,640x200,640x400) */
+ {1368,1008,729,688}, /* ; 01 (320x350,640x350) */
+ {1408,1048,752,711}, /* ; 02 (360x400,720x400) */
+ {1408,1048,729,688}, /* ; 03 (720x350) */
+ {1377,985,794,753}, /* ; 04 (640x480x75Hz) */
+ {1457,1065,854,813}, /* ; 05 (800x600x75Hz) */
+ {1569,1177,938,897}, /* ; 06 (1024x768x75Hz) */
+ {18,1314,0,1025} /* ; 07 (1280x1024x75Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_ExtLCDDes1280x1024x75Data[]= /* ;;1280x1024x75Hz */
+{
+ {9,1305,0,1025},/* ; 00 (320x200,320x400,640x200,640x400) */
+ {9,1305,0,1025},/* ; 01 (320x350,640x350) */
+ {9,1305,0,1025},/* ; 02 (360x400,720x400) */
+ {9,1305,0,1025},/* ; 03 (720x350) */
+ {9,1305,0,1025},/* ; 04 (640x480x60Hz) */
+ {9,1305,0,1025},/* ; 05 (800x600x60Hz) */
+ {9,1305,0,1025},/* ; 06 (1024x768x60Hz) */
+ {9,1305,0,1025} /* ; 07 (1280x1024x60Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_StLCDDes1280x1024x75Data[]=
+{
+ {9,1305,0,1025},/* ; 00 (320x200,320x400,640x200,640x400) */
+ {9,1305,0,1025},/* ; 01 (320x350,640x350) */
+ {9,1305,0,1025},/* ; 02 (360x400,720x400) */
+ {9,1305,0,1025},/* ; 03 (720x350) */
+ {9,1305,0,1025},/* ; 04 (640x480x60Hz) */
+ {9,1305,0,1025},/* ; 05 (800x600x60Hz) */
+ {9,1305,0,1025},/* ; 06 (1024x768x60Hz) */
+ {9,1305,0,1025} /* ; 07 (1280x1024x60Hz) */
+};
+
+XGI330_LCDDataDesStruct XGI_CetLCDDes1280x1024x75Data[]= /* 1280x1024x75Hz */
+{
+ {1368,1008,752,711}, /* ; 00 (320x200,320x400,640x200,640x400) */
+ {1368,1008,729,688}, /* ; 01 (320x350,640x350) */
+ {1408,1048,752,711}, /* ; 02 (360x400,720x400) */
+ {1408,1048,729,688}, /* ; 03 (720x350) */
+ {1377,985,794,753}, /* ; 04 (640x480x75Hz) */
+ {1457,1065,854,813}, /* ; 05 (800x600x75Hz) */
+ {1569,1177,938,897}, /* ; 06 (1024x768x75Hz) */
+ {9,1305,0,1025} /* ; 07 (1280x1024x75Hz) */
+};
+
+XGI330_LCDDataDesStruct2 XGI_NoScalingDesDatax75[]= /* Scaling LCD 75Hz */
+{
+ {9,657,448,405,96,2}, /* ; 00 (320x200,320x400,640x200,640x400) */
+ {9,657,448,355,96,2}, /* ; 01 (320x350,640x350) */
+ {9,738,448,405,108,2}, /* ; 02 (360x400,720x400) */
+ {9,738,448,355,108,2}, /* ; 03 (720x350) */
+ {9,665,0,481,64,3}, /* ; 04 (640x480x75Hz) */
+ {9,825,0,601,80,3}, /* ; 05 (800x600x75Hz) */
+ {9,1049,0,769,96,3}, /* ; 06 (1024x768x75Hz) */
+ {9,1305,0,1025,144,3}, /* ; 07 (1280x1024x75Hz) */
+ {9,1457,0,1051,112,3}, /* ; 08 (1400x1050x60Hz) ;;[ycchen] 12/19/02 */
+ {9,1673,0,1201,192,3}, /* ; 09 (1600x1200x75Hz) */
+ {9,1337,0,771,112,6} /* ; 0A (1280x768x60Hz) */
+};
+
+XGI330_TVDataStruct XGI_StPALData[]=
+{
+ { 1, 1, 864, 525,1270, 400, 100, 0, 760},
+ { 1, 1, 864, 525,1270, 350, 100, 0, 760},
+ { 1, 1, 864, 525,1270, 400, 0, 0, 720},
+ { 1, 1, 864, 525,1270, 350, 0, 0, 720},
+ { 1, 1, 864, 525,1270, 480, 50, 0, 760},
+ { 1, 1, 864, 525,1270, 600, 50, 0, 0}
+};
+
+XGI330_TVDataStruct XGI_ExtPALData[]=
+{
+ { 2, 1,1080, 463,1270, 500, 50, 0, 50},
+ { 15, 7,1152, 413,1270, 500, 50, 0, 50},
+ { 2, 1,1080, 463,1270, 500, 50, 0, 50},
+ { 15, 7,1152, 413,1270, 500, 50, 0, 50},
+ { 2, 1, 900, 543,1270, 500, 0, 0, 50},
+ { 4, 3,1080, 663,1270, 500, 438, 0, 438},
+ { 1, 1,1125, 831,1270, 500, 686, 0, 686}, /*301b*/
+ { 3, 2,1080, 619,1270, 540, 438, 0, 438}
+};
+
+XGI330_TVDataStruct XGI_StNTSCData[]=
+{
+ { 1, 1, 858, 525,1270, 400, 50, 0, 760},
+ { 1, 1, 858, 525,1270, 350, 50, 0, 640},
+ { 1, 1, 858, 525,1270, 400, 0, 0, 720},
+ { 1, 1, 858, 525,1270, 350, 0, 0, 720},
+ { 1, 1, 858, 525,1270, 480, 0, 0, 760}
+};
+
+XGI330_TVDataStruct XGI_ExtNTSCData[]=
+{
+ { 9, 5, 1001, 453,1270, 420, 171, 0, 171},
+ { 12, 5, 858, 403,1270, 420, 171, 0, 171},
+ { 9, 5, 1001, 453,1270, 420, 171, 0, 171},
+ { 12, 5, 858, 403,1270, 420, 171, 0, 171},
+ { 143, 80, 836, 523,1270, 420, 224, 0, 0},
+ { 143, 120,1008, 643,1270, 420, 0, 1, 0},
+ { 1, 1,1120, 821,1516, 420, 0, 1, 0}, /*301b*/
+ { 2, 1, 858, 503,1584, 480, 0, 1, 0},
+ { 3, 2,1001, 533,1270, 420, 0, 0, 0}
+};
+
+XGI330_TVDataStruct XGI_St1HiTVData[]=
+{
+ { 1,1,892,563,690,800,0,0,0 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 1,1,892,563,690,700,0,0,0 }, /* 01 (320x350,640x350) */
+ { 1,1,1000,563,785,800,0,0,0 }, /* 02 (360x400,720x400) */
+ { 1,1,1000,563,785,700,0,0,0 }, /* 03 (720x350) */
+ { 1,1,892,563,690,960,0,0,0 }, /* 04 (320x240,640x480) */
+ { 8,5,1050,683,1648,960,0x150,1,0 } /* 05 (400x300,800x600) */
+};
+
+XGI330_TVDataStruct XGI_St2HiTVData[]=
+{
+ { 3,1,840,483,1648,960,0x032,0,0 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 1,1,892,563,690,700,0,0,0 }, /* 01 (320x350,640x350) */
+ { 3,1,840,483,1648,960,0x032,0,0 }, /* 02 (360x400,720x400) */
+ { 1,1,1000,563,785,700,0,0,0 }, /* 03 (720x350) */
+ { 5,2,840,563,1648,960,0x08D,1,0 }, /* 04 (320x240,640x480) */
+ { 8,5,1050,683,1648,960,0x17C,1,0 } /* 05 (400x300,800x600) */
+
+};
+
+XGI330_TVDataStruct XGI_ExtHiTVData[]=
+{
+ { 6,1,840,563,1632,960,0,0,0 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 3,1,960,563,1632,960,0,0,0 }, /* 01 (320x350,640x350) */
+ { 3,1,840,483,1632,960,0,0,0 }, /* 02 (360x400,720x400) */
+ { 3,1,960,563,1632,960,0,0,0 }, /* 03 (720x350) */
+ { 5,1,840,563,1648,960,0x166,1,0 }, /* 04 (320x240,640x480) */
+ { 16,5,1050,683,1648,960,0x143,1,0 }, /* 05 (400x300,800x600) */
+ { 25,12,1260,851,1648,960,0x032,0,0 }, /* 06 (512x384,1024x768) */
+ { 5,4,1575,1124,1648,960,0x128,0,0 }, /* 07 (1280x1024) */
+ { 4,1,1050,563,1548,960,0x143,1,0 }, /* 08 (800x480) */
+ { 5,2,1400,659,1648,960,0x032,0,0 }, /* 09 (1024x576) */
+ { 8,5,1750,803,1648,960,0x128,0,0 } /* 0A (1280x720) */
+
+};
+
+XGI330_TVDataStruct XGI_ExtYPbPr525iData[]=
+{
+ { 9, 5, 1001, 453,1270, 420, 171, 0, 171},
+ { 12, 5, 858, 403,1270, 420, 171, 0, 171},
+ { 9, 5, 1001, 453,1270, 420, 171, 0, 171},
+ { 12, 5, 858, 403,1270, 420, 171, 0, 171},
+ { 143, 80, 836, 523,1250, 420, 224, 0, 0},
+ { 143, 120,1008, 643,1250, 420, 0, 1, 0},
+ { 1, 1,1120, 821,1516, 420, 0, 1, 0}, /*301b*/
+ { 2, 1, 858, 503,1584, 480, 0, 1, 0},
+ { 3, 2,1001, 533,1250, 420, 0, 0, 0}
+};
+
+XGI330_TVDataStruct XGI_StYPbPr525iData[]=
+{
+ { 1, 1, 858, 525,1270, 400, 50, 0, 760},
+ { 1, 1, 858, 525,1270, 350, 50, 0, 640},
+ { 1, 1, 858, 525,1270, 400, 0, 0, 720},
+ { 1, 1, 858, 525,1270, 350, 0, 0, 720},
+ { 1, 1, 858, 525,1270, 480, 0, 0, 760},
+};
+
+XGI330_TVDataStruct XGI_ExtYPbPr525pData[]=
+{
+ { 9, 5, 1001, 453,1270, 420, 171, 0, 171},
+ { 12, 5, 858, 403,1270, 420, 171, 0, 171},
+ { 9, 5, 1001, 453,1270, 420, 171, 0, 171},
+ { 12, 5, 858, 403,1270, 420, 171, 0, 171},
+ { 143, 80, 836, 523,1270, 420, 224, 0, 0},
+ { 143, 120,1008, 643,1270, 420, 0, 1, 0},
+ { 1, 1,1120, 821,1516, 420, 0, 1, 0}, /*301b*/
+ { 2, 1, 858, 503,1584, 480, 0, 1, 0},
+ { 3, 2,1001, 533,1270, 420, 0, 0, 0}
+ };
+
+XGI330_TVDataStruct XGI_StYPbPr525pData[]=
+{
+ { 1, 1,1716, 525,1270, 400, 50, 0, 760},
+ { 1, 1,1716, 525,1270, 350, 50, 0, 640},
+ { 1, 1,1716, 525,1270, 400, 0, 0, 720},
+ { 1, 1,1716, 525,1270, 350, 0, 0, 720},
+ { 1, 1,1716, 525,1270, 480, 0, 0, 760},
+};
+
+XGI330_TVDataStruct XGI_ExtYPbPr750pData[]=
+{
+ { 3, 1, 935, 470,1130, 680, 50, 0, 0}, /* 00 (320x200,320x400,640x200,640x400) */
+ { 24, 7, 935, 420,1130, 680, 50, 0, 0}, /* 01 (320x350,640x350) */
+ { 3, 1, 935, 470,1130, 680, 50, 0, 0}, /* 02 (360x400,720x400) */
+ { 24, 7, 935, 420,1130, 680, 50, 0, 0}, /* 03 (720x350) */
+ { 2, 1,1100, 590,1130, 640, 50, 0, 0}, /* 04 (320x240,640x480) */
+ { 3, 2,1210, 690,1130, 660, 50, 0, 0}, /* 05 (400x300,800x600) */
+ { 1, 1,1375, 878,1130, 640, 638, 0, 0}, /* 06 (1024x768) */
+ { 2, 1, 858, 503,1130, 480, 0, 1, 0}, /* 07 (720x480) */
+ { 5, 4,1815, 570,1130, 660, 50, 0, 0},
+ { 5, 3,1100, 686,1130, 640, 50, 1, 0},
+ { 10, 9,1320, 830,1130, 640, 50, 0, 0}
+};
+
+XGI330_TVDataStruct XGI_StYPbPr750pData[]=
+{
+ { 1, 1,1650, 750,1280, 400, 50, 0, 760},
+ { 1, 1,1650, 750,1280, 350, 50, 0, 640},
+ { 1, 1,1650, 750,1280, 400, 0, 0, 720},
+ { 1, 1,1650, 750,1280, 350, 0, 0, 720},
+ { 1, 1,1650, 750,1280, 480, 0, 0, 760},
+};
+
+UCHAR XGI330_NTSCTiming[] = {
+ 0x17,0x1d,0x03,0x09,0x05,0x06,0x0c,0x0c,
+ 0x94,0x49,0x01,0x0a,0x06,0x0d,0x04,0x0a,
+ 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b,
+ 0x0c,0x50,0x00,0x97,0x00,0xda,0x4a,0x17,
+ 0x7d,0x05,0x4b,0x00,0x00,0xe2,0x00,0x02,
+ 0x03,0x0a,0x65,0x9d,0x08,0x92,0x8f,0x40,
+ 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x50,
+ 0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00};
+
+UCHAR XGI330_PALTiming[] = {
+ 0x21,0x5A,0x35,0x6e,0x04,0x38,0x3d,0x70,
+ 0x94,0x49,0x01,0x12,0x06,0x3e,0x35,0x6d,
+ 0x06,0x14,0x3e,0x35,0x6d,0x00,0x45,0x2b,
+ 0x70,0x50,0x00,0x9b,0x00,0xd9,0x5d,0x17,
+ 0x7d,0x05,0x45,0x00,0x00,0xe8,0x00,0x02,
+ 0x0d,0x00,0x68,0xb0,0x0b,0x92,0x8f,0x40,
+ 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x63,
+ 0x00,0x40,0x3e,0x00,0xe1,0x02,0x28,0x00};
+
+UCHAR XGI330_HiTVExtTiming[] =
+{
+ 0x2D,0x60,0x2C,0x5F,0x08,0x31,0x3A,0x64,
+ 0x28,0x02,0x01,0x3D,0x06,0x3E,0x35,0x6D,
+ 0x06,0x14,0x3E,0x35,0x6D,0x00,0xC5,0x3F,
+ 0x64,0x90,0x33,0x8C,0x18,0x36,0x3E,0x13,
+ 0x2A,0xDE,0x2A,0x44,0x40,0x2A,0x44,0x40,
+ 0x8E,0x8E,0x82,0x07,0x0B,
+ 0x92,0x0F,0x40,0x60,0x80,0x14,0x90,0x8C,
+ 0x60,0x14,0x3D,0x63,0x4F,
+ 0x27,0x00,0xfc,0xff,0x6a,0x00
+
+};
+
+UCHAR XGI330_HiTVSt1Timing[] =
+{
+ 0x32,0x65,0x2C,0x5F,0x08,0x31,0x3A,0x65,
+ 0x28,0x02,0x01,0x3D,0x06,0x3E,0x35,0x6D,
+ 0x06,0x14,0x3E,0x35,0x6D,0x00,0xC5,0x3F,
+ 0x65,0x90,0x7B,0xA8,0x03,0xF0,0x87,0x03,
+ 0x11,0x15,0x11,0xCF,0x10,0x11,0xCF,0x10,
+ 0x35,0x35,0x3B,0x69,0x1D,
+ 0x92,0x0F,0x40,0x60,0x80,0x14,0x90,0x8C,
+ 0x60,0x04,0x86,0xAF,0x5D,
+ 0x0E,0x00,0xfc,0xff,0x2d,0x00
+};
+
+UCHAR XGI330_HiTVSt2Timing[] =
+{
+ 0x32,0x65,0x2C,0x5F,0x08,0x31,0x3A,0x64,
+ 0x28,0x02,0x01,0x3D,0x06,0x3E,0x35,0x6D,
+ 0x06,0x14,0x3E,0x35,0x6D,0x00,0xC5,0x3F,
+ 0x64,0x90,0x33,0x8C,0x18,0x36,0x3E,0x13,
+ 0x2A,0xDE,0x2A,0x44,0x40,0x2A,0x44,0x40,
+ 0x8E,0x8E,0x82,0x07,0x0B,
+ 0x92,0x0F,0x40,0x60,0x80,0x14,0x90,0x8C,
+ 0x60,0x14,0x3D,0x63,0x4F,
+ 0x27,0x00,0xFC,0xff,0x6a,0x00
+};
+
+UCHAR XGI330_HiTVTextTiming[] =
+{
+ 0x32,0x65,0x2C,0x5F,0x08,0x31,0x3A,0x65,
+ 0x28,0x02,0x01,0x3D,0x06,0x3E,0x35,0x6D,
+ 0x06,0x14,0x3E,0x35,0x6D,0x00,0xC5,0x3F,
+ 0x65,0x90,0xE7,0xBC,0x03,0x0C,0x97,0x03,
+ 0x14,0x78,0x14,0x08,0x20,0x14,0x08,0x20,
+ 0xC8,0xC8,0x3B,0xD2,0x26,
+ 0x92,0x0F,0x40,0x60,0x80,0x14,0x90,0x8C,
+ 0x60,0x04,0x96,0x72,0x5C,
+ 0x11,0x00,0xFC,0xFF,0x32,0x00
+};
+
+UCHAR XGI330_YPbPr750pTiming[] =
+{
+ 0x30,0x1d,0xe8,0x09,0x09,0xed,0x0c,0x0c,
+ 0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
+ 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
+ 0xed,0x50,0x70,0x9f,0x16,0x59,0x60,0x13,
+ 0x27,0x0b,0x27,0xfc,0x30,0x27,0x1c,0xb0,
+ 0x4b,0x4b,0x6f,0x2f,0x63,
+ 0x92,0x0F,0x40,0x60,0x80,0x14,0x90,0x8C,
+ 0x60,0x14,0x73,0x00,0x40,
+ 0x11,0x00,0xfc,0xff,0x32,0x00
+};
+
+UCHAR XGI330_YPbPr525pTiming[] =
+{
+ 0x3E,0x11,0x06,0x09,0x0b,0x0c,0x0c,0x0c,
+ 0x98,0x0a,0x01,0x0d,0x06,0x0d,0x04,0x0a,
+ 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
+ 0x0c,0x50,0xb2,0x9f,0x16,0x59,0x4f,0x13,
+ 0xad,0x11,0xad,0x1d,0x40,0x8a,0x3d,0xb8,
+ 0x51,0x5e,0x60,0x49,0x7d,
+ 0x92,0x0F,0x40,0x60,0x80,0x14,0x90,0x8C,
+ 0x60,0x14,0x4B,0x43,0x41,
+ 0x11,0x00,0xFC,0xFF,0x32,0x00
+};
+
+UCHAR XGI330_YPbPr525iTiming[] =
+{
+ 0x1B,0x21,0x03,0x09,0x05,0x06,0x0C,0x0C,
+ 0x94,0x49,0x01,0x0A,0x06,0x0D,0x04,0x0A,
+ 0x06,0x14,0x0D,0x04,0x0A,0x00,0x85,0x1B,
+ 0x0C,0x50,0x00,0x97,0x00,0xDA,0x4A,0x17,
+ 0x7D,0x05,0x4B,0x00,0x00,0xE2,0x00,0x02,
+ 0x03,0x0A,0x65,0x9D,0x08,
+ 0x92,0x8F,0x40,0x60,0x80,0x14,0x90,0x8C,
+ 0x60,0x14,0x4B,0x00,0x40,
+ 0x44,0x00,0xDB,0x02,0x3B,0x00
+
+};
+
+UCHAR XGI330_HiTVGroup3Data[] =
+{
+ 0x00,0x1A,0x22,0x63,0x62,0x22,0x08,0x5F,
+ 0x05,0x21,0xB2,0xB2,0x55,0x77,0x2A,0xA6,
+ 0x25,0x2F,0x47,0xFA,0xC8,0xFF,0x8E,0x20,
+ 0x8C,0x6E,0x60,0x2E,0x58,0x48,0x72,0x44,
+ 0x56,0x36,0x4F,0x6E,0x3F,0x80,0x00,0x80,
+ 0x4F,0x7F,0x03,0xA8,0x7D,0x20,0x1A,0xA9,
+ 0x14,0x05,0x03,0x7E,0x64,0x31,0x14,0x75,
+ 0x18,0x05,0x18,0x05,0x4C,0xA8,0x01
+};
+
+UCHAR XGI330_HiTVGroup3Simu[] =
+{
+ 0x00,0x1A,0x22,0x63,0x62,0x22,0x08,0x95,
+ 0xDB,0x20,0xB8,0xB8,0x55,0x47,0x2A,0xA6,
+ 0x25,0x2F,0x47,0xFA,0xC8,0xFF,0x8E,0x20,
+ 0x8C,0x6E,0x60,0x15,0x26,0xD3,0xE4,0x11,
+ 0x56,0x36,0x4F,0x6E,0x3F,0x80,0x00,0x80,
+ 0x67,0x36,0x01,0x47,0x0E,0x10,0xBE,0xB4,
+ 0x01,0x05,0x03,0x7E,0x65,0x31,0x14,0x75,
+ 0x18,0x05,0x18,0x05,0x4C,0xA8,0x01
+};
+
+UCHAR XGI330_HiTVGroup3Text[] =
+{
+ 0x00,0x1A,0x22,0x63,0x62,0x22,0x08,0xA7,
+ 0xF5,0x20,0xCE,0xCE,0x55,0x47,0x2A,0xA6,
+ 0x25,0x2F,0x47,0xFA,0xC8,0xFF,0x8E,0x20,
+ 0x8C,0x6E,0x60,0x18,0x2C,0x0C,0x20,0x22,
+ 0x56,0x36,0x4F,0x6E,0x3F,0x80,0x00,0x80,
+ 0x93,0x3C,0x01,0x50,0x2F,0x10,0xF4,0xCA,
+ 0x01,0x05,0x03,0x7E,0x65,0x31,0x14,0x75,
+ 0x18,0x05,0x18,0x05,0x4C,0xA8,0x01
+};
+
+UCHAR XGI330_Ren525pGroup3[] =
+{
+ 0x00,0x14,0x15,0x25,0x55,0x15,0x0b,0x13,
+ 0xB1,0x41,0x62,0x62,0xFF,0xF4,0x45,0xa6,
+ 0x25,0x2F,0x67,0xF6,0xbf,0xFF,0x8E,0x20,
+ 0xAC,0xDA,0x60,0xFe,0x6A,0x9A,0x06,0x10,
+ 0xd1,0x04,0x18,0x0a,0xFF,0x80,0x00,0x80,
+ 0x3c,0x77,0x00,0xEF,0xE0,0x10,0xB0,0xE0,
+ 0x10,0x4F,0x0F,0x0F,0x05,0x0F,0x08,0x6E,
+ 0x1a,0x1F,0x25,0x2a,0x4C,0xAA,0x01
+};
+
+UCHAR XGI330_Ren750pGroup3[] =
+{
+ 0x00,0x14,0x15,0x25,0x55,0x15,0x0b,0x7a,
+ 0x54,0x41,0xE7,0xE7,0xFF,0xF4,0x45,0xa6,
+ 0x25,0x2F,0x67,0xF6,0xbf,0xFF,0x8E,0x20,
+ 0xAC,0x6A,0x60,0x2b,0x52,0xCD,0x61,0x10,
+ 0x51,0x04,0x18,0x0a,0x1F,0x80,0x00,0x80,
+ 0xFF,0xA4,0x04,0x2B,0x94,0x21,0x72,0x94,
+ 0x26,0x05,0x01,0x0F,0xed,0x0F,0x0A,0x64,
+ 0x18,0x1D,0x23,0x28,0x4C,0xAA,0x01
+};
+
+XGI_PanelDelayTblStruct XGI330_PanelDelayTbl[]=
+{
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}},
+{{0x00,0x00}}
+};
+
+XGI330_LVDSDataStruct XGI330_LVDS320x480Data_1[]=
+{
+ {848, 433,400,525},
+ {848, 389,400,525},
+ {848, 433,400,525},
+ {848, 389,400,525},
+ {848, 518,400, 525},
+ {1056, 628,400,525},
+ {400, 525,400,525},
+ {800, 449,1000, 644},
+ {800, 525,1000, 635}
+};
+
+XGI330_LVDSDataStruct XGI330_LVDS800x600Data_1[]=
+{
+ {848, 433,1060, 629},
+ {848, 389,1060, 629},
+ {848, 433,1060, 629},
+ {848, 389,1060, 629},
+ {848, 518,1060, 629},
+ {1056, 628,1056, 628},
+ {1056, 628,1056, 628},
+ {800, 449,1000, 644},
+ {800, 525,1000, 635}
+};
+
+XGI330_LVDSDataStruct XGI330_LVDS800x600Data_2[]=
+{
+ {1056, 628,1056, 628},
+ {1056, 628,1056, 628},
+ {1056, 628,1056, 628},
+ {1056, 628,1056, 628},
+ {1056, 628,1056, 628},
+ {1056, 628,1056, 628},
+ {1056, 628,1056, 628},
+ {800, 449,1000, 644},
+ {800, 525,1000, 635}
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1024x768Data_1[]=
+{
+ { 960 , 438 , 1344 , 806 } , /* 00 (320x200,320x400,640x200,640x400) */
+ { 960 , 388 , 1344 , 806 } , /* 01 (320x350,640x350) */
+ { 1040, 438 , 1344 , 806 } , /* 02 (360x400,720x400) */
+ { 1040, 388 , 1344 , 806 } , /* 03 (720x350) */
+ { 960 , 518 , 1344 , 806 } , /* 04 (320x240,640x480) */
+ {1120 , 638 , 1344 , 806 } , /* 05 (400x300,800x600) */
+ {1344 , 806 , 1344 , 806 } /* 06 (512x384,1024x768) */
+};
+
+
+XGI330_LVDSDataStruct XGI_LVDS1024x768Data_2[]=
+{
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {800, 449,1280, 801},
+ {800, 525,1280, 813}
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_1[]=
+{
+ {1048, 442,1688, 1066},
+ {1048, 392,1688, 1066},
+ {1048, 442,1688, 1066},
+ {1048, 392,1688, 1066},
+ {1048, 522,1688, 1066},
+ {1208, 642,1688, 1066},
+ {1432, 810,1688, 1066},
+ {1688, 1066,1688, 1066}
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_2[]=
+{
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {800, 449,1280, 801},
+ {800, 525,1280, 813}
+};
+/*
+XGI330_LVDSDataStruct XGI_LVDS1280x768Data_1[]=
+{
+ {768,438,1408,806},
+ {768,388,1408,806},
+ {768,438,1408,806},
+ {768,388,1408,806},
+ {768,518,1408,806},
+ {928,638,1408,806},
+ {1408,806,1408,806},
+ {1408,806,1408,806},
+ {1408,806,1408,806}
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1280x768Data_2[]=
+{
+ {1408, 806,1408, 806},
+ {1408, 806,1408, 806},
+ {1408, 806,1408, 806},
+ {1408, 806,1408, 806},
+ {1408, 806,1408, 806},
+ {1408, 806,1408, 806},
+ {1408, 806,1408, 806},
+ {1408, 806,1408, 806},
+ {1408, 806,1408, 806}
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1280x768NData_1[]=
+{
+ {704, 438,1344, 806},
+ {704, 388,1344, 806},
+ {704, 438,1344, 806},
+ {704, 388,1344, 806},
+ {704, 518,1344, 806},
+ {864, 638,1344, 806},
+ {1088, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806}
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1280x768NData_2[]=
+{
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806},
+ {1344, 806,1344, 806}
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1280x768SData_1[]=
+{
+ {1048,438,1688,806},
+ {1048,388,1688,806},
+ {1148,438,1688,806},
+ {1148,388,1688,806},
+ {1048,518,1688,806},
+ {1208,638,1688,806},
+ {1432,806,1688,806},
+ {1688,806,1688,806},
+ {1688,806,1688,806}
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1280x768SData_2[]=
+{
+ {1688,806,1688,806},
+ {1688,806,1688,806},
+ {1688,806,1688,806},
+ {1688,806,1688,806},
+ {1688,806,1688,806},
+ {1688,806,1688,806},
+ {1688,806,1688,806},
+ {1688,806,1688,806},
+ {1688,806,1688,806}
+};
+*/
+XGI330_LVDSDataStruct XGI_LVDS1400x1050Data_1[]=
+{
+ {928,416,1688,1066},
+ {928,366,1688,1066},
+ {928,416,1688,1066},
+ {928,366,1688,1066},
+ {928,496,1688,1066},
+ {1088,616,1688,1066},
+ {1312,784,1688,1066},
+ {1568,1040,1688,1066},
+ {1688,1066,1688,1066}
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1400x1050Data_2[]=
+{
+ {1688,1066,1688,1066},
+ {1688,1066,1688,1066},
+ {1688,1066,1688,1066},
+ {1688,1066,1688,1066},
+ {1688,1066,1688,1066},
+ {1688,1066,1688,1066},
+ {1688,1066,1688,1066},
+ {1688,1066,1688,1066},
+ {1688,1066,1688,1066}
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1600x1200Data_1[]=
+{ /* ;;[ycchen] 12/05/02 LCDHTxLCDVT=2048x1320 */
+ { 1088,520,2048,1320 },/* 00 (320x200,320x400,640x200,640x400) */
+ { 1088,470,2048,1320 },/* 01 (320x350,640x350) */
+ { 1088,520,2048,1320 },/* 02 (360x400,720x400) */
+ { 1088,470,2048,1320 },/* 03 (720x350) */
+ { 1088,600,2048,1320 },/* 04 (320x240,640x480) */
+ { 1248,720,2048,1320 },/* 05 (400x300,800x600) */
+ { 1472,888,2048,1320 },/* 06 (512x384,1024x768) */
+ { 1728,1144,2048,1320 },/* 07 (640x512,1280x1024) */
+ { 1848,1170,2048,1320 },/* 08 (1400x1050) */
+ { 2048,1320,2048,1320 } /* 09 (1600x1200) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDSNoScalingData[]=
+{
+ { 800,449,800,449 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 800,449,800,449 }, /* 01 (320x350,640x350) */
+ { 800,449,800,449 }, /* 02 (360x400,720x400) */
+ { 800,449,800,449 }, /* 03 (720x350) */
+ { 800,525,800,525 }, /* 04 (640x480x60Hz) */
+ { 1056,628,1056,628 }, /* 05 (800x600x60Hz) */
+ { 1344,806,1344,806 }, /* 06 (1024x768x60Hz) */
+ { 1688,1066,1688,1066 }, /* 07 (1280x1024x60Hz) */
+ { 1688,1066,1688,1066 }, /* 08 (1400x1050x60Hz) ;;[ycchen] 12/19/02 */
+ { 2160,1250,2160,1250 }, /* 09 (1600x1200x60Hz) */
+ { 1688,806,1688,806 } /* 0A (1280x768x60Hz) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1024x768Data_1x75[]=
+{
+ {960,438,1312,800 }, /* 00 (320x200,320x400,640x200,640x400) */
+ {960,388,1312,800 }, /* 01 (320x350,640x350) */
+ {1040,438,1312,800 }, /* 02 (360x400,720x400) */
+ {1040,388,1312,800 }, /* 03 (720x350) */
+ {928,512,1312,800 }, /* 04 (320x240,640x480) */
+ {1088,632,1312,800 }, /* 05 (400x300,800x600) */
+ {1312,800,1312,800 }, /* 06 (512x384,1024x768) */
+};
+
+
+XGI330_LVDSDataStruct XGI_LVDS1024x768Data_2x75[]=
+{
+ {1312,800,1312,800}, /* ; 00 (320x200,320x400,640x200,640x400) */
+ {1312,800,1312,800}, /* ; 01 (320x350,640x350) */
+ {1312,800,1312,800}, /* ; 02 (360x400,720x400) */
+ {1312,800,1312,800}, /* ; 03 (720x350) */
+ {1312,800,1312,800}, /* ; 04 (320x240,640x480) */
+ {1312,800,1312,800}, /* ; 05 (400x300,800x600) */
+ {1312,800,1312,800}, /* ; 06 (512x384,1024x768) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_1x75[]=
+{
+ {1048,442,1688,1066 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+ {1048,392,1688,1066 }, /* ; 01 (320x350,640x350) */
+ {1128,442,1688,1066 }, /* ; 02 (360x400,720x400) */
+ {1128,392,1688,1066 }, /* ; 03 (720x350) */
+ {1048,522,1688,1066 }, /* ; 04 (320x240,640x480) */
+ {1208,642,1688,1066 }, /* ; 05 (400x300,800x600) */
+ {1432,810,1688,1066 }, /* ; 06 (512x384,1024x768) */
+ {1688,1066,1688,1066 }, /* ; 06; 07 (640x512,1280x1024) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_2x75[]=
+{
+ {1688,1066,1688,1066 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+ {1688,1066,1688,1066 }, /* ; 01 (320x350,640x350) */
+ {1688,1066,1688,1066 }, /* ; 02 (360x400,720x400) */
+ {1688,1066,1688,1066 }, /* ; 03 (720x350) */
+ {1688,1066,1688,1066 }, /* ; 04 (320x240,640x480) */
+ {1688,1066,1688,1066 }, /* ; 05 (400x300,800x600) */
+ {1688,1066,1688,1066 }, /* ; 06 (512x384,1024x768) */
+ {1688,1066,1688,1066 }, /* ; 06; 07 (640x512,1280x1024) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDSNoScalingDatax75[]=
+{
+ {800,449,800,449 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+ {800,449,800,449 }, /* ; 01 (320x350,640x350) */
+ {900,449,900,449 }, /* ; 02 (360x400,720x400) */
+ {900,449,900,449 }, /* ; 03 (720x350) */
+ {800,500,800,500 }, /* ; 04 (640x480x75Hz) */
+ {1056,625,1056,625 }, /* ; 05 (800x600x75Hz) */
+ {1312,800,1312,800 }, /* ; 06 (1024x768x75Hz) */
+ {1688,1066,1688,1066 }, /* ; 07 (1280x1024x75Hz) */
+ {1688,1066,1688,1066 }, /* ; 08 (1400x1050x75Hz) ;;[ycchen] 12/19/02 */
+ {2160,1250,2160,1250 }, /* ; 09 (1600x1200x75Hz) */
+ {1688,806,1688,806 }, /* ; 0A (1280x768x75Hz) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1024x768Des_1[]=
+{
+ { 0,1048, 0, 771 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 0,1048, 0, 771 }, /* 01 (320x350,640x350) */
+ { 0,1048, 0, 771 }, /* 02 (360x400,720x400) */
+ { 0,1048, 0, 771 }, /* 03 (720x350) */
+ { 0,1048, 0, 771 }, /* 04 (640x480x60Hz) */
+ { 0,1048, 0, 771 }, /* 05 (800x600x60Hz) */
+ { 0,1048, 805, 770 } /* 06 (1024x768x60Hz) */
+} ;
+
+XGI330_LVDSDataStruct XGI_LVDS1024x768Des_2[]=
+{
+ { 1142, 856, 622, 587 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 1142, 856, 597, 562 }, /* 01 (320x350,640x350) */
+ { 1142, 856, 622, 587 }, /* 02 (360x400,720x400) */
+ { 1142, 856, 597, 562 }, /* 03 (720x350) */
+ { 1142,1048, 722, 687 }, /* 04 (640x480x60Hz) */
+ { 1232, 936, 722, 687 }, /* 05 (800x600x60Hz) */
+ { 0,1048, 805, 771 } /* 06 (1024x768x60Hz) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1024x768Des_3[]=
+{
+ { 320, 24, 622, 587 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 320, 24, 597, 562 }, /* 01 (320x350,640x350) */
+ { 320, 24, 622, 587 }, /* 02 (360x400,720x400) */
+ { 320, 24, 597, 562 }, /* 03 (720x350) */
+ { 320, 24, 722, 687 } /* 04 (640x480x60Hz) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_1[]=
+{
+ { 0,1328, 0, 1025 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 0,1328, 0, 1025 }, /* 01 (320x350,640x350) */
+ { 0,1328, 0, 1025 }, /* 02 (360x400,720x400) */
+ { 0,1328, 0, 1025 }, /* 03 (720x350) */
+ { 0,1328, 0, 1025 }, /* 04 (640x480x60Hz) */
+ { 0,1328, 0, 1025 }, /* 05 (800x600x60Hz) */
+ { 0,1328, 0, 1025 }, /* 06 (1024x768x60Hz) */
+ { 0,1328, 1065, 1024 } /* 07 (1280x1024x60Hz) */
+};
+
+ /* The Display setting for DE Mode Panel */
+XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_2[]=
+{
+ { 1368,1008,752,711 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 1368,1008,729,688 }, /* 01 (320x350,640x350) */
+ { 1408,1048,752,711 }, /* 02 (360x400,720x400) */
+ { 1408,1048,729,688 }, /* 03 (720x350) */
+ { 1368,1008,794,753 }, /* 04 (640x480x60Hz) */
+ { 1448,1068,854,813 }, /* 05 (800x600x60Hz) */
+ { 1560,1200,938,897 }, /* 06 (1024x768x60Hz) */
+ { 0000,1328,0,1025 } /* 07 (1280x1024x60Hz) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1400x1050Des_1[]=
+{
+ { 0,1448,0,1051 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 0,1448,0,1051 }, /* 01 (320x350,640x350) */
+ { 0,1448,0,1051 }, /* 02 (360x400,720x400) */
+ { 0,1448,0,1051 }, /* 03 (720x350) */
+ { 0,1448,0,1051 }, /* 04 (640x480x60Hz) */
+ { 0,1448,0,1051 }, /* 05 (800x600x60Hz) */
+ { 0,1448,0,1051 }, /* 06 (1024x768x60Hz) */
+ { 0,1448,0,1051 }, /* 07 (1280x1024x60Hz) */
+ { 0,1448,0,1051 } /* 08 (1400x1050x60Hz) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1400x1050Des_2[]=
+{
+ { 1308,1068, 781, 766 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 1308,1068, 781, 766 }, /* 01 (320x350,640x350) */
+ { 1308,1068, 781, 766 }, /* 02 (360x400,720x400) */
+ { 1308,1068, 781, 766 }, /* 03 (720x350) */
+ { 1308,1068, 781, 766 }, /* 04 (640x480x60Hz) */
+ { 1388,1148, 841, 826 }, /* 05 (800x600x60Hz) */
+ { 1490,1250, 925, 910 }, /* 06 (1024x768x60Hz) */
+ { 1608,1368,1053,1038 }, /* 07 (1280x1024x60Hz) */
+ { 0,1448,0,1051 } /* 08 (1400x1050x60Hz) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1600x1200Des_1[]=
+{
+ { 0,1664,0,1201 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 0,1664,0,1201 }, /* 01 (320x350,640x350) */
+ { 0,1664,0,1201 }, /* 02 (360x400,720x400) */
+ { 0,1664,0,1201 }, /* 03 (720x350) */
+ { 0,1664,0,1201 }, /* 04 (640x480x60Hz) */
+ { 0,1664,0,1201 }, /* 05 (800x600x60Hz) */
+ { 0,1664,0,1201 }, /* 06 (1024x768x60Hz) */
+ { 0,1664,0,1201 }, /* 07 (1280x1024x60Hz) */
+ { 0,1664,0,1201 }, /* 08 (1400x1050x60Hz) */
+ { 0,1664,0,1201 } /* 09 (1600x1200x60Hz) */
+};
+
+
+
+XGI330_LCDDataDesStruct2 XGI_LVDSNoScalingDesData[]=
+{
+ { 0, 648, 448, 405, 96, 2 }, /* 00 (320x200,320x400,640x200,640x400) */
+ { 0, 648, 448, 355, 96, 2 }, /* 01 (320x350,640x350) */
+ { 0, 648, 448, 405, 96, 2 }, /* 02 (360x400,720x400) */
+ { 0, 648, 448, 355, 96, 2 }, /* 03 (720x350) */
+ { 0, 648, 1, 483, 96, 2 }, /* 04 (640x480x60Hz) */
+ { 0, 840, 627, 600, 128, 4 }, /* 05 (800x600x60Hz) */
+ { 0,1048, 805, 770, 136, 6 }, /* 06 (1024x768x60Hz) */
+ { 0,1328,0,1025, 112, 3 }, /* 07 (1280x1024x60Hz) */
+ { 0,1438,0,1051, 112, 3 }, /* 08 (1400x1050x60Hz) ;;[ycchen] 12/19/02 */
+ { 0,1664,0,1201, 192, 3 }, /* 09 (1600x1200x60Hz) */
+ { 0,1328,0,0771, 112, 6 } /* 0A (1280x768x60Hz) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1024x768Des_1x75[]= /* ; 1024x768 Full-screen */
+{
+ {0,1040,0,769}, /* ; 00 (320x200,320x400,640x200,640x400) */
+ {0,1040,0,769}, /* ; 01 (320x350,640x350) */
+ {0,1040,0,769}, /* ; 02 (360x400,720x400) */
+ {0,1040,0,769}, /* ; 03 (720x350) */
+ {0,1040,0,769}, /* ; 04 (640x480x75Hz) */
+ {0,1040,0,769}, /* ; 05 (800x600x75Hz) */
+ {0,1040,0,769} /* ; 06 (1024x768x75Hz) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1024x768Des_2x75[]= /* ; 1024x768 center-screen (Enh. Mode) */
+{
+ {1142, 856,622,587 }, /* 00 (320x200,320x400,640x200,640x400) */
+ {1142, 856,597,562 }, /* 01 (320x350,640x350) */
+ {1142, 856,622,587 }, /* 02 (360x400,720x400) */
+ {1142, 856,597,562 }, /* 03 (720x350) */
+ {1142,1048,722,687 }, /* 04 (640x480x60Hz) */
+ {1232, 936,722,687 }, /* 05 (800x600x60Hz) */
+ { 0,1048,805,771 } /* 06 (1024x768x60Hz) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1024x768Des_3x75[]= /* ; 1024x768 center-screen (St.Mode) */
+{
+ {320,24,622,587 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+ {320,24,597,562 }, /* ; 01 (320x350,640x350) */
+ {320,24,622,587 }, /* ; 02 (360x400,720x400) */
+ {320,24,597,562 }, /* ; 03 (720x350) */
+ {320,24,722,687 } /* ; 04 (640x480x60Hz) */
+};
+
+XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_1x75[]=
+{
+ {0,1296,0,1025}, /* ; 00 (320x200,320x400,640x200,640x400) */
+ {0,1296,0,1025}, /* ; 01 (320x350,640x350) */
+ {0,1296,0,1025}, /* ; 02 (360x400,720x400) */
+ {0,1296,0,1025}, /* ; 03 (720x350) */
+ {0,1296,0,1025}, /* ; 04 (640x480x75Hz) */
+ {0,1296,0,1025}, /* ; 05 (800x600x75Hz) */
+ {0,1296,0,1025}, /* ; 06 (1024x768x75Hz) */
+ {0,1296,0,1025} /* ; 07 (1280x1024x75Hz) */
+};
+
+/* The Display setting for DE Mode Panel */
+XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_2x75[]= /* [ycchen] 02/18/03 Set DE as default */
+{
+ {1368,976,752,711 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+ {1368,976,729,688 }, /* ; 01 (320x350,640x350) */
+ {1408,976,752,711 }, /* ; 02 (360x400,720x400) */
+ {1408,976,729,688 }, /* ; 03 (720x350) */
+ {1368,976,794,753 }, /* ; 04 (640x480x75Hz) */
+ {1448,1036,854,813}, /* ; 05 (800x600x75Hz) */
+ {1560,1168,938,897}, /* ; 06 (1024x768x75Hz) */
+ {0,1296,0,1025 } /* ; 07 (1280x1024x75Hz) */
+};
+
+XGI330_LCDDataDesStruct2 XGI_LVDSNoScalingDesDatax75[]= /* Scaling LCD 75Hz */
+{
+ { 0,648,448,405,96,2 }, /* ; 00 (320x200,320x400,640x200,640x400) */
+ { 0,648,448,355,96,2 }, /* ; 01 (320x350,640x350) */
+ { 0,729,448,405,108,2 }, /* ; 02 (360x400,720x400) */
+ { 0,729,448,355,108,2 }, /* ; 03 (720x350) */
+ { 0,656,0,481,64,3 }, /* ; 04 (640x480x75Hz) */
+ { 0,816,0,601,80,3 }, /* ; 05 (800x600x75Hz) */
+ { 0,1040,0,769,96,3 }, /* ; 06 (1024x768x75Hz) */
+ { 0,1296,0,1025,144,3 }, /* ; 07 (1280x1024x75Hz) */
+ { 0,1448,0,1051,112,3 }, /* ; 08 (1400x1050x75Hz) ;;[ycchen] 12/19/02 */
+ { 0,1664,0,1201,192,3 }, /* ; 09 (1600x1200x75Hz) */
+ { 0,1328,0,771,112,6 } /* ; 0A (1280x768x75Hz) */
+};
+
+XGI330_LVDSDataStruct XGI330_LVDS640x480Data_1[]=
+{
+ {800, 449, 800, 449},
+ {800, 449, 800, 449},
+ {800, 449, 800, 449},
+ {800, 449, 800, 449},
+ {800, 525, 800, 525},
+ {1056, 628,1056, 628},
+ {1056, 628,1056, 628},
+ {1056, 628,1056, 628},
+ {1056, 628,1056, 628}
+};
+
+XGI330_CHTVDataStruct XGI_CHTVUNTSCData[]=
+{
+ {840, 600, 840, 600},
+ {840, 600, 840, 600},
+ {840, 600, 840, 600},
+ {840, 600, 840, 600},
+ {784, 600, 784, 600},
+ {1064, 750,1064, 750}
+};
+
+XGI330_CHTVDataStruct XGI_CHTVONTSCData[]=
+{
+ {840, 525, 840, 525},
+ {840, 525, 840, 525},
+ {840, 525, 840, 525},
+ {840, 525, 840, 525},
+ {784, 525, 784, 525},
+ {1040, 700,1040, 700}
+};
+
+XGI330_CHTVDataStruct XGI_CHTVUPALData[]=
+{
+ {1008, 625,1008, 625},
+ {1008, 625,1008, 625},
+ {1008, 625,1008, 625},
+ {1008, 625,1008, 625},
+ {840, 750, 840, 750},
+ {936, 836, 936, 836}
+};
+
+XGI330_CHTVDataStruct XGI_CHTVOPALData[]=
+{
+ {1008, 625,1008, 625},
+ {1008, 625,1008, 625},
+ {1008, 625,1008, 625},
+ {1008, 625,1008, 625},
+ {840, 625, 840, 625},
+ {960, 750, 960, 750}
+};
+
+XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_1_H[]=
+{
+ /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+ {{ 0x4B,0x27,0x8F,0x32,0x1B,0x00,0x45,0x00 }}, /* 00 (320x) */
+ {{ 0x4B,0x27,0x8F,0x2B,0x03,0x00,0x44,0x00 }}, /* 01 (360x) */
+ {{ 0x55,0x31,0x99,0x46,0x1D,0x00,0x55,0x00 }}, /* 02 (400x) */
+ {{ 0x63,0x3F,0x87,0x4A,0x93,0x00,0x01,0x00 }}, /* 03 (512x) */
+ {{ 0x73,0x4F,0x97,0x55,0x86,0x00,0x05,0x00 }}, /* 04 (640x) */
+ {{ 0x73,0x4F,0x97,0x55,0x86,0x00,0x05,0x00 }}, /* 05 (720x) */
+ {{ 0x87,0x63,0x8B,0x69,0x1A,0x00,0x26,0x00 }}, /* 06 (800x) */
+ {{ 0xA3,0x7F,0x87,0x86,0x97,0x00,0x02,0x00 }} /* 07 (1024x) */
+};
+
+XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_1_H[]=
+{
+ /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+ {{ 0x56,0x27,0x9A,0x30,0x1E,0x00,0x05,0x00 }}, /* 00 (320x) */
+ {{ 0x56,0x27,0x9A,0x30,0x1E,0x00,0x05,0x00 }}, /* 01 (360x) */
+ {{ 0x60,0x31,0x84,0x3A,0x88,0x00,0x01,0x00 }}, /* 02 (400x) */
+ {{ 0x6E,0x3F,0x92,0x48,0x96,0x00,0x01,0x00 }}, /* 03 (512x) */
+ {{ 0x7E,0x4F,0x82,0x58,0x06,0x00,0x06,0x00 }}, /* 04 (640x) */
+ {{ 0x7E,0x4F,0x82,0x58,0x06,0x00,0x06,0x00 }}, /* 05 (720x) */
+ {{ 0x92,0x63,0x96,0x6C,0x1A,0x00,0x06,0x00 }}, /* 06 (800x) */
+ {{ 0xAE,0x7F,0x92,0x88,0x96,0x00,0x02,0x00 }}, /* 07 (1024x) */
+ {{ 0xCE,0x9F,0x92,0xA8,0x16,0x00,0x07,0x00 }} /* 08 (1280x) */
+};
+
+XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_2_H[]=
+{
+ /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+ {{ 0x63,0x27,0x87,0x3B,0x8C,0x00,0x01,0x00 }}, /* 00 (320x) */
+ {{ 0x63,0x27,0x87,0x3B,0x8C,0x00,0x01,0x00 }}, /* 01 (360x) */
+ {{ 0x63,0x31,0x87,0x3D,0x8E,0x00,0x01,0x00 }}, /* 02 (400x) */
+ {{ 0x63,0x3F,0x87,0x45,0x96,0x00,0x01,0x00 }}, /* 03 (512x) */
+ {{ 0xA3,0x4F,0x87,0x6E,0x9F,0x00,0x06,0x00 }}, /* 04 (640x) */
+ {{ 0xA3,0x4F,0x87,0x6E,0x9F,0x00,0x06,0x00 }}, /* 05 (720x) */
+ {{ 0xA3,0x63,0x87,0x78,0x89,0x00,0x02,0x00 }}, /* 06 (800x) */
+ {{ 0xA3,0x7F,0x87,0x86,0x97,0x00,0x02,0x00 }} /* 07 (1024x) */
+};
+
+XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_2_H[]=
+{
+ /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+ {{ 0x7E,0x3B,0x9A,0x44,0x12,0x00,0x01,0x00 }}, /* 00 (320x) */
+ {{ 0x7E,0x3B,0x9A,0x44,0x12,0x00,0x01,0x00 }}, /* 01 (360x) */
+ {{ 0x7E,0x40,0x84,0x49,0x91,0x00,0x01,0x00 }}, /* 02 (400x) */
+ {{ 0x7E,0x47,0x93,0x50,0x9E,0x00,0x01,0x00 }}, /* 03 (512x) */
+ {{ 0xCE,0x77,0x8A,0x80,0x8E,0x00,0x02,0x00 }}, /* 04 (640x) */
+ {{ 0xCE,0x77,0x8A,0x80,0x8E,0x00,0x02,0x00 }}, /* 05 (720x) */
+ {{ 0xCE,0x81,0x94,0x8A,0x98,0x00,0x02,0x00 }}, /* 06 (800x) */
+ {{ 0xCE,0x8F,0x82,0x98,0x06,0x00,0x07,0x00 }}, /* 07 (1024x) */
+ {{ 0xCE,0x9F,0x92,0xA8,0x16,0x00,0x07,0x00 }} /* 08 (1280x) */
+};
+
+XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11400x1050_1_H[]=
+{ /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+ {{ 0x47,0x27,0x8B,0x2C,0x1A,0x00,0x05,0x00 }}, /* 00 (320x) */
+ {{ 0x47,0x27,0x8B,0x30,0x1E,0x00,0x05,0x00 }}, /* 01 (360x) */
+ {{ 0x51,0x31,0x95,0x36,0x04,0x00,0x01,0x00 }}, /* 02 (400x) */
+ {{ 0x5F,0x3F,0x83,0x44,0x92,0x00,0x01,0x00 }}, /* 03 (512x) */
+ {{ 0x6F,0x4F,0x93,0x54,0x82,0x00,0x05,0x00 }}, /* 04 (640x) */
+ {{ 0x6F,0x4F,0x93,0x54,0x82,0x00,0x05,0x00 }}, /* 05 (720x) */
+ {{ 0x83,0x63,0x87,0x68,0x16,0x00,0x06,0x00 }}, /* 06 (800x) */
+ {{ 0x9F,0x7F,0x83,0x84,0x92,0x00,0x02,0x00 }}, /* 07 (1024x) */
+ {{ 0xBF,0x9F,0x83,0xA4,0x12,0x00,0x07,0x00 }}, /* 08 (1280x) */
+ {{ 0xCE,0xAE,0x92,0xB3,0x01,0x00,0x03,0x00 }} /* 09 (1400x) */
+};
+
+XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11400x1050_2_H[]=
+{ /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+ {{ 0x76,0x3F,0x83,0x45,0x8C,0x00,0x41,0x00 }}, /* 00 (320x) */
+ {{ 0x76,0x3F,0x83,0x45,0x8C,0x00,0x41,0x00 }}, /* 01 (360x) */
+ {{ 0x76,0x31,0x9A,0x48,0x9F,0x00,0x41,0x00 }}, /* 02 (400x) */
+ {{ 0x76,0x3F,0x9A,0x4F,0x96,0x00,0x41,0x00 }}, /* 03 (512x) */
+ {{ 0xCE,0x7E,0x82,0x87,0x9E,0x00,0x02,0x00 }}, /* 04 (640x) */
+ {{ 0xCE,0x7E,0x82,0x87,0x9E,0x00,0x02,0x00 }}, /* 05 (720x) */
+ {{ 0xCE,0x63,0x92,0x96,0x04,0x00,0x07,0x00 }}, /* 06 (800x) */
+ {{ 0xCE,0x7F,0x92,0xA4,0x12,0x00,0x07,0x00 }}, /* 07 (1024x) */
+ {{ 0xCE,0x9F,0x92,0xB4,0x02,0x00,0x03,0x00 }}, /* 08 (1280x) */
+ {{ 0xCE,0xAE,0x92,0xBC,0x0A,0x00,0x03,0x00 }} /* 09 (1400x) */
+};
+
+XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11600x1200_1_H[]=
+/* ;302lv channelA [ycchen] 12/05/02 LCDHT=2048 */
+{ /* ; CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+ {{ 0x5B,0x27,0x9F,0x32,0x0A,0x00,0x01,0x00 }},/* 00 (320x) */
+ {{ 0x5B,0x27,0x9F,0x32,0x0A,0x00,0x01,0x00 }},/* 01 (360x) */
+ {{ 0x65,0x31,0x89,0x3C,0x94,0x00,0x01,0x00 }},/* 02 (400x) */
+ {{ 0x73,0x3F,0x97,0x4A,0x82,0x00,0x05,0x00 }},/* 03 (512x) */
+ {{ 0x83,0x4F,0x87,0x51,0x09,0x00,0x06,0x00 }},/* 04 (640x) */
+ {{ 0x83,0x4F,0x87,0x51,0x09,0x00,0x06,0x00 }},/* 05 (720x) */
+ {{ 0x97,0x63,0x9B,0x65,0x1D,0x00,0x06,0xF0 }},/* 06 (800x) */
+ {{ 0xB3,0x7F,0x97,0x81,0x99,0x00,0x02,0x00 }},/* 07 (1024x) */
+ {{ 0xD3,0x9F,0x97,0xA1,0x19,0x00,0x07,0x00 }},/* 08 (1280x) */
+ {{ 0xE2,0xAE,0x86,0xB9,0x91,0x00,0x03,0x00 }},/* 09 (1400x) */
+ {{ 0xFB,0xC7,0x9F,0xC9,0x81,0x00,0x07,0x00 }} /* 0A (1600x) */
+};
+
+XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_1_V[]=
+{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A+CR09(5->7) */
+ {{ 0x97,0x1F,0x60,0x87,0x5D,0x83,0x10 }}, /* 00 (x350) */
+ {{ 0xB4,0x1F,0x92,0x89,0x8F,0xB5,0x30 }}, /* 01 (x400) */
+ {{ 0x04,0x3E,0xE2,0x89,0xDF,0x05,0x00 }}, /* 02 (x480) */
+ {{ 0x7C,0xF0,0x5A,0x8F,0x57,0x7D,0xA0 }}, /* 03 (x600) */
+ {{ 0x24,0xF5,0x02,0x88,0xFF,0x25,0x90 }} /* 04 (x768) */
+};
+
+XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_2_V[]=
+{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
+ {{ 0x24,0xBB,0x31,0x87,0x5D,0x25,0x30 }}, /* 00 (x350) */
+ {{ 0x24,0xBB,0x4A,0x80,0x8F,0x25,0x30 }}, /* 01 (x400) */
+ {{ 0x24,0xBB,0x72,0x88,0xDF,0x25,0x30 }}, /* 02 (x480) */
+ {{ 0x24,0xF1,0xAE,0x84,0x57,0x25,0xB0 }}, /* 03 (x600) */
+ {{ 0x24,0xF5,0x02,0x88,0xFF,0x25,0x90 }} /* 04 (x768) */
+};
+
+XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_1_V[]=
+{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
+ {{ 0x86,0x1F,0x5E,0x82,0x5D,0x87,0x00 }}, /* 00 (x350) */
+ {{ 0xB8,0x1F,0x90,0x84,0x8F,0xB9,0x30 }}, /* 01 (x400) */
+ {{ 0x08,0x3E,0xE0,0x84,0xDF,0x09,0x00 }}, /* 02 (x480) */
+ {{ 0x80,0xF0,0x58,0x8C,0x57,0x81,0xA0 }}, /* 03 (x600) */
+ {{ 0x28,0xF5,0x00,0x84,0xFF,0x29,0x90 }}, /* 04 (x768) */
+ {{ 0x28,0x5A,0x13,0x87,0xFF,0x29,0xA9 }} /* 05 (x1024) */
+};
+
+XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_2_V[]=
+{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
+ {{ 0x28,0xD2,0xAF,0x83,0xAE,0xD8,0xA1 }}, /* 00 (x350) */
+ {{ 0x28,0xD2,0xC8,0x8C,0xC7,0xF2,0x81 }}, /* 01 (x400) */
+ {{ 0x28,0xD2,0xF0,0x84,0xEF,0x1A,0xB1 }}, /* 02 (x480) */
+ {{ 0x28,0xDE,0x2C,0x8F,0x2B,0x56,0x91 }}, /* 03 (x600) */
+ {{ 0x28,0xDE,0x80,0x83,0x7F,0xAA,0x91 }}, /* 04 (x768) */
+ {{ 0x28,0x5A,0x13,0x87,0xFF,0x29,0xA9 }} /* 05 (x1024) */
+};
+
+XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11400x1050_1_V[]=
+{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
+ {{ 0x6C,0x1F,0x60,0x84,0x5D,0x6D,0x10 }}, /* 00 (x350) */
+ {{ 0x9E,0x1F,0x93,0x86,0x8F,0x9F,0x30 }}, /* 01 (x400) */
+ {{ 0xEE,0x1F,0xE2,0x86,0xDF,0xEF,0x10 }}, /* 02 (x480) */
+ {{ 0x66,0xF0,0x5A,0x8e,0x57,0x67,0xA0 }}, /* 03 (x600) */
+ {{ 0x0E,0xF5,0x02,0x86,0xFF,0x0F,0x90 }}, /* 04 (x768) */
+ {{ 0x0E,0x5A,0x02,0x86,0xFF,0x0F,0x89 }}, /* 05 (x1024) */
+ {{ 0x28,0x10,0x1A,0x80,0x19,0x29,0x0F }} /* 06 (x1050) */
+};
+
+XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11400x1050_2_V[]=
+{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
+ {{ 0x28,0x92,0xB6,0x83,0xB5,0xCF,0x81 }}, /* 00 (x350) */
+ {{ 0x28,0x92,0xD5,0x82,0xD4,0xEE,0x81 }}, /* 01 (x400) */
+ {{ 0x28,0x92,0xFD,0x8A,0xFC,0x16,0xB1 }}, /* 02 (x480) */
+ {{ 0x28,0xD4,0x39,0x86,0x57,0x29,0x81 }}, /* 03 (x600) */
+ {{ 0x28,0xD4,0x8D,0x9A,0xFF,0x29,0xA1 }}, /* 04 (x768) */
+ {{ 0x28,0x5A,0x0D,0x9A,0xFF,0x29,0xA9 }}, /* 05 (x1024) */
+ {{ 0x28,0x10,0x1A,0x87,0x19,0x29,0x8F }} /* 06 (x1050) */
+};
+
+XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11600x1200_1_V[]=
+{
+ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A+CR09(5->7) */
+ {{ 0xd4,0x1F,0x81,0x84,0x5D,0xd5,0x10 }}, /* 00 (x350) */
+ {{ 0x06,0x3e,0xb3,0x86,0x8F,0x07,0x20 }}, /* 01 (x400) */
+ {{ 0x56,0xba,0x03,0x86,0xDF,0x57,0x00 }}, /* 02 (x480) */
+ {{ 0xce,0xF0,0x7b,0x8e,0x57,0xcf,0xa0 }}, /* 03 (x600) */
+ {{ 0x76,0xF5,0x23,0x86,0xFF,0x77,0x90 }}, /* 04 (x768) */
+ {{ 0x76,0x5A,0x23,0x86,0xFF,0x77,0x89 }}, /* 05 (x1024) */
+ {{ 0x90,0x10,0x1A,0x8E,0x19,0x91,0x2F }}, /* 06 (x1050) */
+ {{ 0x26,0x11,0xd3,0x86,0xaF,0x27,0x3f }} /* 07 (x1200) */
+};
+
+XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_1_Hx75[]=
+{ /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+ {{ 0x4B,0x27,0x8F,0x32,0x1B,0x00,0x45,0x00 }},/* ; 00 (320x) */
+ {{ 0x4B,0x27,0x8F,0x2B,0x03,0x00,0x44,0x00 }},/* ; 01 (360x) */
+ {{ 0x55,0x31,0x99,0x46,0x1D,0x00,0x55,0x00 }},/* ; 02 (400x) */
+ {{ 0x63,0x3F,0x87,0x4A,0x93,0x00,0x01,0x00 }},/* ; 03 (512x) */
+ {{ 0x6F,0x4F,0x93,0x54,0x80,0x00,0x05,0x00 }},/* ; 04 (640x) */
+ {{ 0x6F,0x4F,0x93,0x54,0x80,0x00,0x05,0x00 }},/* ; 05 (720x) */
+ {{ 0x83,0x63,0x87,0x68,0x14,0x00,0x26,0x00 }},/* ; 06 (800x) */
+ {{ 0x9F,0x7F,0x83,0x85,0x91,0x00,0x02,0x00 }} /* ; 07 (1024x) */
+};
+
+XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_1_Vx75[]=
+{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A+CR09(5->7) */
+ {{ 0x97,0x1F,0x60,0x87,0x5D,0x83,0x10 }},/* ; 00 (x350) */
+ {{ 0xB4,0x1F,0x92,0x89,0x8F,0xB5,0x30 }},/* ; 01 (x400) */
+ {{ 0xFE,0x1F,0xE0,0x84,0xDF,0xFF,0x10 }},/* ; 02 (x480) */
+ {{ 0x76,0xF0,0x58,0x8C,0x57,0x77,0xA0 }},/* ; 03 (x600) */
+ {{ 0x1E,0xF5,0x00,0x83,0xFF,0x1F,0x90 }} /* ; 04 (x768) */
+};
+
+XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_2_Hx75[]=
+{ /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+ {{ 0x63,0x27,0x87,0x3B,0x8C,0x00,0x01,0x00 }},/* ; 00 (320x) */
+ {{ 0x63,0x27,0x87,0x3B,0x8C,0x00,0x01,0x00 }},/* ; 01 (360x) */
+ {{ 0x63,0x31,0x87,0x3D,0x8E,0x00,0x01,0x00 }},/* ; 02 (400x) */
+ {{ 0x63,0x3F,0x87,0x45,0x96,0x00,0x01,0x00 }},/* ; 03 (512x) */
+ {{ 0xA3,0x4F,0x87,0x6E,0x9F,0x00,0x06,0x00 }},/* ; 04 (640x) */
+ {{ 0xA3,0x4F,0x87,0x6E,0x9F,0x00,0x06,0x00 }},/* ; 05 (720x) */
+ {{ 0xA3,0x63,0x87,0x78,0x89,0x00,0x02,0x00 }},/* ; 06 (800x) */
+ {{ 0xA3,0x7F,0x87,0x86,0x97,0x00,0x02,0x00 }} /* ; 07 (1024x) */
+};
+
+XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_2_Vx75[]=
+{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
+ {{ 0x24,0xBB,0x31,0x87,0x5D,0x25,0x30 }},/* ; 00 (x350) */
+ {{ 0x24,0xBB,0x4A,0x80,0x8F,0x25,0x30 }},/* ; 01 (x400) */
+ {{ 0x24,0xBB,0x72,0x88,0xDF,0x25,0x30 }},/* ; 02 (x480) */
+ {{ 0x24,0xF1,0xAE,0x84,0x57,0x25,0xB0 }},/* ; 03 (x600) */
+ {{ 0x24,0xF5,0x02,0x88,0xFF,0x25,0x90 }} /* ; 04 (x768) */
+};
+
+XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_1_Hx75[]=
+{ /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+ {{ 0x56,0x27,0x9A,0x30,0x1E,0x00,0x05,0x00 }},/* ; 00 (320x) */
+ {{ 0x56,0x27,0x9A,0x30,0x1E,0x00,0x05,0x00 }},/* ; 01 (360x) */
+ {{ 0x60,0x31,0x84,0x3A,0x88,0x00,0x01,0x00 }},/* ; 02 (400x) */
+ {{ 0x6E,0x3F,0x92,0x48,0x96,0x00,0x01,0x00 }},/* ; 03 (512x) */
+ {{ 0x7E,0x4F,0x82,0x54,0x06,0x00,0x06,0x00 }},/* ; 04 (640x) */
+ {{ 0x7E,0x4F,0x82,0x54,0x06,0x00,0x06,0x00 }},/* ; 05 (720x) */
+ {{ 0x92,0x63,0x96,0x68,0x1A,0x00,0x06,0x00 }},/* ; 06 (800x) */
+ {{ 0xAE,0x7F,0x92,0x84,0x96,0x00,0x02,0x00 }},/* ; 07 (1024x) */
+ {{ 0xCE,0x9F,0x92,0xA5,0x17,0x00,0x07,0x00 }} /* ; 08 (1280x) */
+};
+
+XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_1_Vx75[]=
+{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
+ {{ 0x86,0xD1,0xBC,0x80,0xBB,0xE5,0x00 }},/* ; 00 (x350) */
+ {{ 0xB8,0x1F,0x90,0x84,0x8F,0xB9,0x30 }},/* ; 01 (x400) */
+ {{ 0x08,0x3E,0xE0,0x84,0xDF,0x09,0x00 }},/* ; 02 (x480) */
+ {{ 0x80,0xF0,0x58,0x8C,0x57,0x81,0xA0 }},/* ; 03 (x600) */
+ {{ 0x28,0xF5,0x00,0x84,0xFF,0x29,0x90 }},/* ; 04 (x768) */
+ {{ 0x28,0x5A,0x13,0x87,0xFF,0x29,0xA9 }} /* ; 05 (x1024) */
+};
+
+XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_2_Hx75[]=
+{
+ /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
+ {{ 0x7E,0x3B,0x9A,0x44,0x12,0x00,0x01,0x00 }},/* ; 00 (320x) */
+ {{ 0x7E,0x3B,0x9A,0x44,0x12,0x00,0x01,0x00 }},/* ; 01 (360x) */
+ {{ 0x7E,0x40,0x84,0x49,0x91,0x00,0x01,0x00 }},/* ; 02 (400x) */
+ {{ 0x7E,0x47,0x93,0x50,0x9E,0x00,0x01,0x00 }},/* ; 03 (512x) */
+ {{ 0xCE,0x77,0x8A,0x80,0x8E,0x00,0x02,0x00 }},/* ; 04 (640x) */
+ {{ 0xCE,0x77,0x8A,0x80,0x8E,0x00,0x02,0x00 }},/* ; 05 (720x) */
+ {{ 0xCE,0x81,0x94,0x8A,0x98,0x00,0x02,0x00 }},/* ; 06 (800x) */
+ {{ 0xCE,0x8F,0x82,0x98,0x06,0x00,0x07,0x00 }},/* ; 07 (1024x) */
+ {{ 0xCE,0x9F,0x92,0xA8,0x16,0x00,0x07,0x00 }} /* ; 08 (1280x) */
+};
+
+XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_2_Vx75[]=
+{
+ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
+ {{ 0x28,0xD2,0xAF,0x83,0xAE,0xD8,0xA1 }},/* ; 00 (x350) */
+ {{ 0x28,0xD2,0xC8,0x8C,0xC7,0xF2,0x81 }},/* ; 01 (x400) */
+ {{ 0x28,0xD2,0xF0,0x84,0xEF,0x1A,0xB1 }},/* ; 02 (x480) */
+ {{ 0x28,0xDE,0x2C,0x8F,0x2B,0x56,0x91 }},/* ; 03 (x600) */
+ {{ 0x28,0xDE,0x80,0x83,0x7F,0xAA,0x91 }},/* ; 04 (x768) */
+ {{ 0x28,0x5A,0x13,0x87,0xFF,0x29,0xA9 }} /* ; 05 (x1024) */
+};
+
+XGI_LVDSCRT1DataStruct XGI_CHTVCRT1UNTSC[]=
+{
+ {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
+ 0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,0x00 }},
+ {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
+ 0xd0,0x82,0x5d,0x57,0x00,0x00,0x01,0x00 }},
+ {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
+ 0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,0x00 }},
+ {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
+ 0xd0,0x82,0x5d,0x57,0x00,0x00,0x01,0x00 }},
+ {{0x5d,0x4f,0x81,0x53,0x9c,0x56,0xba,
+ 0x18,0x84,0xdf,0x57,0x00,0x00,0x01,0x00 }},
+ {{0x80,0x63,0x84,0x6c,0x17,0xec,0xf0,
+ 0x90,0x8c,0x57,0xed,0x20,0x00,0x06,0x01 }}
+};
+
+XGI_LVDSCRT1DataStruct XGI_CHTVCRT1ONTSC[]=
+{
+ {{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
+ 0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,0x00 }},
+ {{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
+ 0xb0,0x8d,0x5d,0x0c,0x00,0x00,0x01,0x00 }},
+ {{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
+ 0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,0x00 }},
+ {{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
+ 0xb0,0x8d,0x5d,0x0c,0x00,0x00,0x01,0x00 }},
+ {{0x5d,0x4f,0x81,0x56,0x9c,0x0b,0x3e,
+ 0xe8,0x84,0xdf,0x0c,0x00,0x00,0x01,0x00 }},
+ {{0x7d,0x63,0x81,0x6a,0x16,0xba,0xf0,
+ 0x7f,0x86,0x57,0xbb,0x00,0x00,0x06,0x01 }}
+};
+
+XGI_LVDSCRT1DataStruct XGI_CHTVCRT1UPAL[]=
+{
+ {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+ 0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,0x00 }},
+ {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+ 0xde,0x81,0x5d,0x70,0x00,0x00,0x05,0x00 }},
+ {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+ 0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,0x00 }},
+ {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+ 0xde,0x81,0x5d,0x70,0x00,0x00,0x05,0x00 }},
+ {{0x64,0x4f,0x88,0x55,0x80,0xec,0xba,
+ 0x50,0x84,0xdf,0xed,0x00,0x00,0x05,0x00 }},
+ {{0x70,0x63,0x94,0x68,0x8d,0x42,0xf1,
+ 0xc8,0x8c,0x57,0xe9,0x20,0x00,0x05,0x01 }}
+};
+
+XGI_LVDSCRT1DataStruct XGI_CHTVCRT1OPAL[]=
+{
+ {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+ 0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,0x00 }},
+ {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+ 0xde,0x81,0x5d,0x70,0x00,0x00,0x05,0x00 }},
+ {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+ 0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,0x00 }},
+ {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
+ 0xde,0x81,0x5d,0x70,0x00,0x00,0x05,0x00 }},
+ {{0x64,0x4f,0x88,0x55,0x80,0x6f,0xba,
+ 0x20,0x83,0xdf,0x70,0x00,0x00,0x05,0x00 }},
+ {{0x73,0x63,0x97,0x69,0x8e,0xec,0xf0,
+ 0x90,0x8c,0x57,0xed,0x20,0x00,0x05,0x01 }}
+};
+
+/*add for new UNIVGABIOS*/
+XGI330_LCDDataTablStruct XGI_LCDDataTable[]=
+{
+ {Panel1024x768,0x0019,0x0001,0}, /* XGI_ExtLCD1024x768Data */
+ {Panel1024x768,0x0019,0x0000,1}, /* XGI_StLCD1024x768Data */
+ {Panel1024x768,0x0018,0x0010,2}, /* XGI_CetLCD1024x768Data */
+ {Panel1280x1024,0x0019,0x0001,3}, /* XGI_ExtLCD1280x1024Data */
+ {Panel1280x1024,0x0019,0x0000,4}, /* XGI_StLCD1280x1024Data */
+ {Panel1280x1024,0x0018,0x0010,5}, /* XGI_CetLCD1280x1024Data */
+ {Panel1400x1050,0x0019,0x0001,6}, /* XGI_ExtLCD1400x1050Data */
+ {Panel1400x1050,0x0019,0x0000,7}, /* XGI_StLCD1400x1050Data */
+ {Panel1400x1050,0x0018,0x0010,8}, /* XGI_CetLCD1400x1050Data */
+ {Panel1600x1200,0x0019,0x0001,9}, /* XGI_ExtLCD1600x1200Data */
+ {Panel1600x1200,0x0019,0x0000,10}, /* XGI_StLCD1600x1200Data */
+ {PanelRef60Hz,0x0008,0x0008,11}, /* XGI_NoScalingData */
+ {Panel1024x768x75,0x0019,0x0001,12}, /* XGI_ExtLCD1024x768x75Data */
+ {Panel1024x768x75,0x0019,0x0000,13}, /* XGI_StLCD1024x768x75Data */
+ {Panel1024x768x75,0x0018,0x0010,14}, /* XGI_CetLCD1024x768x75Data */
+ {Panel1280x1024x75,0x0019,0x0001,15}, /* XGI_ExtLCD1280x1024x75Data */
+ {Panel1280x1024x75,0x0019,0x0000,16}, /* XGI_StLCD1280x1024x75Data */
+ {Panel1280x1024x75,0x0018,0x0010,17}, /* XGI_CetLCD1280x1024x75Data */
+ {PanelRef75Hz,0x0008,0x0008,18}, /* XGI_NoScalingDatax75 */
+ {0xFF,0x0000,0x0000,0} /* End of table */
+};
+
+XGI330_LCDDataTablStruct XGI_LCDDesDataTable[]=
+{
+ {Panel1024x768,0x0019,0x0001,0}, /* XGI_ExtLCDDes1024x768Data */
+ {Panel1024x768,0x0019,0x0000,1}, /* XGI_StLCDDes1024x768Data */
+ {Panel1024x768,0x0018,0x0010,2}, /* XGI_CetLCDDes1024x768Data */
+ {Panel1280x1024,0x0019,0x0001,3}, /* XGI_ExtLCDDes1280x1024Data */
+ {Panel1280x1024,0x0019,0x0000,4}, /* XGI_StLCDDes1280x1024Data */
+ {Panel1280x1024,0x0018,0x0010,5}, /* XGI_CetLCDDes1280x1024Data */
+ {Panel1400x1050,0x0019,0x0001,6}, /* XGI_ExtLCDDes1400x1050Data */
+ {Panel1400x1050,0x0019,0x0000,7}, /* XGI_StLCDDes1400x1050Data */
+ {Panel1400x1050,0x0418,0x0010,8}, /* XGI_CetLCDDes1400x1050Data */
+ {Panel1400x1050,0x0418,0x0410,9}, /* XGI_CetLCDDes1400x1050Data2 */
+ {Panel1600x1200,0x0019,0x0001,10}, /* XGI_ExtLCDDes1600x1200Data */
+ {Panel1600x1200,0x0019,0x0000,11}, /* XGI_StLCDDes1600x1200Data */
+ {PanelRef60Hz,0x0008,0x0008,12}, /* XGI_NoScalingDesData */
+ {Panel1024x768x75,0x0019,0x0001,13}, /* XGI_ExtLCDDes1024x768x75Data */
+ {Panel1024x768x75,0x0019,0x0000,14}, /* XGI_StLCDDes1024x768x75Data */
+ {Panel1024x768x75,0x0018,0x0010,15}, /* XGI_CetLCDDes1024x768x75Data */
+ {Panel1280x1024x75,0x0019,0x0001,16}, /* XGI_ExtLCDDes1280x1024x75Data */
+ {Panel1280x1024x75,0x0019,0x0000,17}, /* XGI_StLCDDes1280x1024x75Data */
+ {Panel1280x1024x75,0x0018,0x0010,18}, /* XGI_CetLCDDes1280x1024x75Data */
+ {PanelRef75Hz,0x0008,0x0008,19}, /* XGI_NoScalingDesDatax75 */
+ {0xFF,0x0000,0x0000,0}
+};
+
+XGI330_LCDDataTablStruct XGI_EPLLCDCRT1Ptr_H[]=
+{
+ {Panel1024x768,0x0018,0x0000,0}, /* XGI_LVDSCRT11024x768_1_H */
+ {Panel1024x768,0x0018,0x0010,1}, /* XGI_LVDSCRT11024x768_2_H */
+ {Panel1280x1024,0x0018,0x0000,2}, /* XGI_LVDSCRT11280x1024_1_H */
+ {Panel1280x1024,0x0018,0x0010,3}, /* XGI_LVDSCRT11280x1024_2_H */
+ {Panel1400x1050,0x0018,0x0000,4}, /* XGI_LVDSCRT11400x1050_1_H */
+ {Panel1400x1050,0x0018,0x0010,5}, /* XGI_LVDSCRT11400x1050_2_H */
+ {Panel1600x1200,0x0018,0x0000,6}, /* XGI_LVDSCRT11600x1200_1_H */
+ {Panel1024x768x75,0x0018,0x0000,7}, /* XGI_LVDSCRT11024x768_1_Hx75 */
+ {Panel1024x768x75,0x0018,0x0010,8}, /* XGI_LVDSCRT11024x768_2_Hx75 */
+ {Panel1280x1024x75,0x0018,0x0000,9}, /* XGI_LVDSCRT11280x1024_1_Hx75 */
+ {Panel1280x1024x75,0x0018,0x0010,10}, /* XGI_LVDSCRT11280x1024_2_Hx75 */
+ {0xFF,0x0000,0x0000,0}
+};
+
+XGI330_LCDDataTablStruct XGI_EPLLCDCRT1Ptr_V[]=
+{
+ {Panel1024x768,0x0018,0x0000,0}, /* XGI_LVDSCRT11024x768_1_V */
+ {Panel1024x768,0x0018,0x0010,1}, /* XGI_LVDSCRT11024x768_2_V */
+ {Panel1280x1024,0x0018,0x0000,2}, /* XGI_LVDSCRT11280x1024_1_V */
+ {Panel1280x1024,0x0018,0x0010,3}, /* XGI_LVDSCRT11280x1024_2_V */
+ {Panel1400x1050,0x0018,0x0000,4}, /* XGI_LVDSCRT11400x1050_1_V */
+ {Panel1400x1050,0x0018,0x0010,5}, /* XGI_LVDSCRT11400x1050_2_V */
+ {Panel1600x1200,0x0018,0x0000,6}, /* XGI_LVDSCRT11600x1200_1_V */
+ {Panel1024x768x75,0x0018,0x0000,7}, /* XGI_LVDSCRT11024x768_1_Vx75 */
+ {Panel1024x768x75,0x0018,0x0010,8}, /* XGI_LVDSCRT11024x768_2_Vx75 */
+ {Panel1280x1024x75,0x0018,0x0000,9}, /* XGI_LVDSCRT11280x1024_1_Vx75 */
+ {Panel1280x1024x75,0x0018,0x0010,10}, /* XGI_LVDSCRT11280x1024_2_Vx75 */
+ {0xFF,0x0000,0x0000,0}
+};
+
+XGI330_LCDDataTablStruct XGI_EPLLCDDataPtr[]=
+{
+ {Panel1024x768,0x0018,0x0000,0}, /* XGI_LVDS1024x768Data_1 */
+ {Panel1024x768,0x0018,0x0010,1}, /* XGI_LVDS1024x768Data_2 */
+ {Panel1280x1024,0x0018,0x0000,2}, /* XGI_LVDS1280x1024Data_1 */
+ {Panel1280x1024,0x0018,0x0010,3}, /* XGI_LVDS1280x1024Data_2 */
+ {Panel1400x1050,0x0018,0x0000,4}, /* XGI_LVDS1400x1050Data_1 */
+ {Panel1400x1050,0x0018,0x0010,5}, /* XGI_LVDS1400x1050Data_2 */
+ {Panel1600x1200,0x0018,0x0000,6}, /* XGI_LVDS1600x1200Data_1 */
+ {PanelRef60Hz,0x0008,0x0008,7}, /* XGI_LVDSNoScalingData */
+ {Panel1024x768x75,0x0018,0x0000,8}, /* XGI_LVDS1024x768Data_1x75 */
+ {Panel1024x768x75,0x0018,0x0010,9}, /* XGI_LVDS1024x768Data_2x75 */
+ {Panel1280x1024x75,0x0018,0x0000,10}, /* XGI_LVDS1280x1024Data_1x75 */
+ {Panel1280x1024x75,0x0018,0x0010,11}, /* XGI_LVDS1280x1024Data_2x75 */
+ {PanelRef75Hz,0x0008,0x0008,12}, /* XGI_LVDSNoScalingDatax75 */
+ {0xFF,0x0000,0x0000,0}
+};
+
+XGI330_LCDDataTablStruct XGI_EPLLCDDesDataPtr[]=
+{
+ {Panel1024x768,0x0018,0x0000,0}, /* XGI_LVDS1024x768Des_1 */
+ {Panel1024x768,0x0618,0x0410,1}, /* XGI_LVDS1024x768Des_3 */
+ {Panel1024x768,0x0018,0x0010,2}, /* XGI_LVDS1024x768Des_2 */
+ {Panel1280x1024,0x0018,0x0000,3}, /* XGI_LVDS1280x1024Des_1 */
+ {Panel1280x1024,0x0018,0x0010,4}, /* XGI_LVDS1280x1024Des_2 */
+ {Panel1400x1050,0x0018,0x0000,5}, /* XGI_LVDS1400x1050Des_1 */
+ {Panel1400x1050,0x0018,0x0010,6}, /* XGI_LVDS1400x1050Des_2 */
+ {Panel1600x1200,0x0018,0x0000,7}, /* XGI_LVDS1600x1200Des_1 */
+ {PanelRef60Hz,0x0008,0x0008,8}, /* XGI_LVDSNoScalingDesData */
+ {Panel1024x768x75,0x0018,0x0000,9}, /* XGI_LVDS1024x768Des_1x75 */
+ {Panel1024x768x75,0x0618,0x0410,10}, /* XGI_LVDS1024x768Des_3x75 */
+ {Panel1024x768x75,0x0018,0x0010,11}, /* XGI_LVDS1024x768Des_2x75 */
+ {Panel1280x1024x75,0x0018,0x0000,12}, /* XGI_LVDS1280x1024Des_1x75 */
+ {Panel1280x1024x75,0x0018,0x0010,13}, /* XGI_LVDS1280x1024Des_2x75 */
+ {PanelRef75Hz,0x0008,0x0008,14}, /* XGI_LVDSNoScalingDesDatax75 */
+ {0xFF,0x0000,0x0000,0}
+};
+
+XGI330_LCDDataTablStruct XGI_EPLCHLCDRegPtr[]=
+{
+ {Panel1024x768,0x0000,0x0000,0}, /* XGI_CH7017LV1024x768 */
+ {Panel1400x1050,0x0000,0x0000,1}, /* XGI_CH7017LV1400x1050 */
+ {0xFF,0x0000,0x0000,0}
+};
+
+XGI330_TVDataTablStruct XGI_TVDataTable[]=
+{
+ {0x09E1,0x0001,0}, /* XGI_ExtPALData */
+ {0x09E1,0x0000,1}, /* XGI_ExtNTSCData */
+ {0x09E1,0x0801,2}, /* XGI_StPALData */
+ {0x09E1,0x0800,3}, /* XGI_StNTSCData */
+ {0x49E0,0x0100,4}, /* XGI_ExtHiTVData */
+ {0x49E0,0x4100,5}, /* XGI_St2HiTVData */
+ {0x49E0,0x4900,13}, /* XGI_St1HiTVData */
+ {0x09E0,0x0020,6}, /* XGI_ExtYPbPr525iData */
+ {0x09E0,0x0040,7}, /* XGI_ExtYPbPr525pData */
+ {0x09E0,0x0080,8}, /* XGI_ExtYPbPr750pData */
+ {0x09E0,0x0820,9}, /* XGI_StYPbPr525iData */
+ {0x09E0,0x0840,10}, /* XGI_StYPbPr525pData */
+ {0x09E0,0x0880,11}, /* XGI_StYPbPr750pData */
+ {0xffff,0x0000,12} /* END */
+};
+
+USHORT TVLenList[]=
+{
+ LVDSCRT1Len_H,
+ LVDSCRT1Len_V,
+ LVDSDataLen,
+ 0,
+ TVDataLen,
+ 0,
+ 0,
+ CHTVRegLen
+} ;
+
+/* Chrontel 7017 TV CRT1 Timing List */
+XGI330_TVDataTablStruct XGI_EPLCHTVCRT1Ptr[]=
+{
+ {0x0011,0x0000,0}, /* XGI_CHTVCRT1UNTSC */
+ {0x0011,0x0010,1}, /* XGI_CHTVCRT1ONTSC */
+ {0x0011,0x0001,2}, /* XGI_CHTVCRT1UPAL */
+ {0x0011,0x0011,3}, /* XGI_CHTVCRT1OPAL */
+ {0xFFFF,0x0000,4}
+};
+
+/* ;;Chrontel 7017 TV Timing List */
+XGI330_TVDataTablStruct XGI_EPLCHTVDataPtr[]=
+{
+ {0x0011,0x0000,0}, /* XGI_CHTVUNTSCData */
+ {0x0011,0x0010,1}, /* XGI_CHTVONTSCData */
+ {0x0011,0x0001,2}, /* XGI_CHTVUPALData */
+ {0x0011,0x0011,3}, /* XGI_CHTVOPALData */
+ {0xFFFF,0x0000,4}
+};
+
+/* ;;Chrontel 7017 TV Reg. List */
+XGI330_TVDataTablStruct XGI_EPLCHTVRegPtr[]=
+{
+ {0x0011,0x0000,0}, /* XGI_CHTVRegUNTSC */
+ {0x0011,0x0010,1}, /* XGI_CHTVRegONTSC */
+ {0x0011,0x0001,2}, /* XGI_CHTVRegUPAL */
+ {0x0011,0x0011,3}, /* XGI_CHTVRegOPAL */
+ {0xFFFF,0x0000,4}
+};
+
+USHORT LCDLenList[]=
+{
+ LVDSCRT1Len_H,
+ LVDSCRT1Len_V,
+ LVDSDataLen,
+ LCDDesDataLen,
+ LCDDataLen,
+ LCDDesDataLen,
+ 0,
+ LCDDesDataLen,
+ LCDDesDataLen,
+ 0
+} ;
+
+XGI330_LCDCapStruct XGI660_LCDDLCapList[]= /* 660, Dual link */
+{
+/* LCDCap1024x768 */
+ {Panel1024x768, DefaultLCDCap, 0, 0x014, 0x88, 0x06, VCLK65,
+ 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
+/* LCDCap1280x1024 */
+ {Panel1280x1024, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x053, 0x70, 0x03, VCLK108_2,
+ 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCap1400x1050 */
+ {Panel1400x1050, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x053, 0x70, 0x03, VCLK108_2,
+ 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCap1600x1200 */
+ {Panel1600x1200, LCDDualLink+DefaultLCDCap, LCDToFull, 0x053, 0xC0, 0x03, VCLK162,
+ 0x43, 0x22, 0x70, 0x24, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCap1024x768x75 */
+ {Panel1024x768x75, DefaultLCDCap, 0, 0x014, 0x60, 0, VCLK78_75,
+ 0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
+/* LCDCap1280x1024x75 */
+ {Panel1280x1024x75, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x053, 0x90, 0x03, VCLK135_5,
+ 0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCapDefault */
+ {0xFF, DefaultLCDCap, 0, 0x053, 0x88, 0x06, VCLK65,
+ 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}
+};
+
+XGI330_LCDCapStruct XGI_LCDDLCapList[]= /* Dual link only */
+{
+/* LCDCap1024x768 */
+ {Panel1024x768, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65,
+ 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
+/* LCDCap1280x1024 */
+ {Panel1280x1024, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x012, 0x70, 0x03, VCLK108_2,
+ 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCap1400x1050 */
+ {Panel1400x1050, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x012, 0x70, 0x03, VCLK108_2,
+ 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCap1600x1200 */
+ {Panel1600x1200, LCDDualLink+DefaultLCDCap, LCDToFull, 0x012, 0xC0, 0x03, VCLK162,
+ 0x43, 0x22, 0x70, 0x24, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCap1024x768x75 */
+ {Panel1024x768x75, DefaultLCDCap, 0, 0x012, 0x60, 0, VCLK78_75,
+ 0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
+/* LCDCap1280x1024x75 */
+ {Panel1280x1024x75, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x012, 0x90, 0x03, VCLK135_5,
+ 0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCapDefault */
+ {0xFF, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65,
+ 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}
+};
+
+XGI330_LCDCapStruct XGI660_LCDCapList[]=
+{
+/* LCDCap1024x768 */
+ {Panel1024x768, DefaultLCDCap, 0, 0x014, 0x88, 0x06, VCLK65,
+ 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
+/* LCDCap1280x1024 */
+ {Panel1280x1024, DefaultLCDCap, StLCDBToA, 0x053, 0x70, 0x03, VCLK108_2,
+ 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCap1400x1050 */
+ {Panel1400x1050, DefaultLCDCap, StLCDBToA, 0x053, 0x70, 0x03, VCLK108_2,
+ 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCap1600x1200 */
+ {Panel1600x1200, DefaultLCDCap, LCDToFull, 0x053, 0xC0, 0x03, VCLK162,
+ 0x5A, 0x23, 0x5A, 0x23, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCap1024x768x75 */
+ {Panel1024x768x75, DefaultLCDCap, 0, 0x014, 0x60, 0, VCLK78_75,
+ 0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
+/* LCDCap1280x1024x75 */
+ {Panel1280x1024x75,+DefaultLCDCap, StLCDBToA, 0x053, 0x90, 0x03, VCLK135_5,
+ 0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCapDefault */
+ {0xFF, DefaultLCDCap, 0, 0x053, 0x88, 0x06, VCLK65,
+ 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}
+};
+
+XGI330_LCDCapStruct XGI_LCDCapList[]=
+{
+/* LCDCap1024x768 */
+ {Panel1024x768, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65,
+ 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
+/* LCDCap1280x1024 */
+ {Panel1280x1024, DefaultLCDCap, StLCDBToA, 0x012, 0x70, 0x03, VCLK108_2,
+ 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCap1400x1050 */
+ {Panel1400x1050, DefaultLCDCap, StLCDBToA, 0x012, 0x70, 0x03, VCLK108_2,
+ 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCap1600x1200 */
+ {Panel1600x1200, DefaultLCDCap, LCDToFull, 0x012, 0xC0, 0x03, VCLK162,
+ 0x5A, 0x23, 0x5A, 0x23, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCap1024x768x75 */
+ {Panel1024x768x75, DefaultLCDCap, 0, 0x012, 0x60, 0, VCLK78_75,
+ 0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
+/* LCDCap1280x1024x75 */
+ {Panel1280x1024x75, DefaultLCDCap, StLCDBToA, 0x012, 0x90, 0x03, VCLK135_5,
+ 0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
+/* LCDCapDefault */
+ {0xFF, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65,
+ 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
+ 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}
+};
+
+XGI21_LVDSCapStruct XGI21_LCDCapList[]=
+{
+ {DisableLCD24bpp + LCDPolarity,
+ 2160,1250,1600,1200, 64, 1, 192, 3,
+ 0x70,0x24,0x20,0x04,0x0A,0x02,0xC8
+ },
+ {DisableLCD24bpp + LCDPolarity,
+ 1688,1066,1280,1024, 48, 1, 112, 3,
+ 0x70,0x44,0x20,0x04,0x0A,0x02,0xC8
+ },
+ {DisableLCD24bpp + LCDPolarity + (LCDPolarity << 8),
+ 1344, 806,1024, 768, 24, 3, 136, 6,
+ 0x6C,0x65,0x20,0x04,0x0A,0x02,0xC8
+ },
+ {DisableLCD24bpp + LCDPolarity,
+ 1056, 628, 800, 600, 40, 1, 128, 4,
+ 0x42,0xE2,0x20,0x14,0x0A,0x02,0x00
+ },
+ {DisableLCD24bpp + LCDPolarity,
+ 928, 525, 800, 480, 40, 13, 48, 3,
+ 0x52,0xC5,0x20,0x14,0x0A,0x02,0x00
+ },
+ {DisableLCD24bpp + LCDPolarity + (LCDPolarity << 8),
+ 800, 525, 640, 480, 16, 10, 96, 2,
+ 0x1B,0xE1,0x20,0x04,0x0A,0x02,0xC8
+ }
+
+};
+
+XGI_Ext2Struct XGI330_RefIndex[]=
+{
+{Support32Bpp + SupportAllCRT2 + SyncPN, RES320x200, VCLK25_175, 0x00,0x10,0x59, 320, 200},/* 00 */
+{Support32Bpp + SupportAllCRT2 + SyncPN, RES320x200, VCLK25_175, 0x00,0x10,0x00, 320, 400},/* 01 */
+{Support32Bpp + SupportAllCRT2 + SyncNN, RES320x240, VCLK25_175, 0x04,0x20,0x50, 320, 240},/* 02 */
+{Support32Bpp + SupportAllCRT2 + SyncPP, RES400x300, VCLK40, 0x05,0x32,0x51, 400, 300},/* 03 */
+{Support32Bpp + NoSupportTV + SyncNN + SupportTV1024, RES512x384, VCLK65, 0x06,0x43,0x52, 512, 384},/* 04 */
+{Support32Bpp + SupportAllCRT2 + SyncPN, RES640x400, VCLK25_175, 0x00,0x14,0x2f, 640, 400},/* 05 */
+{Support32Bpp + SupportAllCRT2 + SyncNN, RES640x480x60, VCLK25_175, 0x04,0x24,0x2e, 640, 480},/* 06 640x480x60Hz (LCD 640x480x60z) */
+{Support32Bpp + NoSupportHiVisionTV + SyncNN, RES640x480x72, VCLK31_5, 0x04,0x24,0x2e, 640, 480},/* 07 640x480x72Hz (LCD 640x480x70Hz) */
+{Support32Bpp + NoSupportHiVisionTV + SyncNN, RES640x480x75, VCLK31_5, 0x47,0x24,0x2e, 640, 480},/* 08 640x480x75Hz (LCD 640x480x75Hz) */
+{Support32Bpp + SupportRAMDAC2 + SyncNN, RES640x480x85, VCLK36, 0x8A,0x24,0x2e, 640, 480},/* 09 640x480x85Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPN, RES640x480x100, VCLK43_163, 0x00,0x24,0x2e, 640, 480},/* 0a 640x480x100Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPN, RES640x480x120, VCLK52_406, 0x00,0x24,0x2e, 640, 480},/* 0b 640x480x120Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPN, RES640x480x160, VCLK72_852, 0x00,0x24,0x2e, 640, 480},/* 0c 640x480x160Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncNN, RES640x480x200, VCLK86_6, 0x00,0x24,0x2e, 640, 480},/* 0d 640x480x200Hz */
+{Support32Bpp + NoSupportLCD + SyncPP, RES800x600x56, VCLK36, 0x05,0x36,0x6a, 800, 600},/* 0e 800x600x56Hz */
+{Support32Bpp + NoSupportTV + SyncPP, RES800x600x60, VCLK40, 0x05,0x36,0x6a, 800, 600},/* 0f 800x600x60Hz (LCD 800x600x60Hz) */
+{Support32Bpp + NoSupportHiVisionTV + SyncPP, RES800x600x72, VCLK50, 0x48,0x36,0x6a, 800, 600},/* 10 800x600x72Hz (LCD 800x600x70Hz) */
+{Support32Bpp + NoSupportHiVisionTV + SyncPP, RES800x600x75, VCLK49_5, 0x8B,0x36,0x6a, 800, 600},/* 11 800x600x75Hz (LCD 800x600x75Hz) */
+{Support32Bpp + SupportRAMDAC2 + SyncPP, RES800x600x85, VCLK56_25, 0x00,0x36,0x6a, 800, 600},/* 12 800x600x85Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPN, RES800x600x100, VCLK68_179, 0x00,0x36,0x6a, 800, 600},/* 13 800x600x100Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPN, RES800x600x120, VCLK83_95, 0x00,0x36,0x6a, 800, 600},/* 14 800x600x120Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPN, RES800x600x160, VCLK116_406,0x00,0x36,0x6a, 800, 600},/* 15 800x600x160Hz */
+{Support32Bpp + InterlaceMode + SyncPP, RES1024x768x43, VCLK44_9, 0x00,0x47,0x37,1024, 768},/* 16 1024x768x43Hz */
+{Support32Bpp + NoSupportTV + SyncNN + SupportTV1024, RES1024x768x60, VCLK65, 0x06,0x47,0x37,1024, 768},/* 17 1024x768x60Hz (LCD 1024x768x60Hz) */
+{Support32Bpp + NoSupportHiVisionTV + SyncNN, RES1024x768x70, VCLK75, 0x49,0x47,0x37,1024, 768},/* 18 1024x768x70Hz (LCD 1024x768x70Hz) */
+{Support32Bpp + NoSupportHiVisionTV + SyncPP, RES1024x768x75, VCLK78_75, 0x00,0x47,0x37,1024, 768},/* 19 1024x768x75Hz (LCD 1024x768x75Hz) */
+{Support32Bpp + SupportRAMDAC2 + SyncPP, RES1024x768x85, VCLK94_5, 0x8C,0x47,0x37,1024, 768},/* 1a 1024x768x85Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPN, RES1024x768x100, VCLK113_309,0x00,0x47,0x37,1024, 768},/* 1b 1024x768x100Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPN, RES1024x768x120, VCLK139_054,0x00,0x47,0x37,1024, 768},/* 1c 1024x768x120Hz */
+{Support32Bpp + SupportLCD + SyncPP, RES1280x960x60, VCLK108_2, 0x08,0x58,0x7b,1280, 960},/* 1d 1280x960x60Hz */
+{Support32Bpp + InterlaceMode + SyncPP, RES1280x1024x43, VCLK78_75, 0x00,0x58,0x3a,1280,1024},/* 1e 1280x1024x43Hz */
+{Support32Bpp + NoSupportTV + SyncPP, RES1280x1024x60, VCLK108_2, 0x07,0x58,0x3a,1280,1024},/* 1f 1280x1024x60Hz (LCD 1280x1024x60Hz) */
+{Support32Bpp + NoSupportTV + SyncPP, RES1280x1024x75, VCLK135_5, 0x00,0x58,0x3a,1280,1024},/* 20 1280x1024x75Hz (LCD 1280x1024x75Hz) */
+{Support32Bpp + SyncPP, RES1280x1024x85, VCLK157_5, 0x00,0x58,0x3a,1280,1024},/* 21 1280x1024x85Hz */
+{Support32Bpp + SupportLCD + SyncPP + SupportCRT2in301C, RES1600x1200x60, VCLK162, 0x09,0x7A,0x3c,1600,1200},/* 22 1600x1200x60Hz */
+{Support32Bpp + SyncPP + SupportCRT2in301C, RES1600x1200x65, VCLK175, 0x00,0x69,0x3c,1600,1200},/* 23 1600x1200x65Hz */
+{Support32Bpp + SyncPP + SupportCRT2in301C, RES1600x1200x70, VCLK189, 0x00,0x69,0x3c,1600,1200},/* 24 1600x1200x70Hz */
+{Support32Bpp + SyncPP + SupportCRT2in301C, RES1600x1200x75, VCLK202_5, 0x00,0x69,0x3c,1600,1200},/* 25 1600x1200x75Hz */
+{Support32Bpp + SyncPP, RES1600x1200x85, VCLK229_5, 0x00,0x69,0x3c,1600,1200},/* 26 1600x1200x85Hz */
+{Support32Bpp + SyncPP, RES1600x1200x100,VCLK269_655,0x00,0x69,0x3c,1600,1200},/* 27 1600x1200x100Hz */
+{Support32Bpp + SyncPP, RES1600x1200x120,VCLK323_586,0x00,0x69,0x3c,1600,1200},/* 28 1600x1200x120Hz */
+{Support32Bpp + SupportLCD + SyncNP, RES1920x1440x60, VCLK234, 0x00,0x00,0x68,1920,1440},/* 29 1920x1440x60Hz */
+{Support32Bpp + SyncPN, RES1920x1440x65, VCLK254_817,0x00,0x00,0x68,1920,1440},/* 2a 1920x1440x65Hz */
+{Support32Bpp + SyncPN, RES1920x1440x70, VCLK277_015,0x00,0x00,0x68,1920,1440},/* 2b 1920x1440x70Hz */
+{Support32Bpp + SyncPN, RES1920x1440x75, VCLK291_132,0x00,0x00,0x68,1920,1440},/* 2c 1920x1440x75Hz */
+{Support32Bpp + SyncPN, RES1920x1440x85, VCLK330_615,0x00,0x00,0x68,1920,1440},/* 2d 1920x1440x85Hz */
+{Support16Bpp + SyncPN, RES1920x1440x100,VCLK388_631,0x00,0x00,0x68,1920,1440},/* 2e 1920x1440x100Hz */
+{Support32Bpp + SupportLCD + SyncPN, RES2048x1536x60, VCLK266_952,0x00,0x00,0x6c,2048,1536},/* 2f 2048x1536x60Hz */
+{Support32Bpp + SyncPN, RES2048x1536x65, VCLK291_766,0x00,0x00,0x6c,2048,1536},/* 30 2048x1536x65Hz */
+{Support32Bpp + SyncPN, RES2048x1536x70, VCLK315_195,0x00,0x00,0x6c,2048,1536},/* 31 2048x1536x70Hz */
+{Support32Bpp + SyncPN, RES2048x1536x75, VCLK340_477,0x00,0x00,0x6c,2048,1536},/* 32 2048x1536x75Hz */
+{Support16Bpp + SyncPN, RES2048x1536x85, VCLK375_847,0x00,0x00,0x6c,2048,1536},/* 33 2048x1536x85Hz */
+{Support32Bpp + SupportHiVisionTV + SupportRAMDAC2 + SyncPP + SupportYPbPr, RES800x480x60, VCLK39_77, 0x08,0x00,0x70, 800, 480},/* 34 800x480x60Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPP, RES800x480x75, VCLK49_5, 0x08,0x00,0x70, 800, 480},/* 35 800x480x75Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPP, RES800x480x85, VCLK56_25, 0x08,0x00,0x70, 800, 480},/* 36 800x480x85Hz */
+{Support32Bpp + SupportHiVisionTV + SupportRAMDAC2 + SyncPP + SupportYPbPr, RES1024x576x60, VCLK65, 0x09,0x00,0x71,1024, 576},/* 37 1024x576x60Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPP, RES1024x576x75, VCLK78_75, 0x09,0x00,0x71,1024, 576},/* 38 1024x576x75Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPP, RES1024x576x85, VCLK94_5, 0x09,0x00,0x71,1024, 576},/* 39 1024x576x85Hz */
+{Support32Bpp + SupportHiVisionTV + SupportRAMDAC2 + SyncPP + SupportYPbPr, RES1280x720x60, VCLK108_2, 0x0A,0x00,0x75,1280, 720},/* 3a 1280x720x60Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPP, RES1280x720x75, VCLK135_5, 0x0A,0x00,0x75,1280, 720},/* 3b 1280x720x75Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPP, RES1280x720x85, VCLK157_5, 0x0A,0x00,0x75,1280, 720},/* 3c 1280x720x85Hz */
+{Support32Bpp + SupportTV + SyncNN, RES720x480x60, VCLK28_322, 0x06,0x00,0x31, 720, 480},/* 3d 720x480x60Hz */
+{Support32Bpp + SupportTV + SyncPP, RES720x576x56, VCLK36, 0x06,0x00,0x32, 720, 576},/* 3e 720x576x56Hz */
+{Support32Bpp + InterlaceMode + NoSupportLCD + SyncPP, RES856x480x79I, VCLK35_2, 0x00,0x00,0x00, 856, 480},/* 3f 856x480x79I */
+{Support32Bpp + NoSupportLCD + SyncNN, RES856x480x60, VCLK35_2, 0x00,0x00,0x00, 856, 480},/* 40 856x480x60Hz */
+{Support32Bpp + NoSupportHiVisionTV + SyncPP, RES1280x768x60, VCLK79_411, 0x08,0x48,0x23,1280, 768},/* 41 1280x768x60Hz */
+{Support32Bpp + NoSupportHiVisionTV + SyncPP, RES1400x1050x60, VCLK122_61, 0x08,0x69,0x26,1400,1050},/* 42 1400x1050x60Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPP, RES1152x864x60, VCLK80_350, 0x37,0x00,0x20,1152, 864},/* 43 1152x864x60Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPP, RES1152x864x75, VCLK107_385,0x37,0x00,0x20,1152, 864},/* 44 1152x864x75Hz */
+{Support32Bpp + SupportLCD + SupportRAMDAC2 + SyncPP, RES1280x960x75, VCLK125_999,0x3A,0x88,0x7b,1280, 960},/* 45 1280x960x75Hz */
+{Support32Bpp + SupportLCD + SupportRAMDAC2 + SyncPP, RES1280x960x85, VCLK148_5, 0x0A,0x88,0x7b,1280, 960},/* 46 1280x960x85Hz */
+{Support32Bpp + SupportLCD + SupportRAMDAC2 + SyncPP, RES1280x960x120, VCLK217_325,0x3A,0x88,0x7b,1280, 960},/* 47 1280x960x120Hz */
+{Support32Bpp + SupportRAMDAC2 + SyncPN, RES1024x768x160, VCLK139_054,0x30,0x47,0x37,1024, 768},/* 48 1024x768x160Hz */
+};
+
+
+
+XGI330_VCLKDataStruct XGI330_VCLKData[]=
+{
+ { 0x1b,0xe1, 25}, /* 0x0 */
+ { 0x4e,0xe4, 28}, /* 0x1 */
+ { 0x57,0xe4, 31}, /* 0x2 */
+ { 0xc3,0xc8, 36}, /* 0x3 */
+ { 0x42,0xe2, 40}, /* 0x4 */
+ { 0xfe,0xcd, 43}, /* 0x5 */
+ { 0x5d,0xc4, 44}, /* 0x6 */
+ { 0x52,0xe2, 49}, /* 0x7 */
+ { 0x53,0xe2, 50}, /* 0x8 */
+ { 0x74,0x67, 52}, /* 0x9 */
+ { 0x6d,0x66, 56}, /* 0xa */
+ { 0x6c,0xc3, 65}, /* 0xb */
+ { 0x46,0x44, 67}, /* 0xc */
+ { 0xb1,0x46, 68}, /* 0xd */
+ { 0xd3,0x4a, 72}, /* 0xe */
+ { 0x29,0x61, 75}, /* 0xf */
+ { 0x6e,0x46, 76}, /* 0x10 */
+ { 0x2b,0x61, 78}, /* 0x11 */
+ { 0x31,0x42, 79}, /* 0x12 */
+ { 0xab,0x44, 83}, /* 0x13 */
+ { 0x46,0x25, 84}, /* 0x14 */
+ { 0x78,0x29, 86}, /* 0x15 */
+ { 0x62,0x44, 94}, /* 0x16 */
+ { 0x2b,0x41,104}, /* 0x17 */
+ { 0x3a,0x23,105}, /* 0x18 */
+ { 0x70,0x44,108}, /* 0x19 */
+ { 0x3c,0x23,109}, /* 0x1a */
+ { 0x5e,0x43,113}, /* 0x1b */
+ { 0xbc,0x44,116}, /* 0x1c */
+ { 0xe0,0x46,132}, /* 0x1d */
+ { 0x54,0x42,135}, /* 0x1e */
+ { 0xea,0x2a,139}, /* 0x1f */
+ { 0x41,0x22,157}, /* 0x20 */
+ { 0x70,0x24,162}, /* 0x21 */
+ { 0x30,0x21,175}, /* 0x22 */
+ { 0x4e,0x22,189}, /* 0x23 */
+ { 0xde,0x26,194}, /* 0x24 */
+ { 0x62,0x06,202}, /* 0x25 */
+ { 0x3f,0x03,229}, /* 0x26 */
+ { 0xb8,0x06,234}, /* 0x27 */
+ { 0x34,0x02,253}, /* 0x28 */
+ { 0x58,0x04,255}, /* 0x29 */
+ { 0x24,0x01,265}, /* 0x2a */
+ { 0x9b,0x02,267}, /* 0x2b */
+ { 0x70,0x05,270}, /* 0x2c */
+ { 0x25,0x01,272}, /* 0x2d */
+ { 0x9c,0x02,277}, /* 0x2e */
+ { 0x27,0x01,286}, /* 0x2f */
+ { 0x3c,0x02,291}, /* 0x30 */
+ { 0xef,0x0a,292}, /* 0x31 */
+ { 0xf6,0x0a,310}, /* 0x32 */
+ { 0x95,0x01,315}, /* 0x33 */
+ { 0xf0,0x09,324}, /* 0x34 */
+ { 0xfe,0x0a,331}, /* 0x35 */
+ { 0xf3,0x09,332}, /* 0x36 */
+ { 0xea,0x08,340}, /* 0x37 */
+ { 0xe8,0x07,376}, /* 0x38 */
+ { 0xde,0x06,389}, /* 0x39 */
+ { 0x52,0x2a, 54}, /* 0x3a */
+ { 0x52,0x6a, 27}, /* 0x3b */
+ { 0x62,0x24, 70}, /* 0x3c */
+ { 0x62,0x64, 70}, /* 0x3d */
+ { 0xa8,0x4c, 30}, /* 0x3e */
+ { 0x20,0x26, 33}, /* 0x3f */
+ { 0x31,0xc2, 39}, /* 0x40 */
+ { 0x60,0x36, 30}, /* 0x41 */
+ { 0x40,0x4A, 28}, /* 0x42 */
+ { 0x9F,0x46, 44}, /* 0x43 */
+ { 0x97,0x2C, 26}, /* 0x44 */
+ { 0x44,0xE4, 25}, /* 0x45 */
+ { 0x7E,0x32, 47}, /* 0x46 */
+ { 0x08,0x24, 31}, /* 0x47 */
+ { 0x97,0x2c, 26}, /* 0x48 */
+ { 0xCE,0x3c, 39}, /* 0x49 */
+ { 0x52,0x4A, 36}, /* 0x4a */
+ { 0x2C,0x61, 95}, /* 0x4b */
+ { 0x78,0x27,108}, /* 0x4c */
+ { 0x66,0x43,123}, /* 0x4d */
+ { 0x2c,0x61, 80}, /* 0x4e */
+ { 0x3b,0x61,108} /* 0x4f */
+};
+
+XGI_VBVCLKDataStruct XGI330_VBVCLKData[]=
+{
+ { 0x1b,0xe1, 25}, /* 0x0 */
+ { 0x4e,0xe4, 28}, /* 0x1 */
+ { 0x57,0xe4, 31}, /* 0x2 */
+ { 0xc3,0xc8, 36}, /* 0x3 */
+ { 0x42,0x47, 40}, /* 0x4 */
+ { 0xfe,0xcd, 43}, /* 0x5 */
+ { 0x5d,0xc4, 44}, /* 0x6 */
+ { 0x52,0x47, 49}, /* 0x7 */
+ { 0x53,0x47, 50}, /* 0x8 */
+ { 0x74,0x67, 52}, /* 0x9 */
+ { 0x6d,0x66, 56}, /* 0xa */
+ { 0x5a,0x64, 65}, /* 0xb */
+ { 0x46,0x44, 67}, /* 0xc */
+ { 0xb1,0x46, 68}, /* 0xd */
+ { 0xd3,0x4a, 72}, /* 0xe */
+ { 0x29,0x61, 75}, /* 0xf */
+ { 0x6d,0x46, 75}, /* 0x10 */
+ { 0x41,0x43, 78}, /* 0x11 */
+ { 0x31,0x42, 79}, /* 0x12 */
+ { 0xab,0x44, 83}, /* 0x13 */
+ { 0x46,0x25, 84}, /* 0x14 */
+ { 0x78,0x29, 86}, /* 0x15 */
+ { 0x62,0x44, 94}, /* 0x16 */
+ { 0x2b,0x22,104}, /* 0x17 */
+ { 0x49,0x24,105}, /* 0x18 */
+ { 0xf8,0x2f,108}, /* 0x19 */
+ { 0x3c,0x23,109}, /* 0x1a */
+ { 0x5e,0x43,113}, /* 0x1b */
+ { 0xbc,0x44,116}, /* 0x1c */
+ { 0xe0,0x46,132}, /* 0x1d */
+ { 0xd4,0x28,135}, /* 0x1e */
+ { 0xea,0x2a,139}, /* 0x1f */
+ { 0x41,0x22,157}, /* 0x20 */
+ { 0x70,0x24,162}, /* 0x21 */
+ { 0x30,0x21,175}, /* 0x22 */
+ { 0x4e,0x22,189}, /* 0x23 */
+ { 0xde,0x26,194}, /* 0x24 */
+ { 0x70,0x07,202}, /* 0x25 */
+ { 0x3f,0x03,229}, /* 0x26 */
+ { 0xb8,0x06,234}, /* 0x27 */
+ { 0x34,0x02,253}, /* 0x28 */
+ { 0x58,0x04,255}, /* 0x29 */
+ { 0x24,0x01,265}, /* 0x2a */
+ { 0x9b,0x02,267}, /* 0x2b */
+ { 0x70,0x05,270}, /* 0x2c */
+ { 0x25,0x01,272}, /* 0x2d */
+ { 0x9c,0x02,277}, /* 0x2e */
+ { 0x27,0x01,286}, /* 0x2f */
+ { 0x3c,0x02,291}, /* 0x30 */
+ { 0xef,0x0a,292}, /* 0x31 */
+ { 0xf6,0x0a,310}, /* 0x32 */
+ { 0x95,0x01,315}, /* 0x33 */
+ { 0xf0,0x09,324}, /* 0x34 */
+ { 0xfe,0x0a,331}, /* 0x35 */
+ { 0xf3,0x09,332}, /* 0x36 */
+ { 0xea,0x08,340}, /* 0x37 */
+ { 0xe8,0x07,376}, /* 0x38 */
+ { 0xde,0x06,389}, /* 0x39 */
+ { 0x52,0x2a, 54}, /* 0x3a */
+ { 0x52,0x6a, 27}, /* 0x3b */
+ { 0x62,0x24, 70}, /* 0x3c */
+ { 0x62,0x64, 70}, /* 0x3d */
+ { 0xa8,0x4c, 30}, /* 0x3e */
+ { 0x20,0x26, 33}, /* 0x3f */
+ { 0x31,0xc2, 39}, /* 0x40 */
+ { 0x2e,0x48, 25}, /* 0x41 */
+ { 0x24,0x46, 25}, /* 0x42 */
+ { 0x26,0x64, 28}, /* 0x43 */
+ { 0x37,0x64, 40}, /* 0x44 */
+ { 0xa1,0x42,108}, /* 0x45 */
+ { 0x37,0x61,100}, /* 0x46 */
+ { 0x78,0x27,108}, /* 0x47 */
+ { 0x5e,0x64,68}, /* 0x48 chiawen for fuj1280x768*/
+ { 0x70,0x44,108}, /* 0x49 chiawen for 1400x1050*/
+};
+
+UCHAR XGI330_ScreenOffset[]={ 0x14,0x19,0x20,0x28,0x32,0x40,0x50,0x64,0x78,0x80,0x2d,0x35,0x57,0x48 };
+
+XGI_StResInfoStruct XGI330_StResInfo[]=
+{
+ { 640,400},
+ { 640,350},
+ { 720,400},
+ { 720,350},
+ { 640,480}
+};
+
+XGI_ModeResInfoStruct XGI330_ModeResInfo[]=
+{
+ { 320, 200, 8, 8},
+ { 320, 240, 8, 8},
+ { 320, 400, 8, 8},
+ { 400, 300, 8, 8},
+ { 512, 384, 8, 8},
+ { 640, 400, 8,16},
+ { 640, 480, 8,16},
+ { 800, 600, 8,16},
+ { 1024, 768, 8,16},
+ { 1280,1024, 8,16},
+ { 1600,1200, 8,16},
+ { 1920,1440, 8,16},
+ { 2048,1536, 8,16},
+ { 720, 480, 8,16},
+ { 720, 576, 8,16},
+ { 1280, 960, 8,16},
+ { 800, 480, 8,16},
+ { 1024, 576, 8,16},
+ { 1280, 720, 8,16},
+ { 856, 480, 8,16},
+ { 1280, 768, 8,16},
+ { 1400,1050, 8,16},
+ { 1152, 864, 8,16}
+};
+
+UCHAR XGI330_OutputSelect =0x40;
+UCHAR XGI330_SoftSetting = 0x30;
+UCHAR XGI330_SR07=0x18;
+UCHAR XGI330New_SR15[8][8]={
+{0x0,0x4,0x60,0x60},
+{0xf,0xf,0xf,0xf},
+{0xba,0xba,0xba,0xba},
+{0xa9,0xa9,0xac,0xac},
+{0xa0,0xa0,0xa0,0xa8},
+{0x0,0x0,0x2,0x2},
+{0x30,0x30,0x40,0x40},
+{0x0,0xa5,0xfb,0xf6}
+};
+
+UCHAR XGI330New_CR40[5][8]={
+{0x77,0x77,0x44,0x44},
+{0x77,0x77,0x44,0x44},
+{0x0,0x0,0x0,0x0},
+{0x5b,0x5b,0xab,0xab},
+{0x0,0x0,0xf0,0xf8}
+};
+
+UCHAR XGI330_CR49[]={0xaa,0x88};
+UCHAR XGI330_SR1F=0x0;
+UCHAR XGI330_SR21=0xa3;
+UCHAR XGI330_650_SR21=0xa7;
+UCHAR XGI330_SR22=0xfb;
+UCHAR XGI330_SR23=0xf6;
+UCHAR XGI330_SR24=0xd;
+
+UCHAR XGI660_SR21=0xa3;/* 2003.0312 */
+UCHAR XGI660_SR22=0xf3;/* 2003.0312 */
+
+UCHAR XGI330_LVDS_SR32=0x00; /* ynlai for 650 LVDS */
+UCHAR XGI330_LVDS_SR33=0x00; /* chiawen for 650 LVDS */
+UCHAR XGI330_650_SR31=0x40;
+UCHAR XGI330_650_SR33=0x04;
+UCHAR XGI330_CRT2Data_1_2 = 0x0;
+UCHAR XGI330_CRT2Data_4_D = 0x0;
+UCHAR XGI330_CRT2Data_4_E = 0x0;
+UCHAR XGI330_CRT2Data_4_10 = 0x80;
+USHORT XGI330_RGBSenseData = 0xd1;
+USHORT XGI330_VideoSenseData = 0xb9;
+USHORT XGI330_YCSenseData = 0xb3;
+USHORT XGI330_RGBSenseData2 = 0x0190; /*301b*/
+USHORT XGI330_VideoSenseData2 = 0x0110;
+USHORT XGI330_YCSenseData2 = 0x016B;
+UCHAR XGI330_NTSCPhase[] = {0x21,0xed,0x8a,0x8};
+UCHAR XGI330_PALPhase[] = {0x2a,0x5,0xd3,0x0};
+UCHAR XGI330_NTSCPhase2[] = {0x21,0xF0,0x7B,0xD6};/*301b*/
+UCHAR XGI330_PALPhase2[] = {0x2a,0x09,0x86,0xe9};
+UCHAR XGI330_PALMPhase[] = {0x21,0xE4,0x2E,0x9B}; /*palmn*/
+UCHAR XGI330_PALNPhase[] = {0x21,0xF4,0x3E,0xBA};
+UCHAR XG40_I2CDefinition = 0x00 ;
+UCHAR XG20_CR97 = 0x10 ;
+
+UCHAR XG21_DVOSetting = 0x00 ;
+UCHAR XG21_CR2E = 0x00 ;
+UCHAR XG21_CR2F = 0x00 ;
+UCHAR XG21_CR46 = 0x00 ;
+UCHAR XG21_CR47 = 0x00 ;
+
+UCHAR XG27_CR97 = 0xC1 ;
+UCHAR XG27_SR36 = 0x30 ;
+UCHAR XG27_CR8F = 0x0C ;
+UCHAR XG27_CRD0[] = {0,0,0,0,0,0,0,0x82,0x00,0x66,0x01,0x00} ;
+UCHAR XG27_CRDE[] = {0,0} ;
+UCHAR XG27_SR40 = 0x04 ;
+UCHAR XG27_SR41 = 0x00 ;
+
+UCHAR XGI330_CHTVVCLKUNTSC[]={0x00 };
+
+UCHAR XGI330_CHTVVCLKONTSC[]={0x00 };
+
+UCHAR XGI330_CHTVVCLKUPAL[]={0x00 };
+
+UCHAR XGI330_CHTVVCLKOPAL[]={0x00 };
+
+UCHAR XGI7007_CHTVVCLKUNTSC[]={CH7007TVVCLK30_2,
+ CH7007TVVCLK30_2,
+ CH7007TVVCLK30_2,
+ CH7007TVVCLK30_2,
+ CH7007TVVCLK28_1,
+ CH7007TVVCLK47_8
+ };
+
+UCHAR XGI7007_CHTVVCLKONTSC[]={CH7007TVVCLK26_4,
+ CH7007TVVCLK26_4,
+ CH7007TVVCLK26_4,
+ CH7007TVVCLK26_4,
+ CH7007TVVCLK24_6,
+ CH7007TVVCLK43_6
+ };
+
+UCHAR XGI7007_CHTVVCLKUPAL[]={CH7007TVVCLK31_5,
+ CH7007TVVCLK31_5,
+ CH7007TVVCLK31_5,
+ CH7007TVVCLK31_5,
+ CH7007TVVCLK26_2,
+ CH7007TVVCLK39
+ };
+
+UCHAR XGI7007_CHTVVCLKOPAL[]={CH7007TVVCLK31_5,
+ CH7007TVVCLK31_5,
+ CH7007TVVCLK31_5,
+ CH7007TVVCLK31_5,
+ CH7007TVVCLK26_2,
+ CH7007TVVCLK36
+ };
+
+XGI330_VCLKDataStruct XGI_CH7007VCLKData[]=
+{
+ { 0x60,0x36,30}, /* 0 30.2 MHZ */
+ { 0x40,0x4A,28}, /* 1 28.19 MHZ */
+ { 0x9F,0x46,44}, /* 2 43.6 MHZ */
+ { 0x97,0x2C,26}, /* 3 26.4 MHZ */
+ { 0x44,0xE4,25}, /* 4 24.6 MHZ */
+ { 0x7E,0x32,47}, /* 5 47.832 MHZ */
+ { 0x8A,0x24,31}, /* 6 31.5 MHZ */
+ { 0x97,0x2C,26}, /* 7 26.2 MHZ */
+ { 0xCE,0x3C,39}, /* 8 39 MHZ */
+ { 0x52,0x4A,36}, /* 9 36 MHZ */
+ { 0xFF,0x00,0 } /* End mark */
+};
+
+XGI330_VCLKDataStruct XGI_VCLKData[]=
+{
+ /* SR2B,SR2C,SR2D */
+ { 0x1B,0xE1,25 },/* 00 (25.175MHz) */
+
+ { 0x4E,0xE4,28 },/* 01 (28.322MHz) */
+
+ { 0x57,0xE4,31 },/* 02 (31.500MHz) */
+
+ { 0xC3,0xC8,36 },/* 03 (36.000MHz) */
+
+ { 0x42,0xE2,40 },/* 04 (40.000MHz) */
+
+ { 0xFE,0xCD,43 },/* 05 (43.163MHz) */
+
+ { 0x5D,0xC4,44 },/* 06 (44.900MHz) */
+
+ { 0x52,0xE2,49 },/* 07 (49.500MHz) */
+
+ { 0x53,0xE2,50 },/* 08 (50.000MHz) */
+
+ { 0x74,0x67,52 },/* 09 (52.406MHz) */
+
+ { 0x6D,0x66,56 },/* 0A (56.250MHz) */
+
+ { 0x6C,0xC3,65 },/* 0B (65.000MHz) */
+
+ { 0x46,0x44,67 },/* 0C (67.765MHz) */
+
+ { 0xB1,0x46,68 },/* 0D (68.179MHz) */
+
+ { 0xD3,0x4A,72 },/* 0E (72.852MHz) */
+
+ { 0x29,0x61,75 },/* 0F (75.000MHz) */
+
+ { 0x6E,0x46,76 },/* 10 (75.800MHz) */
+
+ { 0x2B,0x61,78 },/* 11 (78.750MHz) */
+
+ { 0x31,0x42,79 },/* 12 (79.411MHz) */
+
+ { 0xAB,0x44,83 },/* 13 (83.950MHz) */
+
+ { 0x46,0x25,84 },/* 14 (84.800MHz) */
+
+ { 0x78,0x29,86 },/* 15 (86.600MHz) */
+
+ { 0x62,0x44,94 },/* 16 (94.500MHz) */
+
+ { 0x2B,0x41,104 },/* 17 (104.998MHz) */
+
+ { 0x3A,0x23,105 },/* 18 (105.882MHz) */
+
+ { 0x70,0x44,108 },/* 19 (107.862MHz) */
+
+ { 0x3C,0x23,109 },/* 1A (109.175MHz) */
+
+ { 0x5E,0x43,113 },/* 1B (113.309MHz) */
+
+ { 0xBC,0x44,116 },/* 1C (116.406MHz) */
+
+ { 0xE0,0x46,132 },/* 1D (132.258MHz) */
+
+ { 0x54,0x42,135 },/* 1E (135.500MHz) */
+
+ { 0x9C,0x22,139 },/* 1F (139.275MHz) */
+
+ { 0x41,0x22,157 },/* 20 (157.500MHz) */
+
+ { 0x70,0x24,162 },/* 21 (161.793MHz) */
+
+ { 0x30,0x21,175 },/* 22 (175.000MHz) */
+
+ { 0x4E,0x22,189 },/* 23 (188.520MHz) */
+
+ { 0xDE,0x26,194 },/* 24 (194.400MHz) */
+
+ { 0x62,0x06,202 },/* 25 (202.500MHz) */
+
+ { 0x3F,0x03,229 },/* 26 (229.500MHz) */
+
+ { 0xB8,0x06,234 },/* 27 (233.178MHz) */
+
+ { 0x34,0x02,253 },/* 28 (252.699MHz) */
+
+ { 0x58,0x04,255 },/* 29 (254.817MHz) */
+
+ { 0x24,0x01,265 },/* 2A (265.728MHz) */
+
+ { 0x9B,0x02,267 },/* 2B (266.952MHz) */
+
+ { 0x70,0x05,270 },/* 2C (269.65567MHz) */
+
+ { 0x25,0x01,272 },/* 2D (272.04199MHz) */
+
+ { 0x9C,0x02,277 },/* 2E (277.015MHz) */
+
+ { 0x27,0x01,286 },/* 2F (286.359985MHz) */
+
+ { 0xB3,0x04,291 },/* 30 (291.13266MHz) */
+
+ { 0xBC,0x05,292 },/* 31 (291.766MHz) */
+
+ { 0xF6,0x0A,310 },/* 32 (309.789459MHz) */
+
+ { 0x95,0x01,315 },/* 33 (315.195MHz) */
+
+ { 0xF0,0x09,324 },/* 34 (323.586792MHz) */
+
+ { 0xFE,0x0A,331 },/* 35 (330.615631MHz) */
+
+ { 0xF3,0x09,332 },/* 36 (332.177612MHz) */
+
+ { 0x5E,0x03,340 },/* 37 (340.477MHz) */
+
+ { 0xE8,0x07,376 },/* 38 (375.847504MHz) */
+
+ { 0xDE, 0x06,389 },/* 39 (388.631439MHz) */
+
+ { 0x52,0x2A,54 },/* 3A (54.000MHz) */
+
+ { 0x52,0x6A,27 },/* 3B (27.000MHz) */
+
+ { 0x62,0x24,70 },/* 3C (70.874991MHz) */
+
+ { 0x62,0x64,70 },/* 3D (70.1048912MHz) */
+
+ { 0xA8,0x4C,30 },/* 3E (30.1048912MHz) */
+
+ { 0x20,0x26,33 },/* 3F (33.7499957MHz) */
+
+ { 0x31,0xc2,39 },/* 40 (39.77MHz) */
+
+ { 0x11,0x21,30 },/* 41 (30MHz) }// NTSC 1024X768 */
+
+ { 0x2E,0x48,25 },/* 42 (25.175MHz) }// ScaleLCD */
+
+ { 0x24,0x46,25 },/* 43 (25.175MHz) */
+
+ { 0x26,0x64,28 },/* 44 (28.322MHz) */
+
+ { 0x37,0x64,40 },/* 45 (40.000MHz) */
+
+ { 0xA1,0x42,108 },/* 46 (95.000MHz) }// QVGA */
+
+ { 0x37,0x61,100 },/* 47 (100.00MHz) */
+
+ { 0x78,0x27,108 },/* 48 (108.200MHz) */
+
+ { 0xBF,0xC8,35 },/* 49 (35.2MHz) */
+
+ { 0x66,0x43,123 },/* 4A (122.61Mhz) */
+
+ { 0x2C,0x61,80 },/* 4B (80.350Mhz) */
+
+ { 0x3B,0x61,108 },/* 4C (107.385Mhz) */
+
+
+/* { 0x60,0x36,30 },// 4D (30.200MHz) }// No use
+
+ { 0x60,0x36,30 },// 4E (30.200MHz) }// No use
+
+ { 0x60,0x36,30 },// 4F (30.200MHz) }// No use
+
+ { 0x60,0x36,30 },// 50 (30.200MHz) }// CHTV
+
+ { 0x40,0x4A,28 },// 51 (28.190MHz)
+
+ { 0x9F,0x46,44 },// 52 (43.600MHz)
+
+ { 0x97,0x2C,26 },// 53 (26.400MHz)
+
+ { 0x44,0xE4,25 },// 54 (24.600MHz)
+
+ { 0x7E,0x32,47 },// 55 (47.832MHz)
+
+ { 0x8A,0x24,31 },// 56 (31.500MHz)
+
+ { 0x97,0x2C,26 },// 57 (26.200MHz)
+
+ { 0xCE,0x3C,39 },// 58 (39.000MHz)
+
+ { 0x52,0x4A,36 },// 59 (36.000MHz)
+
+*/
+ { 0x69,0x61,191 }, /* 4D (190.96MHz ) */
+ { 0x4F,0x22,192 }, /* 4E (192.069MHz) */
+ { 0x28,0x26,322 }, /* 4F (322.273MHz) */
+ { 0x5C,0x6B,27 }, /* 50 (27.74HMz) */
+ { 0x57,0x24,126 }, /* 51 (125.999MHz) */
+ { 0x5C,0x42,148 }, /* 52 (148.5MHz) */
+ { 0x42,0x61,120 }, /* 53 (120.839MHz) */
+ { 0x62,0x61,178 }, /* 54 (178.992MHz) */
+ { 0x59,0x22,217 }, /* 55 (217.325MHz) */
+ { 0x29,0x01,300 }, /* 56 (299.505Mhz) */
+ { 0x52,0x63,74 }, /* 57 (74.25MHz) */
+
+
+ { 0xFF,0x00,0 }/* End mark */
+ } ;
+
+XGI330_VCLKDataStruct XGI_VBVCLKData[]=
+{
+ { 0x1B,0xE1,25 },/* 00 (25.175MHz) */
+
+ { 0x4E,0xE4,28 },/* 01 (28.322MHz) */
+
+ { 0x57,0xE4,31 },/* 02 (31.500MHz) */
+
+ { 0xC3,0xC8,36 },/* 03 (36.000MHz) */
+
+ { 0x42,0x47,40 },/* 04 (40.000MHz) */
+
+ { 0xFE,0xCD,43 },/* 05 (43.163MHz) */
+
+ { 0x5D,0xC4,44 },/* 06 (44.900MHz) */
+
+ { 0x52,0x47,49 },/* 07 (49.500MHz) */
+
+ { 0x53,0x47,50 },/* 08 (50.000MHz) */
+
+ { 0x74,0x67,52 },/* 09 (52.406MHz) */
+
+ { 0x6D,0x66,56 },/* 0A (56.250MHz) */
+
+ { 0x35,0x62,65 },/* 0B (65.000MHz) */
+
+ { 0x46,0x44,67 },/* 0C (67.765MHz) */
+
+ { 0xB1,0x46,68 },/* 0D (68.179MHz) */
+
+ { 0xD3,0x4A,72 },/* 0E (72.852MHz) */
+
+ { 0x29,0x61,75 },/* 0F (75.000MHz) */
+
+ { 0x6D,0x46,75 },/* 10 (75.800MHz) */
+
+ { 0x41,0x43,78 },/* 11 (78.750MHz) */
+
+ { 0x31,0x42,79 },/* 12 (79.411MHz) */
+
+ { 0xAB,0x44,83 },/* 13 (83.950MHz) */
+
+ { 0x46,0x25,84 },/* 14 (84.800MHz) */
+
+ { 0x78,0x29,86 },/* 15 (86.600MHz) */
+
+ { 0x62,0x44,94 },/* 16 (94.500MHz) */
+
+ { 0x2B,0x22,104 },/* 17 (104.998MHz) */
+
+ { 0x49,0x24,105 },/* 18 (105.882MHz) */
+
+ { 0xF8,0x2F,108 },/* 19 (108.279MHz) */
+
+ { 0x3C,0x23,109 },/* 1A (109.175MHz) */
+
+ { 0x5E,0x43,113 },/* 1B (113.309MHz) */
+
+ { 0xBC,0x44,116 },/* 1C (116.406MHz) */
+
+ { 0xE0,0x46,132 },/* 1D (132.258MHz) */
+
+ { 0xD4,0x28,135 },/* 1E (135.220MHz) */
+
+ { 0xEA,0x2A,139 },/* 1F (139.275MHz) */
+
+ { 0x41,0x22,157 },/* 20 (157.500MHz) */
+
+ { 0x70,0x24,162 },/* 21 (161.793MHz) */
+
+ { 0x30,0x21,175 },/* 22 (175.000MHz) */
+
+ { 0x4E,0x22,189 },/* 23 (188.520MHz) */
+
+ { 0xDE,0x26,194 },/* 24 (194.400MHz) */
+
+ { 0x70,0x07,202 },/* 25 (202.500MHz) */
+
+ { 0x3F,0x03,229 },/* 26 (229.500MHz) */
+
+ { 0xB8,0x06,234 },/* 27 (233.178MHz) */
+
+ { 0x34,0x02,253 },/* 28 (252.699997 MHz) */
+
+ { 0x58,0x04,255 },/* 29 (254.817MHz) */
+
+ { 0x24,0x01,265 },/* 2A (265.728MHz) */
+
+ { 0x9B,0x02,267 },/* 2B (266.952MHz) */
+
+ { 0x70,0x05,270 },/* 2C (269.65567 MHz) */
+
+ { 0x25,0x01,272 },/* 2D (272.041992 MHz) */
+
+ { 0x9C,0x02,277 },/* 2E (277.015MHz) */
+
+ { 0x27,0x01,286 },/* 2F (286.359985 MHz) */
+
+ { 0x3C,0x02,291 },/* 30 (291.132660 MHz) */
+
+ { 0xEF,0x0A,292 },/* 31 (291.766MHz) */
+
+ { 0xF6,0x0A,310 },/* 32 (309.789459 MHz) */
+
+ { 0x95,0x01,315 },/* 33 (315.195MHz) */
+
+ { 0xF0,0x09,324 },/* 34 (323.586792 MHz) */
+
+ { 0xFE,0x0A,331 },/* 35 (330.615631 MHz) */
+
+ { 0xF3,0x09,332 },/* 36 (332.177612 MHz) */
+
+ { 0xEA,0x08,340 },/* 37 (340.477MHz) */
+
+ { 0xE8,0x07,376 },/* 38 (375.847504 MHz) */
+
+ { 0xDE,0x06,389 },/* 39 (388.631439 MHz) */
+
+ { 0x52,0x2A,54 },/* 3A (54.000MHz) */
+
+ { 0x52,0x6A,27 },/* 3B (27.000MHz) */
+
+
+ { 0x62,0x24,70 },/* 3C (70.874991MHz) */
+
+
+ { 0x62,0x64,70 },/* 3D (70.1048912MHz) */
+
+ { 0xA8,0x4C,30 },/* 3E (30.1048912MHz) */
+
+ { 0x20,0x26,33 },/* 3F (33.7499957MHz) */
+
+ { 0x31,0xc2,39 },/* 40 (39.77MHz) */
+
+ { 0x11,0x21,30 },/* 41 (30MHz) }// NTSC 1024X768 */
+
+ { 0x2E,0x48,25 },/* 42 (25.175MHz) }// ScaleLCD */
+
+ { 0x24,0x46,25 },/* 43 (25.175MHz) */
+
+ { 0x26,0x64,28 },/* 44 (28.322MHz) */
+
+ { 0x37,0x64,40 },/* 45 (40.000MHz) */
+
+ { 0xA1,0x42,108 },/* 46 (95.000MHz) }// QVGA */
+
+ { 0x37,0x61,100 },/* 47 (100.00MHz) */
+
+ { 0x78,0x27,108 },/* 48 (108.200MHz) */
+
+ { 0xBF,0xC8,35 },/* 49 (35.2MHz) */
+
+ { 0x66,0x43,123 },/* 4A (122.61Mhz) */
+
+ { 0x2C,0x61,80 },/* 4B (80.350Mhz) */
+
+ { 0x3B,0x61,108 },/* 4C (107.385Mhz) */
+
+/*
+ { 0x60,0x36,30 },// 4D (30.200MHz) }// No use
+
+ { 0x60,0x36,30 },// 4E (30.200MHz) }// No use
+
+ { 0x60,0x36,30 },// 4F (30.200MHz) }// No use
+
+ { 0x60,0x36,30 },// 50 (30.200MHz) }// CHTV
+
+ { 0x40,0x4A,28 },// 51 (28.190MHz)
+
+ { 0x9F,0x46,44 },// 52 (43.600MHz)
+
+ { 0x97,0x2C,26 },// 53 (26.400MHz)
+
+ { 0x44,0xE4,25 },// 54 (24.600MHz)
+
+ { 0x7E,0x32,47 },// 55 (47.832MHz)
+
+ { 0x8A,0x24,31 },// 56 (31.500MHz)
+
+ { 0x97,0x2C,26 },// 57 (26.200MHz)
+
+ { 0xCE,0x3C,39 },// 58 (39.000MHz)
+
+ { 0x52,0x4A,36 },// 59 (36.000MHz)
+*/
+ { 0x69,0x61,191 }, /* 4D (190.96MHz ) */
+ { 0x4F,0x22,192 }, /* 4E (192.069MHz) */
+ { 0x28,0x26,322 }, /* 4F (322.273MHz) */
+ { 0x5C,0x6B,27 }, /* 50 (27.74HMz) */
+ { 0x57,0x24,126 }, /* 51 (125.999MHz) */
+ { 0x5C,0x42,148 }, /* 52 (148.5MHz) */
+ { 0x42,0x61,120 }, /* 53 (120.839MHz) */
+ { 0x62,0x61,178 }, /* 54 (178.992MHz) */
+ { 0x59,0x22,217 }, /* 55 (217.325MHz) */
+ { 0x29,0x01,300 }, /* 56 (299.505Mhz) */
+ { 0x52,0x63,74 }, /* 57 (74.25MHz) */
+
+
+ { 0xFF,0x00,0 } /* End mark */
+};
+
+UCHAR XGI660_TVDelayList[]=
+{
+ 0x44, /* ; 0 ExtNTSCDelay */
+ 0x44, /* ; 1 StNTSCDelay */
+ 0x44, /* ; 2 ExtPALDelay */
+ 0x44, /* ; 3 StPALDelay */
+ 0x44, /* ; 4 ExtHiTVDelay(1080i) */
+ 0x44, /* ; 5 StHiTVDelay(1080i) */
+ 0x44, /* ; 6 ExtYPbPrDelay(525i) */
+ 0x44, /* ; 7 StYPbPrDealy(525i) */
+ 0x44, /* ; 8 ExtYPbPrDelay(525p) */
+ 0x44, /* ; 9 StYPbPrDealy(525p) */
+ 0x44, /* ; A ExtYPbPrDelay(750p) */
+ 0x44 /* ; B StYPbPrDealy(750p) */
+};
+
+UCHAR XGI660_TVDelayList2[]=
+{
+ 0x44, /* ; 0 ExtNTSCDelay */
+ 0x44, /* ; 1 StNTSCDelay */
+ 0x44, /* ; 2 ExtPALDelay */
+ 0x44, /* ; 3 StPALDelay */
+ 0x44, /* ; 4 ExtHiTVDelay */
+ 0x44, /* ; 5 StHiTVDelay */
+ 0x44, /* ; 6 ExtYPbPrDelay(525i) */
+ 0x44, /* ; 7 StYPbPrDealy(525i) */
+ 0x44, /* ; 8 ExtYPbPrDelay(525p) */
+ 0x44, /* ; 9 StYPbPrDealy(525p) */
+ 0x44, /* ; A ExtYPbPrDelay(750p) */
+ 0x44 /* ; B StYPbPrDealy(750p) */
+};
+
+UCHAR XGI301TVDelayList[]=
+{
+ 0x22, /* ; 0 ExtNTSCDelay */
+ 0x22, /* ; 1 StNTSCDelay */
+ 0x22, /* ; 2 ExtPALDelay */
+ 0x22, /* ; 3 StPALDelay */
+ 0x88, /* ; 4 ExtHiTVDelay(1080i) */
+ 0xBB, /* ; 5 StHiTVDelay(1080i) */
+ 0x22, /* ; 6 ExtYPbPrDelay(525i) */
+ 0x22, /* ; 7 StYPbPrDealy(525i) */
+ 0x22, /* ; 8 ExtYPbPrDelay(525p) */
+ 0x22, /* ; 9 StYPbPrDealy(525p) */
+ 0x22, /* ; A ExtYPbPrDelay(750p) */
+ 0x22 /* B StYPbPrDealy(750p) */
+};
+
+UCHAR XGI301TVDelayList2[]=
+{
+ 0x22, /* ; 0 ExtNTSCDelay */
+ 0x22, /* ; 1 StNTSCDelay */
+ 0x22, /* ; 2 ExtPALDelay */
+ 0x22, /* ; 3 StPALDelay */
+ 0x22, /* ; 4 ExtHiTVDelay */
+ 0x22, /* ; 5 StHiTVDelay */
+ 0x22, /* ; 6 ExtYPbPrDelay(525i) */
+ 0x22, /* ; 7 StYPbPrDealy(525i) */
+ 0x22, /* ; 8 ExtYPbPrDelay(525p) */
+ 0x22, /* ; 9 StYPbPrDealy(525p) */
+ 0x22, /* ; A ExtYPbPrDelay(750p) */
+ 0x22 /* ; B StYPbPrDealy(750p) */
+};
+
+
+UCHAR TVAntiFlickList[]=
+{/* NTSCAntiFlicker */
+ 0x04, /* ; 0 Adaptive */
+ 0x00, /* ; 1 new anti-flicker ? */
+/* PALAntiFlicker */
+ 0x04, /* ; 0 Adaptive */
+ 0x08, /* ; 1 new anti-flicker ? */
+/* HiTVAntiFlicker */
+ 0x04, /* ; 0 ? */
+ 0x00 /* ; 1 new anti-flicker ? */
+};
+
+
+UCHAR TVEdgeList[]=
+{
+ 0x00, /* ; 0 NTSC No Edge enhance */
+ 0x04, /* ; 1 NTSC Adaptive Edge enhance */
+ 0x00, /* ; 0 PAL No Edge enhance */
+ 0x04, /* ; 1 PAL Adaptive Edge enhance */
+ 0x00, /* ; 0 HiTV */
+ 0x00 /* ; 1 HiTV */
+};
+
+ULONG TVPhaseList[]=
+{ 0x08BAED21, /* ; 0 NTSC phase */
+ 0x00E3052A, /* ; 1 PAL phase */
+ 0x9B2EE421, /* ; 2 PAL-M phase */
+ 0xBA3EF421, /* ; 3 PAL-N phase */
+ 0xA7A28B1E, /* ; 4 NTSC 1024x768 */
+ 0xE00A831E, /* ; 5 PAL-M 1024x768 */
+ 0x00000000, /* ; 6 reserved */
+ 0x00000000, /* ; 7 reserved */
+ 0xD67BF021, /* ; 8 NTSC phase */
+ 0xE986092A, /* ; 9 PAL phase */
+ 0xA4EFE621, /* ; A PAL-M phase */
+ 0x4694F621, /* ; B PAL-N phase */
+ 0x8BDE711C, /* ; C NTSC 1024x768 */
+ 0xE00A831E /* ; D PAL-M 1024x768 */
+};
+
+UCHAR NTSCYFilter1[]=
+{
+ 0x00,0xF4,0x10,0x38 ,/* 0 : 320x text mode */
+ 0x00,0xF4,0x10,0x38 ,/* 1 : 360x text mode */
+ 0xEB,0x04,0x25,0x18 ,/* 2 : 640x text mode */
+ 0xF1,0x04,0x1F,0x18 ,/* 3 : 720x text mode */
+ 0x00,0xF4,0x10,0x38 ,/* 4 : 320x gra. mode */
+ 0xEB,0x04,0x25,0x18 ,/* 5 : 640x gra. mode */
+ 0xEB,0x15,0x25,0xF6 /* 6 : 800x gra. mode */
+};
+
+UCHAR PALYFilter1[]=
+{
+ 0x00,0xF4,0x10,0x38, /* 0 : 320x text mode */
+ 0x00,0xF4,0x10,0x38 ,/* 1 : 360x text mode */
+ 0xF1,0xF7,0x1F,0x32 ,/* 2 : 640x text mode */
+ 0xF3,0x00,0x1D,0x20 ,/* 3 : 720x text mode */
+ 0x00,0xF4,0x10,0x38 ,/* 4 : 320x gra. mode */
+ 0xF1,0xF7,0x1F,0x32 ,/* 5 : 640x gra. mode */
+ 0xFC,0xFB,0x14,0x2A /* 6 : 800x gra. mode */
+};
+
+UCHAR PALMYFilter1[]=
+{
+ 0x00,0xF4,0x10,0x38, /* 0 : 320x text mode */
+ 0x00,0xF4,0x10,0x38, /* 1 : 360x text mode */
+ 0xEB,0x04,0x10,0x18, /* 2 : 640x text mode */
+ 0xF7,0x06,0x19,0x14, /* 3 : 720x text mode */
+ 0x00,0xF4,0x10,0x38, /* 4 : 320x gra. mode */
+ 0xEB,0x04,0x25,0x18, /* 5 : 640x gra. mode */
+ 0xEB,0x15,0x25,0xF6, /* 6 : 800x gra. mode */
+ 0xFF,0xFF,0xFF,0xFF /* End of Table */
+};
+
+UCHAR PALNYFilter1[]=
+{
+ 0x00,0xF4,0x10,0x38, /* 0 : 320x text mode */
+ 0x00,0xF4,0x10,0x38, /* 1 : 360x text mode */
+ 0xEB,0x04,0x10,0x18, /* 2 : 640x text mode */
+ 0xF7,0x06,0x19,0x14, /* 3 : 720x text mode */
+ 0x00,0xF4,0x10,0x38, /* 4 : 320x gra. mode */
+ 0xEB,0x04,0x25,0x18, /* 5 : 640x gra. mode */
+ 0xEB,0x15,0x25,0xF6, /* 6 : 800x gra. mode */
+ 0xFF,0xFF,0xFF,0xFF /* End of Table */
+};
+
+UCHAR NTSCYFilter2[]=
+{
+ 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 0 : 320x text mode */
+ 0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 1 : 360x text mode */
+ 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 2 : 640x text mode */
+ 0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 3 : 720x text mode */
+ 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 4 : 320x gra. mode */
+ 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 5 : 640x gra. mode */
+ 0x01,0x01,0xFC,0xF8,0x08,0x26,0x38, /* 6 : 800x gra. mode */
+ 0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28 /* 7 : 1024xgra. mode */
+};
+
+UCHAR PALYFilter2[]=
+{
+ 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 0 : 320x text mode */
+ 0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 1 : 360x text mode */
+ 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 2 : 640x text mode */
+ 0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 3 : 720x text mode */
+ 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 4 : 320x gra. mode */
+ 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 5 : 640x gra. mode */
+ 0x01,0x01,0xFC,0xF8,0x08,0x26,0x38, /* 6 : 800x gra. mode */
+ 0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28 /* 7 : 1024xgra. mode */
+};
+
+UCHAR PALMYFilter2[]=
+{
+ 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 0 : 320x text mode */
+ 0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 1 : 360x text mode */
+ 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 2 : 640x text mode */
+ 0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 3 : 720x text mode */
+ 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 4 : 320x gra. mode */
+ 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 5 : 640x gra. mode */
+ 0x01,0x01,0xFC,0xF8,0x08,0x26,0x38, /* 6 : 800x gra. mode */
+ 0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28 /* 7 : 1024xgra. mode */
+};
+
+UCHAR PALNYFilter2[]=
+{
+ 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 0 : 320x text mode */
+ 0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 1 : 360x text mode */
+ 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 2 : 640x text mode */
+ 0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 3 : 720x text mode */
+ 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 4 : 320x gra. mode */
+ 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 5 : 640x gra. mode */
+ 0x01,0x01,0xFC,0xF8,0x08,0x26,0x38, /* 6 : 800x gra. mode */
+ 0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28 /* 7 : 1024xgra. mode */
+};
+
+UCHAR XGI_NTSC1024AdjTime[]=
+{
+ 0xa7,0x07,0xf2,0x6e,0x17,0x8b,0x73,0x53,
+ 0x13,0x40,0x34,0xF4,0x63,0xBB,0xCC,0x7A,
+ 0x58,0xe4,0x73,0xd0,0x13
+};
+
+XGI301C_Tap4TimingStruct HiTVTap4Timing[]=
+{
+ {0,{
+ 0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F, /* ; C0-C7 */
+ 0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E, /* ; C8-CF */
+ 0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E, /* ; D0-D7 */
+ 0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C, /* ; D8-DF */
+ 0x7C,0x14,0x14,0x7C,0x7C,0x11,0x17,0x7C, /* ; E0-E7 */
+ 0x7D,0x0E,0x19,0x7C,0x7E,0x0B,0x1B,0x7C, /* ; EA-EF */
+ 0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C, /* ; F0-F7 */
+ 0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E /* ; F8-FF */
+ }
+ }
+};
+
+XGI301C_Tap4TimingStruct EnlargeTap4Timing[]=
+{
+ {0,{
+ 0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F, /* ; C0-C7 */
+ 0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E, /* ; C8-CF */
+ 0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E, /* ; D0-D7 */
+ 0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C, /* ; D8-DF */
+ 0x7C,0x14,0x14,0x7C,0x7C,0x11,0x17,0x7C, /* ; E0-E7 */
+ 0x7D,0x0E,0x19,0x7C,0x7E,0x0B,0x1B,0x7C, /* ; EA-EF */
+ 0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C, /* ; F0-F7 */
+ 0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E /* ; F8-FF */
+ }
+ }
+};
+
+XGI301C_Tap4TimingStruct NoScaleTap4Timing[]=
+{
+ {0,{
+ 0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F, /* ; C0-C7 */
+ 0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E, /* ; C8-CF */
+ 0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E, /* ; D0-D7 */
+ 0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C, /* ; D8-DF */
+ 0x7C,0x14,0x14,0x7C,0x7C,0x11,0x17,0x7C, /* ; E0-E7 */
+ 0x7D,0x0E,0x19,0x7C,0x7E,0x0B,0x1B,0x7C, /* ; EA-EF */
+ 0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C, /* ; F0-F7 */
+ 0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E /* ; F8-FF */
+ }
+ }
+};
+
+XGI301C_Tap4TimingStruct PALTap4Timing[]=
+{
+ {600, {
+ 0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E, /* ; C0-C7 */
+ 0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D, /* ; C8-CF */
+ 0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C, /* ; D0-D7 */
+ 0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D, /* ; D8-DF */
+ 0x7D,0x13,0x13,0x7D,0x7D,0x11,0x14,0x7E, /* ; E0-E7 */
+ 0x7D,0x0F,0x16,0x7E,0x7D,0x0E,0x17,0x7E, /* ; EA-EF */
+ 0x7D,0x0C,0x18,0x7F,0x7D,0x0A,0x18,0x01, /* ; F0-F7 */
+ 0x7D,0x08,0x19,0x02,0x7D,0x06,0x19,0x04 /* ; F8-FF */
+ }
+ },
+ {768, {
+ 0x08,0x12,0x08,0x7E,0x07,0x12,0x09,0x7E, /* ; C0-C7 */
+ 0x06,0x12,0x0A,0x7E,0x05,0x11,0x0B,0x7F, /* ; C8-CF */
+ 0x04,0x11,0x0C,0x7F,0x03,0x11,0x0C,0x00, /* ; D0-D7 */
+ 0x03,0x10,0x0D,0x00,0x02,0x0F,0x0E,0x01, /* ; D8-DF */
+ 0x01,0x0F,0x0F,0x01,0x01,0x0E,0x0F,0x02, /* ; E0-E7 */
+ 0x00,0x0D,0x10,0x03,0x7F,0x0C,0x11,0x04, /* ; EA-EF */
+ 0x7F,0x0C,0x11,0x04,0x7F,0x0B,0x11,0x05, /* ; F0-F7 */
+ 0x7E,0x0A,0x12,0x06,0x7E,0x09,0x12,0x07 /* ; F8-FF */
+ }
+ },
+ {0xFFFF,
+ {
+ 0x04,0x1A,0x04,0x7E,0x02,0x1B,0x05,0x7E, /* ; C0-C7 */
+ 0x01,0x1A,0x07,0x7E,0x00,0x1A,0x09,0x7D, /* ; C8-CF */
+ 0x7F,0x19,0x0B,0x7D,0x7E,0x18,0x0D,0x7D, /* ; D0-D7 */
+ 0x7D,0x17,0x10,0x7C,0x7D,0x15,0x12,0x7C, /* ; D8-DF */
+ 0x7C,0x14,0x14,0x7C,0x7C,0x12,0x15,0x7D, /* ; E0-E7 */
+ 0x7C,0x10,0x17,0x7D,0x7C,0x0D,0x18,0x7F, /* ; EA-EF */
+ 0x7D,0x0B,0x19,0x7F,0x7D,0x09,0x1A,0x00, /* ; F0-F7 */
+ 0x7D,0x07,0x1A,0x02,0x7E,0x05,0x1B,0x02 /* ; F8-FF */
+ }
+ }
+};
+
+XGI301C_Tap4TimingStruct NTSCTap4Timing[]=
+{
+ {480, {
+ 0x04,0x1A,0x04,0x7E,0x03,0x1A,0x06,0x7D, /* ; C0-C7 */
+ 0x01,0x1A,0x08,0x7D,0x00,0x19,0x0A,0x7D, /* ; C8-CF */
+ 0x7F,0x19,0x0C,0x7C,0x7E,0x18,0x0E,0x7C, /* ; D0-D7 */
+ 0x7E,0x17,0x10,0x7B,0x7D,0x15,0x12,0x7C, /* ; D8-DF */
+ 0x7D,0x13,0x13,0x7D,0x7C,0x12,0x15,0x7D, /* ; E0-E7 */
+ 0x7C,0x10,0x17,0x7D,0x7C,0x0E,0x18,0x7E, /* ; EA-EF */
+ 0x7D,0x0C,0x19,0x7E,0x7D,0x0A,0x19,0x00, /* ; F0-F7 */
+ 0x7D,0x08,0x1A,0x01,0x7E,0x06,0x1A,0x02 /* ; F8-FF */
+ }
+ },
+ {600, {
+ 0x07,0x14,0x07,0x7E,0x06,0x14,0x09,0x7D, /* ; C0-C7 */
+ 0x05,0x14,0x0A,0x7D,0x04,0x13,0x0B,0x7E, /* ; C8-CF */
+ 0x03,0x13,0x0C,0x7E,0x02,0x12,0x0D,0x7F, /* ; D0-D7 */
+ 0x01,0x12,0x0E,0x7F,0x01,0x11,0x0F,0x7F, /* ; D8-DF */
+ 0x01,0x10,0x10,0x00,0x7F,0x0F,0x11,0x01, /* ; E0-E7 */
+ 0x7F,0x0E,0x12,0x01,0x7E,0x0D,0x12,0x03, /* ; EA-EF */
+ 0x7E,0x0C,0x13,0x03,0x7E,0x0B,0x13,0x04, /* ; F0-F7 */
+ 0x7E,0x0A,0x14,0x04,0x7D,0x09,0x14,0x06 /* ; F8-FF */
+ }
+ },
+ {0xFFFF,
+ {
+ 0x09,0x0F,0x09,0x7F,0x08,0x0F,0x09,0x00, /* ; C0-C7 */
+ 0x07,0x0F,0x0A,0x00,0x06,0x0F,0x0A,0x01, /* ; C8-CF */
+ 0x06,0x0E,0x0B,0x01,0x05,0x0E,0x0B,0x02, /* ; D0-D7 */
+ 0x04,0x0E,0x0C,0x02,0x04,0x0D,0x0C,0x03, /* ; D8-DF */
+ 0x03,0x0D,0x0D,0x03,0x02,0x0C,0x0D,0x05, /* ; E0-E7 */
+ 0x02,0x0C,0x0E,0x04,0x01,0x0B,0x0E,0x06, /* ; EA-EF */
+ 0x01,0x0B,0x0E,0x06,0x00,0x0A,0x0F,0x07, /* ; F0-F7 */
+ 0x00,0x0A,0x0F,0x07,0x00,0x09,0x0F,0x08 /* ; F8-FF */
+ }
+ }
+};
+
+XGI301C_Tap4TimingStruct YPbPr525pTap4Timing[]=
+{
+ {480, {
+ 0x04,0x1A,0x04,0x7E,0x03,0x1A,0x06,0x7D, /* ; C0-C7 */
+ 0x01,0x1A,0x08,0x7D,0x00,0x19,0x0A,0x7D, /* ; C8-CF */
+ 0x7F,0x19,0x0C,0x7C,0x7E,0x18,0x0E,0x7C, /* ; D0-D7 */
+ 0x7E,0x17,0x10,0x7B,0x7D,0x15,0x12,0x7C, /* ; D8-DF */
+ 0x7D,0x13,0x13,0x7D,0x7C,0x12,0x15,0x7D, /* ; E0-E7 */
+ 0x7C,0x10,0x17,0x7D,0x7C,0x0E,0x18,0x7E, /* ; EA-EF */
+ 0x7D,0x0C,0x19,0x7E,0x7D,0x0A,0x19,0x00, /* ; F0-F7 */
+ 0x7D,0x08,0x1A,0x01,0x7E,0x06,0x1A,0x02 /* ; F8-FF */
+ }
+ },
+ {600, {
+ 0x07,0x14,0x07,0x7E,0x06,0x14,0x09,0x7D, /* ; C0-C7 */
+ 0x05,0x14,0x0A,0x7D,0x04,0x13,0x0B,0x7E, /* ; C8-CF */
+ 0x03,0x13,0x0C,0x7E,0x02,0x12,0x0D,0x7F, /* ; D0-D7 */
+ 0x01,0x12,0x0E,0x7F,0x01,0x11,0x0F,0x7F, /* ; D8-DF */
+ 0x01,0x10,0x10,0x00,0x7F,0x0F,0x11,0x01, /* ; E0-E7 */
+ 0x7F,0x0E,0x12,0x01,0x7E,0x0D,0x12,0x03, /* ; EA-EF */
+ 0x7E,0x0C,0x13,0x03,0x7E,0x0B,0x13,0x04, /* ; F0-F7 */
+ 0x7E,0x0A,0x14,0x04,0x7D,0x09,0x14,0x06 /* ; F8-FF */
+ }
+ },
+ {0xFFFF,
+ {
+ 0x09,0x0F,0x09,0x7F,0x08,0x0F,0x09,0x00, /* ; C0-C7 */
+ 0x07,0x0F,0x0A,0x00,0x06,0x0F,0x0A,0x01, /* ; C8-CF */
+ 0x06,0x0E,0x0B,0x01,0x05,0x0E,0x0B,0x02, /* ; D0-D7 */
+ 0x04,0x0E,0x0C,0x02,0x04,0x0D,0x0C,0x03, /* ; D8-DF */
+ 0x03,0x0D,0x0D,0x03,0x02,0x0C,0x0D,0x05, /* ; E0-E7 */
+ 0x02,0x0C,0x0E,0x04,0x01,0x0B,0x0E,0x06, /* ; EA-EF */
+ 0x01,0x0B,0x0E,0x06,0x00,0x0A,0x0F,0x07, /* ; F0-F7 */
+ 0x00,0x0A,0x0F,0x07,0x00,0x09,0x0F,0x08 /* ; F8-FF */
+ }
+ }
+};
+
+XGI301C_Tap4TimingStruct YPbPr525iTap4Timing[]=
+{
+ {480, {
+ 0x04,0x1A,0x04,0x7E,0x03,0x1A,0x06,0x7D, /* ; C0-C7 */
+ 0x01,0x1A,0x08,0x7D,0x00,0x19,0x0A,0x7D, /* ; C8-CF */
+ 0x7F,0x19,0x0C,0x7C,0x7E,0x18,0x0E,0x7C, /* ; D0-D7 */
+ 0x7E,0x17,0x10,0x7B,0x7D,0x15,0x12,0x7C, /* ; D8-DF */
+ 0x7D,0x13,0x13,0x7D,0x7C,0x12,0x15,0x7D, /* ; E0-E7 */
+ 0x7C,0x10,0x17,0x7D,0x7C,0x0E,0x18,0x7E, /* ; EA-EF */
+ 0x7D,0x0C,0x19,0x7E,0x7D,0x0A,0x19,0x00, /* ; F0-F7 */
+ 0x7D,0x08,0x1A,0x01,0x7E,0x06,0x1A,0x02 /* ; F8-FF */
+ }
+ },
+ {600, {
+ 0x07,0x14,0x07,0x7E,0x06,0x14,0x09,0x7D, /* ; C0-C7 */
+ 0x05,0x14,0x0A,0x7D,0x04,0x13,0x0B,0x7E, /* ; C8-CF */
+ 0x03,0x13,0x0C,0x7E,0x02,0x12,0x0D,0x7F, /* ; D0-D7 */
+ 0x01,0x12,0x0E,0x7F,0x01,0x11,0x0F,0x7F, /* ; D8-DF */
+ 0x01,0x10,0x10,0x00,0x7F,0x0F,0x11,0x01, /* ; E0-E7 */
+ 0x7F,0x0E,0x12,0x01,0x7E,0x0D,0x12,0x03, /* ; EA-EF */
+ 0x7E,0x0C,0x13,0x03,0x7E,0x0B,0x13,0x04, /* ; F0-F7 */
+ 0x7E,0x0A,0x14,0x04,0x7D,0x09,0x14,0x06 /* ; F8-FF */
+ }
+ },
+ {0xFFFF,
+ {
+ 0x09,0x0F,0x09,0x7F,0x08,0x0F,0x09,0x00, /* ; C0-C7 */
+ 0x07,0x0F,0x0A,0x00,0x06,0x0F,0x0A,0x01, /* ; C8-CF */
+ 0x06,0x0E,0x0B,0x01,0x05,0x0E,0x0B,0x02, /* ; D0-D7 */
+ 0x04,0x0E,0x0C,0x02,0x04,0x0D,0x0C,0x03, /* ; D8-DF */
+ 0x03,0x0D,0x0D,0x03,0x02,0x0C,0x0D,0x05, /* ; E0-E7 */
+ 0x02,0x0C,0x0E,0x04,0x01,0x0B,0x0E,0x06, /* ; EA-EF */
+ 0x01,0x0B,0x0E,0x06,0x00,0x0A,0x0F,0x07, /* ; F0-F7 */
+ 0x00,0x0A,0x0F,0x07,0x00,0x09,0x0F,0x08 /* ; F8-FF */
+ }
+ }
+};
+
+XGI301C_Tap4TimingStruct YPbPr750pTap4Timing[]=
+{ {0xFFFF,
+ {
+ 0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E, /* ; C0-C7 */
+ 0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D, /* ; C8-CF */
+ 0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C, /* ; D0-D7 */
+ 0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D, /* ; D8-DF */
+ 0x7D,0x13,0x13,0x7D,0x7D,0x11,0x14,0x7E, /* ; E0-E7 */
+ 0x7D,0x0F,0x16,0x7E,0x7D,0x0E,0x17,0x7E, /* ; EA-EF */
+ 0x7D,0x0C,0x18,0x7F,0x7D,0x0A,0x18,0x01, /* ; F0-F7 */
+ 0x7D,0x08,0x19,0x02,0x7D,0x06,0x19,0x04 /* F8-FF */
+ }
+ }
+};
diff --git a/drivers/staging/xgifb/vb_util.c b/drivers/staging/xgifb/vb_util.c
new file mode 100644
index 0000000..87531b4
--- /dev/null
+++ b/drivers/staging/xgifb/vb_util.c
@@ -0,0 +1,263 @@
+#include "osdef.h"
+#include "vb_def.h"
+#include "vgatypes.h"
+#include "vb_struct.h"
+
+#ifdef LINUX_KERNEL
+#include "XGIfb.h"
+#include <asm/io.h>
+#include <linux/types.h>
+#endif
+
+#ifdef TC
+#include <stdio.h>
+#include <string.h>
+#include <conio.h>
+#include <dos.h>
+#endif
+
+#ifdef WIN2000
+#include <dderror.h>
+#include <devioctl.h>
+#include <miniport.h>
+#include <ntddvdeo.h>
+#include <video.h>
+
+#include "xgiv.h"
+#include "dd_i2c.h"
+#include "tools.h"
+#endif
+
+#ifdef LINUX_XF86
+#include "xf86.h"
+#include "xf86PciInfo.h"
+#include "xgi.h"
+#include "xgi_regs.h"
+#endif
+
+
+
+
+void XGINew_SetReg1( ULONG , USHORT , USHORT ) ;
+void XGINew_SetReg2( ULONG , USHORT , USHORT ) ;
+void XGINew_SetReg3( ULONG , USHORT ) ;
+void XGINew_SetReg4( ULONG , ULONG ) ;
+UCHAR XGINew_GetReg1( ULONG , USHORT) ;
+UCHAR XGINew_GetReg2( ULONG ) ;
+ULONG XGINew_GetReg3( ULONG ) ;
+void XGINew_ClearDAC( PUCHAR ) ;
+void XGINew_SetRegANDOR(ULONG Port,USHORT Index,USHORT DataAND,USHORT DataOR);
+void XGINew_SetRegOR(ULONG Port,USHORT Index,USHORT DataOR);
+void XGINew_SetRegAND(ULONG Port,USHORT Index,USHORT DataAND);
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetReg1 */
+/* Input : */
+/* Output : */
+/* Description : SR CRTC GR */
+/* --------------------------------------------------------------------- */
+void XGINew_SetReg1( ULONG port , USHORT index , USHORT data )
+{
+#ifdef LINUX_XF86
+ OutPortByte( ( PUCHAR )(ULONG)port , index ) ;
+ OutPortByte( ( PUCHAR )(ULONG)port + 1 , data ) ;
+#else
+ OutPortByte( port , index ) ;
+ OutPortByte( port + 1 , data ) ;
+#endif
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetReg2 */
+/* Input : */
+/* Output : */
+/* Description : AR( 3C0 ) */
+/* --------------------------------------------------------------------- */
+/*void XGINew_SetReg2( ULONG port , USHORT index , USHORT data )
+{
+ InPortByte( ( PUCHAR )port + 0x3da - 0x3c0 ) ;
+ OutPortByte( XGINew_P3c0 , index ) ;
+ OutPortByte( XGINew_P3c0 , data ) ;
+ OutPortByte( XGINew_P3c0 , 0x20 ) ;
+}*/
+
+
+/* --------------------------------------------------------------------- */
+/* Function : */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SetReg3( ULONG port , USHORT data )
+{
+ OutPortByte( port , data ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetReg4 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SetReg4( ULONG port , ULONG data )
+{
+ OutPortLong( port , data ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_GetReg1 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+UCHAR XGINew_GetReg1( ULONG port , USHORT index )
+{
+ UCHAR data ;
+
+#ifdef LINUX_XF86
+ OutPortByte( ( PUCHAR )(ULONG)port , index ) ;
+ data = InPortByte( ( PUCHAR )(ULONG)port + 1 ) ;
+#else
+ OutPortByte( port , index ) ;
+ data = InPortByte( port + 1 ) ;
+#endif
+
+ return( data ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_GetReg2 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+UCHAR XGINew_GetReg2( ULONG port )
+{
+ UCHAR data ;
+
+ data = InPortByte( port ) ;
+
+ return( data ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_GetReg3 */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+ULONG XGINew_GetReg3( ULONG port )
+{
+ ULONG data ;
+
+ data = InPortLong( port ) ;
+
+ return( data ) ;
+}
+
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetRegANDOR */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SetRegANDOR( ULONG Port , USHORT Index , USHORT DataAND , USHORT DataOR )
+{
+ USHORT temp ;
+
+ temp = XGINew_GetReg1( Port , Index ) ; /* XGINew_Part1Port index 02 */
+ temp = ( temp & ( DataAND ) ) | DataOR ;
+ XGINew_SetReg1( Port , Index , temp ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetRegAND */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SetRegAND(ULONG Port,USHORT Index,USHORT DataAND)
+{
+ USHORT temp ;
+
+ temp = XGINew_GetReg1( Port , Index ) ; /* XGINew_Part1Port index 02 */
+ temp &= DataAND ;
+ XGINew_SetReg1( Port , Index , temp ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : XGINew_SetRegOR */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void XGINew_SetRegOR( ULONG Port , USHORT Index , USHORT DataOR )
+{
+ USHORT temp ;
+
+ temp = XGINew_GetReg1( Port , Index ) ; /* XGINew_Part1Port index 02 */
+ temp |= DataOR ;
+ XGINew_SetReg1( Port , Index , temp ) ;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : NewDelaySecond */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void NewDelaySeconds( int seconds )
+{
+#ifdef WIN2000
+ int j ;
+#endif
+ int i ;
+
+
+ for( i = 0 ; i < seconds ; i++ )
+ {
+#ifdef TC
+ delay( 1000 ) ;
+#endif
+
+#ifdef WIN2000
+
+ for ( j = 0 ; j < 20000 ; j++ )
+ VideoPortStallExecution( 50 ) ;
+#endif
+
+#ifdef WINCE_HEADER
+#endif
+
+#ifdef LINUX_KERNEL
+#endif
+ }
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Function : Newdebugcode */
+/* Input : */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+void Newdebugcode( UCHAR code )
+{
+// OutPortByte ( 0x80 , code ) ;
+ /* OutPortByte ( 0x300 , code ) ; */
+ /* NewDelaySeconds( 0x3 ) ; */
+}
+
+
+
diff --git a/drivers/staging/xgifb/vb_util.h b/drivers/staging/xgifb/vb_util.h
new file mode 100644
index 0000000..91779d8
--- /dev/null
+++ b/drivers/staging/xgifb/vb_util.h
@@ -0,0 +1,15 @@
+#ifndef _VBUTIL_
+#define _VBUTIL_
+extern void NewDelaySeconds( int );
+extern void Newdebugcode( UCHAR );
+extern void XGINew_SetReg1(ULONG, USHORT, USHORT);
+extern void XGINew_SetReg3(ULONG, USHORT);
+extern UCHAR XGINew_GetReg1(ULONG, USHORT);
+extern UCHAR XGINew_GetReg2(ULONG);
+extern void XGINew_SetReg4(ULONG, ULONG);
+extern ULONG XGINew_GetReg3(ULONG);
+extern void XGINew_SetRegOR(ULONG Port,USHORT Index,USHORT DataOR);
+extern void XGINew_SetRegAND(ULONG Port,USHORT Index,USHORT DataAND);
+extern void XGINew_SetRegANDOR(ULONG Port,USHORT Index,USHORT DataAND,USHORT DataOR);
+#endif
+
diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h
new file mode 100644
index 0000000..295ea86
--- /dev/null
+++ b/drivers/staging/xgifb/vgatypes.h
@@ -0,0 +1,325 @@
+
+#ifndef _VGATYPES_
+#define _VGATYPES_
+
+#include "osdef.h"
+
+#ifdef LINUX_XF86
+#include "xf86Version.h"
+#include "xf86Pci.h"
+#endif
+
+#ifdef LINUX_KERNEL /* We don't want the X driver to depend on kernel source */
+#include <linux/ioctl.h>
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef CHAR
+typedef char CHAR;
+#endif
+
+#ifndef SHORT
+typedef short SHORT;
+#endif
+
+#ifndef LONG
+typedef long LONG;
+#endif
+
+#ifndef UCHAR
+typedef unsigned char UCHAR;
+#endif
+
+#ifndef USHORT
+typedef unsigned short USHORT;
+#endif
+
+#ifndef ULONG
+typedef unsigned long ULONG;
+#endif
+
+#ifndef PUCHAR
+typedef UCHAR *PUCHAR;
+#endif
+
+#ifndef PUSHORT
+typedef USHORT *PUSHORT;
+#endif
+
+#ifndef PLONGU
+typedef ULONG *PULONG;
+#endif
+
+#ifndef VOID
+typedef void VOID;
+#endif
+
+#ifndef PVOID
+typedef void *PVOID;
+#endif
+
+#ifndef BOOLEAN
+typedef UCHAR BOOLEAN;
+#endif
+/*
+#ifndef bool
+typedef UCHAR bool;
+#endif
+*/
+#ifdef LINUX_KERNEL
+typedef unsigned long XGIIOADDRESS;
+#endif
+
+#ifdef LINUX_XF86
+#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,0,0,0)
+typedef unsigned char IOADDRESS;
+typedef unsigned char XGIIOADDRESS;
+#else
+typedef IOADDRESS XGIIOADDRESS;
+#endif
+#endif
+
+#ifndef VBIOS_VER_MAX_LENGTH
+#define VBIOS_VER_MAX_LENGTH 4
+#endif
+
+#ifndef WIN2000
+
+#ifndef LINUX_KERNEL /* For the linux kernel, this is defined in xgifb.h */
+#ifndef XGI_CHIP_TYPE
+typedef enum _XGI_CHIP_TYPE {
+ XGI_VGALegacy = 0,
+#ifdef LINUX_XF86
+ XGI_530,
+ XGI_OLD,
+#endif
+ XGI_300,
+ XGI_630,
+ XGI_640,
+ XGI_315H,
+ XGI_315,
+ XGI_315PRO,
+ XGI_550,
+ XGI_650,
+ XGI_650M,
+ XGI_740,
+ XGI_330,
+ XGI_661,
+ XGI_660,
+ XGI_760,
+ XG40 = 32,
+ XG41,
+ XG42,
+ XG45,
+ XG20 = 48,
+ XG21,
+ XG27,
+ MAX_XGI_CHIP
+} XGI_CHIP_TYPE;
+#endif
+#endif
+
+#ifndef XGI_VB_CHIP_TYPE
+typedef enum _XGI_VB_CHIP_TYPE {
+ VB_CHIP_Legacy = 0,
+ VB_CHIP_301,
+ VB_CHIP_301B,
+ VB_CHIP_301LV,
+ VB_CHIP_302,
+ VB_CHIP_302B,
+ VB_CHIP_302LV,
+ VB_CHIP_301C,
+ VB_CHIP_302ELV,
+ VB_CHIP_UNKNOWN, /* other video bridge or no video bridge */
+ MAX_VB_CHIP
+} XGI_VB_CHIP_TYPE;
+#endif
+
+#ifndef XGI_LCD_TYPE
+typedef enum _XGI_LCD_TYPE {
+ LCD_INVALID = 0,
+ LCD_320x480, /* FSTN, DSTN */
+ LCD_640x480,
+ LCD_640x480_2, /* FSTN, DSTN */
+ LCD_640x480_3, /* FSTN, DSTN */
+ LCD_800x600,
+ LCD_848x480,
+ LCD_1024x600,
+ LCD_1024x768,
+ LCD_1152x768,
+ LCD_1152x864,
+ LCD_1280x720,
+ LCD_1280x768,
+ LCD_1280x800,
+ LCD_1280x960,
+ LCD_1280x1024,
+ LCD_1400x1050,
+ LCD_1600x1200,
+ LCD_1680x1050,
+ LCD_1920x1440,
+ LCD_2048x1536,
+ LCD_CUSTOM,
+ LCD_UNKNOWN
+} XGI_LCD_TYPE;
+#endif
+
+#endif /* not WIN2000 */
+
+#ifndef PXGI_DSReg
+typedef struct _XGI_DSReg
+{
+ UCHAR jIdx;
+ UCHAR jVal;
+} XGI_DSReg, *PXGI_DSReg;
+#endif
+
+#ifndef XGI_HW_DEVICE_INFO
+
+typedef struct _XGI_HW_DEVICE_INFO XGI_HW_DEVICE_INFO, *PXGI_HW_DEVICE_INFO;
+
+typedef BOOLEAN (*PXGI_QUERYSPACE) (PXGI_HW_DEVICE_INFO, ULONG, ULONG, ULONG *);
+
+struct _XGI_HW_DEVICE_INFO
+{
+ ULONG ulExternalChip; /* NO VB or other video bridge*/
+ /* if ujVBChipID = VB_CHIP_UNKNOWN, */
+#ifdef LINUX_XF86
+ PCITAG PciTag; /* PCI Tag */
+#endif
+
+ PUCHAR pjVirtualRomBase; /* ROM image */
+
+ BOOLEAN UseROM; /* Use the ROM image if provided */
+
+ PVOID pDevice;
+
+ PUCHAR pjVideoMemoryAddress;/* base virtual memory address */
+ /* of Linear VGA memory */
+
+ ULONG ulVideoMemorySize; /* size, in bytes, of the memory on the board */
+
+ PUCHAR pjIOAddress; /* base I/O address of VGA ports (0x3B0) */
+
+ PUCHAR pjCustomizedROMImage;
+
+ PUCHAR pj2ndVideoMemoryAddress;
+ ULONG ul2ndVideoMemorySize;
+
+ PUCHAR pj2ndIOAddress;
+/*#ifndef WIN2000
+ XGIIOADDRESS pjIOAddress; // base I/O address of VGA ports (0x3B0)
+#endif */
+ UCHAR jChipType; /* Used to Identify Graphics Chip */
+ /* defined in the data structure type */
+ /* "XGI_CHIP_TYPE" */
+
+ UCHAR jChipRevision; /* Used to Identify Graphics Chip Revision */
+
+ UCHAR ujVBChipID; /* the ID of video bridge */
+ /* defined in the data structure type */
+ /* "XGI_VB_CHIP_TYPE" */
+
+ BOOLEAN bNewScratch;
+
+ ULONG ulCRT2LCDType; /* defined in the data structure type */
+
+ ULONG usExternalChip; /* NO VB or other video bridge (other than */
+ /* video bridge) */
+
+ BOOLEAN bIntegratedMMEnabled;/* supporting integration MM enable */
+
+ BOOLEAN bSkipDramSizing; /* True: Skip video memory sizing. */
+
+ BOOLEAN bSkipSense;
+
+ BOOLEAN bIsPowerSaving; /* True: XGIInit() is invoked by power management,
+ otherwise by 2nd adapter's initialzation */
+
+ PXGI_DSReg pSR; /* restore SR registers in initial function. */
+ /* end data :(idx, val) = (FF, FF). */
+ /* Note : restore SR registers if */
+ /* bSkipDramSizing = TRUE */
+
+ PXGI_DSReg pCR; /* restore CR registers in initial function. */
+ /* end data :(idx, val) = (FF, FF) */
+ /* Note : restore cR registers if */
+ /* bSkipDramSizing = TRUE */
+/*
+#endif
+*/
+
+ PXGI_QUERYSPACE pQueryVGAConfigSpace;
+
+ PXGI_QUERYSPACE pQueryNorthBridgeSpace;
+
+ UCHAR szVBIOSVer[VBIOS_VER_MAX_LENGTH];
+
+};
+#endif
+
+/* Addtional IOCTL for communication xgifb <> X driver */
+/* If changing this, xgifb.h must also be changed (for xgifb) */
+
+#ifdef LINUX_XF86 /* We don't want the X driver to depend on the kernel source */
+
+/* ioctl for identifying and giving some info (esp. memory heap start) */
+#define XGIFB_GET_INFO 0x80046ef8 /* Wow, what a terrible hack... */
+
+/* Structure argument for XGIFB_GET_INFO ioctl */
+typedef struct _XGIFB_INFO xgifb_info, *pxgifb_info;
+
+struct _XGIFB_INFO {
+ CARD32 xgifb_id; /* for identifying xgifb */
+#ifndef XGIFB_ID
+#define XGIFB_ID 0x53495346 /* Identify myself with 'XGIF' */
+#endif
+ CARD32 chip_id; /* PCI ID of detected chip */
+ CARD32 memory; /* video memory in KB which xgifb manages */
+ CARD32 heapstart; /* heap start (= xgifb "mem" argument) in KB */
+ CARD8 fbvidmode; /* current xgifb mode */
+
+ CARD8 xgifb_version;
+ CARD8 xgifb_revision;
+ CARD8 xgifb_patchlevel;
+
+ CARD8 xgifb_caps; /* xgifb's capabilities */
+
+ CARD32 xgifb_tqlen; /* turbo queue length (in KB) */
+
+ CARD32 xgifb_pcibus; /* The card's PCI ID */
+ CARD32 xgifb_pcislot;
+ CARD32 xgifb_pcifunc;
+
+ CARD8 xgifb_lcdpdc;
+
+ CARD8 xgifb_lcda;
+
+ CARD32 xgifb_vbflags;
+ CARD32 xgifb_currentvbflags;
+
+ CARD32 xgifb_scalelcd;
+ CARD32 xgifb_specialtiming;
+
+ CARD8 xgifb_haveemi;
+ CARD8 xgifb_emi30,xgifb_emi31,xgifb_emi32,xgifb_emi33;
+ CARD8 xgifb_haveemilcd;
+
+ CARD8 xgifb_lcdpdca;
+
+ CARD8 reserved[212]; /* for future use */
+};
+#endif
+
+#endif
+
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 0c2f14f..61d7550 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1201,7 +1201,7 @@
if (rcv->urb == NULL) {
dev_dbg(&intf->dev,
"out of memory (read urbs usb_alloc_urb)\n");
- goto alloc_fail7;
+ goto alloc_fail6;
}
rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -1225,7 +1225,7 @@
if (snd->urb == NULL) {
dev_dbg(&intf->dev,
"out of memory (write urbs usb_alloc_urb)");
- goto alloc_fail7;
+ goto alloc_fail8;
}
if (usb_endpoint_xfer_int(epwrite))
@@ -1264,6 +1264,7 @@
i = device_create_file(&intf->dev,
&dev_attr_iCountryCodeRelDate);
if (i < 0) {
+ device_remove_file(&intf->dev, &dev_attr_wCountryCodes);
kfree(acm->country_codes);
goto skip_countries;
}
@@ -1300,6 +1301,7 @@
usb_free_urb(acm->wb[i].urb);
alloc_fail7:
acm_read_buffers_free(acm);
+alloc_fail6:
for (i = 0; i < num_rx_buf; i++)
usb_free_urb(acm->ru[i].urb);
usb_free_urb(acm->ctrlurb);
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index ded550e..a6bd53a 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1272,8 +1272,7 @@
static void choose_wakeup(struct usb_device *udev, pm_message_t msg)
{
- int w, i;
- struct usb_interface *intf;
+ int w;
/* Remote wakeup is needed only when we actually go to sleep.
* For things like FREEZE and QUIESCE, if the device is already
@@ -1285,16 +1284,10 @@
return;
}
- /* If remote wakeup is permitted, see whether any interface drivers
+ /* Enable remote wakeup if it is allowed, even if no interface drivers
* actually want it.
*/
- w = 0;
- if (device_may_wakeup(&udev->dev) && udev->actconfig) {
- for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
- intf = udev->actconfig->interface[i];
- w |= intf->needs_remote_wakeup;
- }
- }
+ w = device_may_wakeup(&udev->dev);
/* If the device is autosuspended with the wrong wakeup setting,
* autoresume now so the setting can be changed.
@@ -1328,6 +1321,7 @@
/* For all other calls, take the device back to full power and
* tell the PM core in case it was autosuspended previously.
+ * Unbind the interfaces that will need rebinding later.
*/
} else {
status = usb_resume_both(udev, msg);
@@ -1336,6 +1330,7 @@
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
udev->last_busy = jiffies;
+ do_unbind_rebind(udev, DO_REBIND);
}
}
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index a73e08f..fd4c36e 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -416,8 +416,11 @@
/* A length of zero means transfer the whole sg list */
len = length;
if (len == 0) {
- for_each_sg(sg, sg, nents, i)
- len += sg->length;
+ struct scatterlist *sg2;
+ int j;
+
+ for_each_sg(sg, sg2, nents, j)
+ len += sg2->length;
}
} else {
/*
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 649c0c5..591ae9f 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -295,6 +295,7 @@
boolean "S3C HS/OtG USB Device controller"
depends on S3C_DEV_USB_HSOTG
select USB_GADGET_S3C_HSOTG_PIO
+ select USB_GADGET_DUALSPEED
help
The Samsung S3C64XX USB2.0 high-speed gadget controller
integrated into the S3C64XX series SoC.
diff --git a/drivers/usb/gadget/f_audio.c b/drivers/usb/gadget/f_audio.c
index 43bf445..b91115f 100644
--- a/drivers/usb/gadget/f_audio.c
+++ b/drivers/usb/gadget/f_audio.c
@@ -101,7 +101,7 @@
static struct usb_audio_control mute_control = {
.list = LIST_HEAD_INIT(mute_control.list),
.name = "Mute Control",
- .type = UAC_MUTE_CONTROL,
+ .type = UAC_FU_MUTE,
/* Todo: add real Mute control code */
.set = generic_set_cmd,
.get = generic_get_cmd,
@@ -110,7 +110,7 @@
static struct usb_audio_control volume_control = {
.list = LIST_HEAD_INIT(volume_control.list),
.name = "Volume Control",
- .type = UAC_VOLUME_CONTROL,
+ .type = UAC_FU_VOLUME,
/* Todo: add real Volume control code */
.set = generic_set_cmd,
.get = generic_get_cmd,
diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/f_eem.c
index 38226e9..95dd466 100644
--- a/drivers/usb/gadget/f_eem.c
+++ b/drivers/usb/gadget/f_eem.c
@@ -469,8 +469,7 @@
crc = get_unaligned_le32(skb->data + len
- ETH_FCS_LEN);
crc2 = ~crc32_le(~0,
- skb->data,
- skb->len - ETH_FCS_LEN);
+ skb->data, len - ETH_FCS_LEN);
} else {
crc = get_unaligned_be32(skb->data + len
- ETH_FCS_LEN);
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 7d05a0b..4ce899c 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -321,8 +321,8 @@
/* Data shared by all the FSG instances. */
struct fsg_common {
struct usb_gadget *gadget;
- struct fsg_dev *fsg;
- struct fsg_dev *prev_fsg;
+ struct fsg_dev *fsg, *new_fsg;
+ wait_queue_head_t fsg_wait;
/* filesem protects: backing files in use */
struct rw_semaphore filesem;
@@ -351,7 +351,6 @@
enum fsg_state state; /* For exception handling */
unsigned int exception_req_tag;
- u8 config, new_config;
enum data_direction data_dir;
u32 data_size;
u32 data_size_from_cmnd;
@@ -595,7 +594,7 @@
u16 w_value = le16_to_cpu(ctrl->wValue);
u16 w_length = le16_to_cpu(ctrl->wLength);
- if (!fsg->common->config)
+ if (!fsg_is_set(fsg->common))
return -EOPNOTSUPP;
switch (ctrl->bRequest) {
@@ -2303,24 +2302,20 @@
return -ENOMEM;
}
-/*
- * Reset interface setting and re-init endpoint state (toggle etc).
- * Call with altsetting < 0 to disable the interface. The only other
- * available altsetting is 0, which enables the interface.
- */
-static int do_set_interface(struct fsg_common *common, int altsetting)
+/* Reset interface setting and re-init endpoint state (toggle etc). */
+static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg)
{
- int rc = 0;
- int i;
- const struct usb_endpoint_descriptor *d;
+ const struct usb_endpoint_descriptor *d;
+ struct fsg_dev *fsg;
+ int i, rc = 0;
if (common->running)
DBG(common, "reset interface\n");
reset:
/* Deallocate the requests */
- if (common->prev_fsg) {
- struct fsg_dev *fsg = common->prev_fsg;
+ if (common->fsg) {
+ fsg = common->fsg;
for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
struct fsg_buffhd *bh = &common->buffhds[i];
@@ -2345,88 +2340,53 @@
fsg->bulk_out_enabled = 0;
}
- common->prev_fsg = 0;
+ common->fsg = NULL;
+ wake_up(&common->fsg_wait);
}
common->running = 0;
- if (altsetting < 0 || rc != 0)
+ if (!new_fsg || rc)
return rc;
- DBG(common, "set interface %d\n", altsetting);
+ common->fsg = new_fsg;
+ fsg = common->fsg;
- if (fsg_is_set(common)) {
- struct fsg_dev *fsg = common->fsg;
- common->prev_fsg = common->fsg;
+ /* Enable the endpoints */
+ d = fsg_ep_desc(common->gadget,
+ &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc);
+ rc = enable_endpoint(common, fsg->bulk_in, d);
+ if (rc)
+ goto reset;
+ fsg->bulk_in_enabled = 1;
- /* Enable the endpoints */
- d = fsg_ep_desc(common->gadget,
- &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc);
- rc = enable_endpoint(common, fsg->bulk_in, d);
+ d = fsg_ep_desc(common->gadget,
+ &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc);
+ rc = enable_endpoint(common, fsg->bulk_out, d);
+ if (rc)
+ goto reset;
+ fsg->bulk_out_enabled = 1;
+ common->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize);
+ clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
+
+ /* Allocate the requests */
+ for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
+ struct fsg_buffhd *bh = &common->buffhds[i];
+
+ rc = alloc_request(common, fsg->bulk_in, &bh->inreq);
if (rc)
goto reset;
- fsg->bulk_in_enabled = 1;
-
- d = fsg_ep_desc(common->gadget,
- &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc);
- rc = enable_endpoint(common, fsg->bulk_out, d);
+ rc = alloc_request(common, fsg->bulk_out, &bh->outreq);
if (rc)
goto reset;
- fsg->bulk_out_enabled = 1;
- common->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize);
- clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
-
- /* Allocate the requests */
- for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
- struct fsg_buffhd *bh = &common->buffhds[i];
-
- rc = alloc_request(common, fsg->bulk_in, &bh->inreq);
- if (rc)
- goto reset;
- rc = alloc_request(common, fsg->bulk_out, &bh->outreq);
- if (rc)
- goto reset;
- bh->inreq->buf = bh->outreq->buf = bh->buf;
- bh->inreq->context = bh->outreq->context = bh;
- bh->inreq->complete = bulk_in_complete;
- bh->outreq->complete = bulk_out_complete;
- }
-
- common->running = 1;
- for (i = 0; i < common->nluns; ++i)
- common->luns[i].unit_attention_data = SS_RESET_OCCURRED;
- return rc;
- } else {
- return -EIO;
- }
-}
-
-
-/*
- * Change our operational configuration. This code must agree with the code
- * that returns config descriptors, and with interface altsetting code.
- *
- * It's also responsible for power management interactions. Some
- * configurations might not work with our current power sources.
- * For now we just assume the gadget is always self-powered.
- */
-static int do_set_config(struct fsg_common *common, u8 new_config)
-{
- int rc = 0;
-
- /* Disable the single interface */
- if (common->config != 0) {
- DBG(common, "reset config\n");
- common->config = 0;
- rc = do_set_interface(common, -1);
+ bh->inreq->buf = bh->outreq->buf = bh->buf;
+ bh->inreq->context = bh->outreq->context = bh;
+ bh->inreq->complete = bulk_in_complete;
+ bh->outreq->complete = bulk_out_complete;
}
- /* Enable the interface */
- if (new_config != 0) {
- common->config = new_config;
- rc = do_set_interface(common, 0);
- if (rc != 0)
- common->config = 0; /* Reset on errors */
- }
+ common->running = 1;
+ for (i = 0; i < common->nluns; ++i)
+ common->luns[i].unit_attention_data = SS_RESET_OCCURRED;
return rc;
}
@@ -2437,9 +2397,7 @@
static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
{
struct fsg_dev *fsg = fsg_from_func(f);
- fsg->common->prev_fsg = fsg->common->fsg;
- fsg->common->fsg = fsg;
- fsg->common->new_config = 1;
+ fsg->common->new_fsg = fsg;
raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
return 0;
}
@@ -2447,9 +2405,7 @@
static void fsg_disable(struct usb_function *f)
{
struct fsg_dev *fsg = fsg_from_func(f);
- fsg->common->prev_fsg = fsg->common->fsg;
- fsg->common->fsg = fsg;
- fsg->common->new_config = 0;
+ fsg->common->new_fsg = NULL;
raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
}
@@ -2459,19 +2415,17 @@
static void handle_exception(struct fsg_common *common)
{
siginfo_t info;
- int sig;
int i;
struct fsg_buffhd *bh;
enum fsg_state old_state;
- u8 new_config;
struct fsg_lun *curlun;
unsigned int exception_req_tag;
- int rc;
/* Clear the existing signals. Anything but SIGUSR1 is converted
* into a high-priority EXIT exception. */
for (;;) {
- sig = dequeue_signal_lock(current, ¤t->blocked, &info);
+ int sig =
+ dequeue_signal_lock(current, ¤t->blocked, &info);
if (!sig)
break;
if (sig != SIGUSR1) {
@@ -2482,7 +2436,7 @@
}
/* Cancel all the pending transfers */
- if (fsg_is_set(common)) {
+ if (likely(common->fsg)) {
for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
bh = &common->buffhds[i];
if (bh->inreq_busy)
@@ -2523,7 +2477,6 @@
common->next_buffhd_to_fill = &common->buffhds[0];
common->next_buffhd_to_drain = &common->buffhds[0];
exception_req_tag = common->exception_req_tag;
- new_config = common->new_config;
old_state = common->state;
if (old_state == FSG_STATE_ABORT_BULK_OUT)
@@ -2573,12 +2526,12 @@
break;
case FSG_STATE_CONFIG_CHANGE:
- rc = do_set_config(common, new_config);
+ do_set_interface(common, common->new_fsg);
break;
case FSG_STATE_EXIT:
case FSG_STATE_TERMINATED:
- do_set_config(common, 0); /* Free resources */
+ do_set_interface(common, NULL); /* Free resources */
spin_lock_irq(&common->lock);
common->state = FSG_STATE_TERMINATED; /* Stop the thread */
spin_unlock_irq(&common->lock);
@@ -2863,6 +2816,7 @@
goto error_release;
}
init_completion(&common->thread_notifier);
+ init_waitqueue_head(&common->fsg_wait);
#undef OR
@@ -2957,9 +2911,17 @@
static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct fsg_dev *fsg = fsg_from_func(f);
+ struct fsg_common *common = fsg->common;
DBG(fsg, "unbind\n");
- fsg_common_put(fsg->common);
+ if (fsg->common->fsg == fsg) {
+ fsg->common->new_fsg = NULL;
+ raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
+ /* FIXME: make interruptible or killable somehow? */
+ wait_event(common->fsg_wait, common->fsg != fsg);
+ }
+
+ fsg_common_put(common);
usb_free_descriptors(fsg->function.descriptors);
usb_free_descriptors(fsg->function.hs_descriptors);
kfree(fsg);
@@ -2970,7 +2932,6 @@
{
struct fsg_dev *fsg = fsg_from_func(f);
struct usb_gadget *gadget = c->cdev->gadget;
- int rc;
int i;
struct usb_ep *ep;
@@ -2996,6 +2957,11 @@
ep->driver_data = fsg->common; /* claim the endpoint */
fsg->bulk_out = ep;
+ /* Copy descriptors */
+ f->descriptors = usb_copy_descriptors(fsg_fs_function);
+ if (unlikely(!f->descriptors))
+ return -ENOMEM;
+
if (gadget_is_dualspeed(gadget)) {
/* Assume endpoint addresses are the same for both speeds */
fsg_hs_bulk_in_desc.bEndpointAddress =
@@ -3003,16 +2969,17 @@
fsg_hs_bulk_out_desc.bEndpointAddress =
fsg_fs_bulk_out_desc.bEndpointAddress;
f->hs_descriptors = usb_copy_descriptors(fsg_hs_function);
- if (unlikely(!f->hs_descriptors))
+ if (unlikely(!f->hs_descriptors)) {
+ usb_free_descriptors(f->descriptors);
return -ENOMEM;
+ }
}
return 0;
autoconf_fail:
ERROR(fsg, "unable to autoconfigure all endpoints\n");
- rc = -ENOTSUPP;
- return rc;
+ return -ENOTSUPP;
}
@@ -3036,11 +3003,6 @@
fsg->function.name = FSG_DRIVER_DESC;
fsg->function.strings = fsg_strings_array;
- fsg->function.descriptors = usb_copy_descriptors(fsg_fs_function);
- if (unlikely(!fsg->function.descriptors)) {
- rc = -ENOMEM;
- goto error_free_fsg;
- }
fsg->function.bind = fsg_bind;
fsg->function.unbind = fsg_unbind;
fsg->function.setup = fsg_setup;
@@ -3056,19 +3018,9 @@
rc = usb_add_function(c, &fsg->function);
if (unlikely(rc))
- goto error_free_all;
-
- fsg_common_get(fsg->common);
- return 0;
-
-error_free_all:
- usb_free_descriptors(fsg->function.descriptors);
- /* fsg_bind() might have copied those; or maybe not? who cares
- * -- free it just in case. */
- usb_free_descriptors(fsg->function.hs_descriptors);
-error_free_fsg:
- kfree(fsg);
-
+ kfree(fsg);
+ else
+ fsg_common_get(fsg->common);
return rc;
}
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
index 2928523..82506ca 100644
--- a/drivers/usb/gadget/fsl_qe_udc.c
+++ b/drivers/usb/gadget/fsl_qe_udc.c
@@ -2400,7 +2400,7 @@
static struct qe_udc __devinit *qe_udc_config(struct of_device *ofdev)
{
struct qe_udc *udc;
- struct device_node *np = ofdev->node;
+ struct device_node *np = ofdev->dev.of_node;
unsigned int tmp_addr = 0;
struct usb_device_para __iomem *usbpram;
unsigned int i;
@@ -2525,7 +2525,7 @@
static int __devinit qe_udc_probe(struct of_device *ofdev,
const struct of_device_id *match)
{
- struct device_node *np = ofdev->node;
+ struct device_node *np = ofdev->dev.of_node;
struct qe_ep *ep;
unsigned int ret = 0;
unsigned int i;
diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c
index 4b0e4a0..d1af253 100644
--- a/drivers/usb/gadget/g_ffs.c
+++ b/drivers/usb/gadget/g_ffs.c
@@ -392,6 +392,17 @@
if (unlikely(ret < 0))
return ret;
+ /* After previous do_configs there may be some invalid
+ * pointers in c->interface array. This happens every time
+ * a user space function with fewer interfaces than a user
+ * space function that was run before the new one is run. The
+ * compasit's set_config() assumes that if there is no more
+ * then MAX_CONFIG_INTERFACES interfaces in a configuration
+ * then there is a NULL pointer after the last interface in
+ * c->interface array. We need to make sure this is true. */
+ if (c->next_interface_id < ARRAY_SIZE(c->interface))
+ c->interface[c->next_interface_id] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/m66592-udc.h
index 8b960de..c3caf1a 100644
--- a/drivers/usb/gadget/m66592-udc.h
+++ b/drivers/usb/gadget/m66592-udc.h
@@ -537,35 +537,35 @@
/*-------------------------------------------------------------------------*/
static inline u16 m66592_read(struct m66592 *m66592, unsigned long offset)
{
- return inw((unsigned long)m66592->reg + offset);
+ return ioread16(m66592->reg + offset);
}
static inline void m66592_read_fifo(struct m66592 *m66592,
unsigned long offset,
void *buf, unsigned long len)
{
- unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
+ void __iomem *fifoaddr = m66592->reg + offset;
if (m66592->pdata->on_chip) {
len = (len + 3) / 4;
- insl(fifoaddr, buf, len);
+ ioread32_rep(fifoaddr, buf, len);
} else {
len = (len + 1) / 2;
- insw(fifoaddr, buf, len);
+ ioread16_rep(fifoaddr, buf, len);
}
}
static inline void m66592_write(struct m66592 *m66592, u16 val,
unsigned long offset)
{
- outw(val, (unsigned long)m66592->reg + offset);
+ iowrite16(val, m66592->reg + offset);
}
static inline void m66592_write_fifo(struct m66592 *m66592,
unsigned long offset,
void *buf, unsigned long len)
{
- unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
+ void __iomem *fifoaddr = m66592->reg + offset;
if (m66592->pdata->on_chip) {
unsigned long count;
@@ -573,25 +573,25 @@
int i;
count = len / 4;
- outsl(fifoaddr, buf, count);
+ iowrite32_rep(fifoaddr, buf, count);
if (len & 0x00000003) {
pb = buf + count * 4;
for (i = 0; i < (len & 0x00000003); i++) {
if (m66592_read(m66592, M66592_CFBCFG)) /* le */
- outb(pb[i], fifoaddr + (3 - i));
+ iowrite8(pb[i], fifoaddr + (3 - i));
else
- outb(pb[i], fifoaddr + i);
+ iowrite8(pb[i], fifoaddr + i);
}
}
} else {
unsigned long odd = len & 0x0001;
len = len / 2;
- outsw(fifoaddr, buf, len);
+ iowrite16_rep(fifoaddr, buf, len);
if (odd) {
unsigned char *p = buf + len*2;
- outb(*p, fifoaddr);
+ iowrite8(*p, fifoaddr);
}
}
}
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index 43abf55..4c3ac5c 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -82,7 +82,7 @@
struct printer_dev {
spinlock_t lock; /* lock this structure */
/* lock buffer lists during read/write calls */
- spinlock_t lock_printer_io;
+ struct mutex lock_printer_io;
struct usb_gadget *gadget;
struct usb_request *req; /* for control responses */
u8 config;
@@ -567,7 +567,7 @@
DBG(dev, "printer_read trying to read %d bytes\n", (int)len);
- spin_lock(&dev->lock_printer_io);
+ mutex_lock(&dev->lock_printer_io);
spin_lock_irqsave(&dev->lock, flags);
/* We will use this flag later to check if a printer reset happened
@@ -601,7 +601,7 @@
* call or not.
*/
if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
return -EAGAIN;
}
@@ -648,7 +648,7 @@
if (dev->reset_printer) {
list_add(¤t_rx_req->list, &dev->rx_reqs);
spin_unlock_irqrestore(&dev->lock, flags);
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
return -EAGAIN;
}
@@ -673,7 +673,7 @@
dev->current_rx_buf = current_rx_buf;
spin_unlock_irqrestore(&dev->lock, flags);
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
DBG(dev, "printer_read returned %d bytes\n", (int)bytes_copied);
@@ -697,7 +697,7 @@
if (len == 0)
return -EINVAL;
- spin_lock(&dev->lock_printer_io);
+ mutex_lock(&dev->lock_printer_io);
spin_lock_irqsave(&dev->lock, flags);
/* Check if a printer reset happens while we have interrupts on */
@@ -713,7 +713,7 @@
* a NON-Blocking call or not.
*/
if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
return -EAGAIN;
}
@@ -752,7 +752,7 @@
if (copy_from_user(req->buf, buf, size)) {
list_add(&req->list, &dev->tx_reqs);
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
return bytes_copied;
}
@@ -766,14 +766,14 @@
if (dev->reset_printer) {
list_add(&req->list, &dev->tx_reqs);
spin_unlock_irqrestore(&dev->lock, flags);
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
return -EAGAIN;
}
if (usb_ep_queue(dev->in_ep, req, GFP_ATOMIC)) {
list_add(&req->list, &dev->tx_reqs);
spin_unlock_irqrestore(&dev->lock, flags);
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
return -EAGAIN;
}
@@ -782,7 +782,7 @@
}
spin_unlock_irqrestore(&dev->lock, flags);
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
DBG(dev, "printer_write sent %d bytes\n", (int)bytes_copied);
@@ -820,11 +820,11 @@
unsigned long flags;
int status = 0;
- spin_lock(&dev->lock_printer_io);
+ mutex_lock(&dev->lock_printer_io);
spin_lock_irqsave(&dev->lock, flags);
setup_rx_reqs(dev);
spin_unlock_irqrestore(&dev->lock, flags);
- spin_unlock(&dev->lock_printer_io);
+ mutex_unlock(&dev->lock_printer_io);
poll_wait(fd, &dev->rx_wait, wait);
poll_wait(fd, &dev->tx_wait, wait);
@@ -1461,7 +1461,7 @@
}
spin_lock_init(&dev->lock);
- spin_lock_init(&dev->lock_printer_io);
+ mutex_init(&dev->lock_printer_io);
INIT_LIST_HEAD(&dev->tx_reqs);
INIT_LIST_HEAD(&dev->tx_reqs_active);
INIT_LIST_HEAD(&dev->rx_reqs);
@@ -1594,7 +1594,7 @@
{
int status;
- spin_lock(&usb_printer_gadget.lock_printer_io);
+ mutex_lock(&usb_printer_gadget.lock_printer_io);
class_destroy(usb_gadget_class);
unregister_chrdev_region(g_printer_devno, 2);
@@ -1602,6 +1602,6 @@
if (status)
ERROR(dev, "usb_gadget_unregister_driver %x\n", status);
- spin_unlock(&usb_printer_gadget.lock_printer_io);
+ mutex_unlock(&usb_printer_gadget.lock_printer_io);
}
module_exit(cleanup);
diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c
index 888d8f1..70a8178 100644
--- a/drivers/usb/gadget/r8a66597-udc.c
+++ b/drivers/usb/gadget/r8a66597-udc.c
@@ -1500,7 +1500,7 @@
struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev);
del_timer_sync(&r8a66597->timer);
- iounmap((void *)r8a66597->reg);
+ iounmap(r8a66597->reg);
free_irq(platform_get_irq(pdev, 0), r8a66597);
r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req);
#ifdef CONFIG_HAVE_CLK
@@ -1578,7 +1578,7 @@
init_timer(&r8a66597->timer);
r8a66597->timer.function = r8a66597_timer;
r8a66597->timer.data = (unsigned long)r8a66597;
- r8a66597->reg = (unsigned long)reg;
+ r8a66597->reg = reg;
#ifdef CONFIG_HAVE_CLK
if (r8a66597->pdata->on_chip) {
diff --git a/drivers/usb/gadget/r8a66597-udc.h b/drivers/usb/gadget/r8a66597-udc.h
index 9a537aa..f763b51 100644
--- a/drivers/usb/gadget/r8a66597-udc.h
+++ b/drivers/usb/gadget/r8a66597-udc.h
@@ -91,7 +91,7 @@
struct r8a66597 {
spinlock_t lock;
- unsigned long reg;
+ void __iomem *reg;
#ifdef CONFIG_HAVE_CLK
struct clk *clk;
@@ -127,7 +127,7 @@
static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset)
{
- return inw(r8a66597->reg + offset);
+ return ioread16(r8a66597->reg + offset);
}
static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
@@ -135,7 +135,7 @@
unsigned char *buf,
int len)
{
- unsigned long fifoaddr = r8a66597->reg + offset;
+ void __iomem *fifoaddr = r8a66597->reg + offset;
unsigned int data;
int i;
@@ -144,7 +144,7 @@
/* aligned buf case */
if (len >= 4 && !((unsigned long)buf & 0x03)) {
- insl(fifoaddr, buf, len / 4);
+ ioread32_rep(fifoaddr, buf, len / 4);
buf += len & ~0x03;
len &= 0x03;
}
@@ -152,7 +152,7 @@
/* unaligned buf case */
for (i = 0; i < len; i++) {
if (!(i & 0x03))
- data = inl(fifoaddr);
+ data = ioread32(fifoaddr);
buf[i] = (data >> ((i & 0x03) * 8)) & 0xff;
}
@@ -161,7 +161,7 @@
/* aligned buf case */
if (len >= 2 && !((unsigned long)buf & 0x01)) {
- insw(fifoaddr, buf, len / 2);
+ ioread16_rep(fifoaddr, buf, len / 2);
buf += len & ~0x01;
len &= 0x01;
}
@@ -169,7 +169,7 @@
/* unaligned buf case */
for (i = 0; i < len; i++) {
if (!(i & 0x01))
- data = inw(fifoaddr);
+ data = ioread16(fifoaddr);
buf[i] = (data >> ((i & 0x01) * 8)) & 0xff;
}
@@ -179,7 +179,7 @@
static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
unsigned long offset)
{
- outw(val, r8a66597->reg + offset);
+ iowrite16(val, r8a66597->reg + offset);
}
static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
@@ -187,21 +187,21 @@
unsigned char *buf,
int len)
{
- unsigned long fifoaddr = r8a66597->reg + offset;
+ void __iomem *fifoaddr = r8a66597->reg + offset;
int adj = 0;
int i;
if (r8a66597->pdata->on_chip) {
/* 32-bit access only if buf is 32-bit aligned */
if (len >= 4 && !((unsigned long)buf & 0x03)) {
- outsl(fifoaddr, buf, len / 4);
+ iowrite32_rep(fifoaddr, buf, len / 4);
buf += len & ~0x03;
len &= 0x03;
}
} else {
/* 16-bit access only if buf is 16-bit aligned */
if (len >= 2 && !((unsigned long)buf & 0x01)) {
- outsw(fifoaddr, buf, len / 2);
+ iowrite16_rep(fifoaddr, buf, len / 2);
buf += len & ~0x01;
len &= 0x01;
}
@@ -216,7 +216,7 @@
}
for (i = 0; i < len; i++)
- outb(buf[i], fifoaddr + adj - (i & adj));
+ iowrite8(buf[i], fifoaddr + adj - (i & adj));
}
static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index 1f73b48..26193ec 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -297,6 +297,12 @@
*/
static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg)
{
+ unsigned int ep;
+ unsigned int addr;
+ unsigned int size;
+ int timeout;
+ u32 val;
+
/* the ryu 2.6.24 release ahs
writel(0x1C0, hsotg->regs + S3C_GRXFSIZ);
writel(S3C_GNPTXFSIZ_NPTxFStAddr(0x200) |
@@ -310,6 +316,51 @@
writel(S3C_GNPTXFSIZ_NPTxFStAddr(2048) |
S3C_GNPTXFSIZ_NPTxFDep(0x1C0),
hsotg->regs + S3C_GNPTXFSIZ);
+
+ /* arange all the rest of the TX FIFOs, as some versions of this
+ * block have overlapping default addresses. This also ensures
+ * that if the settings have been changed, then they are set to
+ * known values. */
+
+ /* start at the end of the GNPTXFSIZ, rounded up */
+ addr = 2048 + 1024;
+ size = 768;
+
+ /* currently we allocate TX FIFOs for all possible endpoints,
+ * and assume that they are all the same size. */
+
+ for (ep = 0; ep <= 15; ep++) {
+ val = addr;
+ val |= size << S3C_DPTXFSIZn_DPTxFSize_SHIFT;
+ addr += size;
+
+ writel(val, hsotg->regs + S3C_DPTXFSIZn(ep));
+ }
+
+ /* according to p428 of the design guide, we need to ensure that
+ * all fifos are flushed before continuing */
+
+ writel(S3C_GRSTCTL_TxFNum(0x10) | S3C_GRSTCTL_TxFFlsh |
+ S3C_GRSTCTL_RxFFlsh, hsotg->regs + S3C_GRSTCTL);
+
+ /* wait until the fifos are both flushed */
+ timeout = 100;
+ while (1) {
+ val = readl(hsotg->regs + S3C_GRSTCTL);
+
+ if ((val & (S3C_GRSTCTL_TxFFlsh | S3C_GRSTCTL_RxFFlsh)) == 0)
+ break;
+
+ if (--timeout == 0) {
+ dev_err(hsotg->dev,
+ "%s: timeout flushing fifos (GRSTCTL=%08x)\n",
+ __func__, val);
+ }
+
+ udelay(1);
+ }
+
+ dev_dbg(hsotg->dev, "FIFOs reset, timeout at %d\n", timeout);
}
/**
@@ -2574,6 +2625,9 @@
writel(S3C_DCTL_CGOUTNak | S3C_DCTL_CGNPInNAK,
hsotg->regs + S3C_DCTL);
+ /* must be at-least 3ms to allow bus to see disconnect */
+ msleep(3);
+
/* remove the soft-disconnect and let's go */
__bic32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon);
@@ -2730,6 +2784,9 @@
writel(0, hsotg->regs + S3C_DAINTMSK);
+ /* Be in disconnected state until gadget is registered */
+ __orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon);
+
if (0) {
/* post global nak until we're ready */
writel(S3C_DCTL_SGNPInNAK | S3C_DCTL_SGOUTNak,
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index d5f4c1d..e724a05 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -1700,9 +1700,13 @@
if (!driver || driver != udc->driver || !driver->unbind)
return -EINVAL;
- dprintk(DEBUG_NORMAL,"usb_gadget_register_driver() '%s'\n",
+ dprintk(DEBUG_NORMAL, "usb_gadget_unregister_driver() '%s'\n",
driver->driver.name);
+ /* report disconnect */
+ if (driver->disconnect)
+ driver->disconnect(&udc->gadget);
+
driver->unbind(&udc->gadget);
device_del(&udc->gadget.dev);
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index 16bdf77..3e8dcb5 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -536,17 +536,11 @@
list_move(&req->list, &port->read_pool);
}
- /* Push from tty to ldisc; this is immediate with low_latency, and
- * may trigger callbacks to this driver ... so drop the spinlock.
+ /* Push from tty to ldisc; without low_latency set this is handled by
+ * a workqueue, so we won't get callbacks and can hold port_lock
*/
if (tty && do_push) {
- spin_unlock_irq(&port->port_lock);
tty_flip_buffer_push(tty);
- wake_up_interruptible(&tty->read_wait);
- spin_lock_irq(&port->port_lock);
-
- /* tty may have been closed */
- tty = port->port_tty;
}
@@ -784,11 +778,6 @@
port->open_count = 1;
port->openclose = false;
- /* low_latency means ldiscs work in tasklet context, without
- * needing a workqueue schedule ... easier to keep up.
- */
- tty->low_latency = 1;
-
/* if connected, start the I/O stream */
if (port->port_usb) {
struct gserial *gser = port->port_usb;
@@ -1195,6 +1184,7 @@
n_ports = 0;
tty_unregister_driver(gs_tty_driver);
+ put_tty_driver(gs_tty_driver);
gs_tty_driver = NULL;
pr_debug("%s: cleaned up ttyGS* support\n", __func__);
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index ef3e88f..a3ef2a9 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1135,7 +1135,7 @@
#ifdef CONFIG_XPS_USB_HCD_XILINX
#include "ehci-xilinx-of.c"
-#define OF_PLATFORM_DRIVER ehci_hcd_xilinx_of_driver
+#define XILINX_OF_PLATFORM_DRIVER ehci_hcd_xilinx_of_driver
#endif
#ifdef CONFIG_PLAT_ORION
@@ -1159,7 +1159,8 @@
#endif
#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
- !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER)
+ !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
+ !defined(XILINX_OF_PLATFORM_DRIVER)
#error "missing bus glue for ehci-hcd"
#endif
@@ -1213,10 +1214,20 @@
if (retval < 0)
goto clean3;
#endif
+
+#ifdef XILINX_OF_PLATFORM_DRIVER
+ retval = of_register_platform_driver(&XILINX_OF_PLATFORM_DRIVER);
+ if (retval < 0)
+ goto clean4;
+#endif
return retval;
+#ifdef XILINX_OF_PLATFORM_DRIVER
+ /* of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER); */
+clean4:
+#endif
#ifdef OF_PLATFORM_DRIVER
- /* of_unregister_platform_driver(&OF_PLATFORM_DRIVER); */
+ of_unregister_platform_driver(&OF_PLATFORM_DRIVER);
clean3:
#endif
#ifdef PS3_SYSTEM_BUS_DRIVER
@@ -1243,6 +1254,9 @@
static void __exit ehci_hcd_cleanup(void)
{
+#ifdef XILINX_OF_PLATFORM_DRIVER
+ of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER);
+#endif
#ifdef OF_PLATFORM_DRIVER
of_unregister_platform_driver(&OF_PLATFORM_DRIVER);
#endif
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
index 544ccfd..bd40277 100644
--- a/drivers/usb/host/ehci-mxc.c
+++ b/drivers/usb/host/ehci-mxc.c
@@ -207,10 +207,17 @@
/* Initialize the transceiver */
if (pdata->otg) {
pdata->otg->io_priv = hcd->regs + ULPI_VIEWPORT_OFFSET;
- if (otg_init(pdata->otg) != 0)
- dev_err(dev, "unable to init transceiver\n");
- else if (otg_set_vbus(pdata->otg, 1) != 0)
+ ret = otg_init(pdata->otg);
+ if (ret) {
+ dev_err(dev, "unable to init transceiver, probably missing\n");
+ ret = -ENODEV;
+ goto err_add;
+ }
+ ret = otg_set_vbus(pdata->otg, 1);
+ if (ret) {
dev_err(dev, "unable to enable vbus on transceiver\n");
+ goto err_add;
+ }
}
priv->hcd = hcd;
diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c
index 013972b..4899f45 100644
--- a/drivers/usb/host/ehci-xilinx-of.c
+++ b/drivers/usb/host/ehci-xilinx-of.c
@@ -151,7 +151,7 @@
static int __devinit
ehci_hcd_xilinx_of_probe(struct of_device *op, const struct of_device_id *match)
{
- struct device_node *dn = op->node;
+ struct device_node *dn = op->dev.of_node;
struct usb_hcd *hcd;
struct ehci_hcd *ehci;
struct resource res;
diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
index 20a0dfe..0587ad4 100644
--- a/drivers/usb/host/isp1362-hcd.c
+++ b/drivers/usb/host/isp1362-hcd.c
@@ -2224,12 +2224,9 @@
/*-------------------------------------------------------------------------*/
-static void isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
+static void __isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
{
int tmp = 20;
- unsigned long flags;
-
- spin_lock_irqsave(&isp1362_hcd->lock, flags);
isp1362_write_reg16(isp1362_hcd, HCSWRES, HCSWRES_MAGIC);
isp1362_write_reg32(isp1362_hcd, HCCMDSTAT, OHCI_HCR);
@@ -2240,6 +2237,14 @@
}
if (!tmp)
pr_err("Software reset timeout\n");
+}
+
+static void isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&isp1362_hcd->lock, flags);
+ __isp1362_sw_reset(isp1362_hcd);
spin_unlock_irqrestore(&isp1362_hcd->lock, flags);
}
@@ -2418,7 +2423,7 @@
if (isp1362_hcd->board && isp1362_hcd->board->reset)
isp1362_hcd->board->reset(hcd->self.controller, 1);
else
- isp1362_sw_reset(isp1362_hcd);
+ __isp1362_sw_reset(isp1362_hcd);
if (isp1362_hcd->board && isp1362_hcd->board->clock)
isp1362_hcd->board->clock(hcd->self.controller, 0);
diff --git a/drivers/usb/host/isp1362.h b/drivers/usb/host/isp1362.h
index 5151516..d995351 100644
--- a/drivers/usb/host/isp1362.h
+++ b/drivers/usb/host/isp1362.h
@@ -65,7 +65,7 @@
unsigned short *bp = (unsigned short *)buf;
while (len--) {
DUMMY_DELAY_ACCESS;
- *bp++ = inw((void *)addr);
+ *bp++ = inw(addr);
}
}
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index 6db57ab..77be3c2 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -1065,7 +1065,7 @@
else if (speed == LSMODE)
rh->port |= USB_PORT_STAT_LOW_SPEED;
- rh->port &= USB_PORT_STAT_RESET;
+ rh->port &= ~USB_PORT_STAT_RESET;
rh->port |= USB_PORT_STAT_ENABLE;
}
@@ -2404,7 +2404,7 @@
del_timer_sync(&r8a66597->rh_timer);
usb_remove_hcd(hcd);
- iounmap((void *)r8a66597->reg);
+ iounmap(r8a66597->reg);
#ifdef CONFIG_HAVE_CLK
if (r8a66597->pdata->on_chip)
clk_put(r8a66597->clk);
@@ -2496,7 +2496,7 @@
init_timer(&r8a66597->rh_timer);
r8a66597->rh_timer.function = r8a66597_timer;
r8a66597->rh_timer.data = (unsigned long)r8a66597;
- r8a66597->reg = (unsigned long)reg;
+ r8a66597->reg = reg;
/* make sure no interrupts are pending */
ret = r8a66597_clock_enable(r8a66597);
diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h
index 228e3fb..95d0f5a 100644
--- a/drivers/usb/host/r8a66597.h
+++ b/drivers/usb/host/r8a66597.h
@@ -112,7 +112,7 @@
struct r8a66597 {
spinlock_t lock;
- unsigned long reg;
+ void __iomem *reg;
#ifdef CONFIG_HAVE_CLK
struct clk *clk;
#endif
@@ -170,67 +170,67 @@
static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset)
{
- return inw(r8a66597->reg + offset);
+ return ioread16(r8a66597->reg + offset);
}
static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
unsigned long offset, u16 *buf,
int len)
{
- unsigned long fifoaddr = r8a66597->reg + offset;
+ void __iomem *fifoaddr = r8a66597->reg + offset;
unsigned long count;
if (r8a66597->pdata->on_chip) {
count = len / 4;
- insl(fifoaddr, buf, count);
+ ioread32_rep(fifoaddr, buf, count);
if (len & 0x00000003) {
- unsigned long tmp = inl(fifoaddr);
+ unsigned long tmp = ioread32(fifoaddr);
memcpy((unsigned char *)buf + count * 4, &tmp,
len & 0x03);
}
} else {
len = (len + 1) / 2;
- insw(fifoaddr, buf, len);
+ ioread16_rep(fifoaddr, buf, len);
}
}
static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
unsigned long offset)
{
- outw(val, r8a66597->reg + offset);
+ iowrite16(val, r8a66597->reg + offset);
}
static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
unsigned long offset, u16 *buf,
int len)
{
- unsigned long fifoaddr = r8a66597->reg + offset;
+ void __iomem *fifoaddr = r8a66597->reg + offset;
unsigned long count;
unsigned char *pb;
int i;
if (r8a66597->pdata->on_chip) {
count = len / 4;
- outsl(fifoaddr, buf, count);
+ iowrite32_rep(fifoaddr, buf, count);
if (len & 0x00000003) {
pb = (unsigned char *)buf + count * 4;
for (i = 0; i < (len & 0x00000003); i++) {
if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)
- outb(pb[i], fifoaddr + i);
+ iowrite8(pb[i], fifoaddr + i);
else
- outb(pb[i], fifoaddr + 3 - i);
+ iowrite8(pb[i], fifoaddr + 3 - i);
}
}
} else {
int odd = len & 0x0001;
len = len / 2;
- outsw(fifoaddr, buf, len);
+ ioread16_rep(fifoaddr, buf, len);
if (unlikely(odd)) {
buf = &buf[len];
- outb((unsigned char)*buf, fifoaddr);
+ iowrite8((unsigned char)*buf, fifoaddr);
}
}
}
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index edffd81..11482b6 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -78,6 +78,8 @@
xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure"
" endpoint cmd after reset endpoint\n");
}
+ if (pdev->vendor == PCI_VENDOR_ID_NEC)
+ xhci->quirks |= XHCI_NEC_HOST;
/* Make sure the HC is halted. */
retval = xhci_halt(xhci);
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 36c858e..94e6934 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -182,8 +182,12 @@
* set, but other sections talk about dealing with the chain bit set. This was
* fixed in the 0.96 specification errata, but we have to assume that all 0.95
* xHCI hardware can't handle the chain bit being cleared on a link TRB.
+ *
+ * @more_trbs_coming: Will you enqueue more TRBs before calling
+ * prepare_transfer()?
*/
-static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer)
+static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
+ bool consumer, bool more_trbs_coming)
{
u32 chain;
union xhci_trb *next;
@@ -199,15 +203,28 @@
while (last_trb(xhci, ring, ring->enq_seg, next)) {
if (!consumer) {
if (ring != xhci->event_ring) {
- if (chain) {
- next->link.control |= TRB_CHAIN;
-
- /* Give this link TRB to the hardware */
- wmb();
- next->link.control ^= TRB_CYCLE;
- } else {
+ /*
+ * If the caller doesn't plan on enqueueing more
+ * TDs before ringing the doorbell, then we
+ * don't want to give the link TRB to the
+ * hardware just yet. We'll give the link TRB
+ * back in prepare_ring() just before we enqueue
+ * the TD at the top of the ring.
+ */
+ if (!chain && !more_trbs_coming)
break;
+
+ /* If we're not dealing with 0.95 hardware,
+ * carry over the chain bit of the previous TRB
+ * (which may mean the chain bit is cleared).
+ */
+ if (!xhci_link_trb_quirk(xhci)) {
+ next->link.control &= ~TRB_CHAIN;
+ next->link.control |= chain;
}
+ /* Give this link TRB to the hardware */
+ wmb();
+ next->link.control ^= TRB_CYCLE;
}
/* Toggle the cycle bit after the last ring segment. */
if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) {
@@ -1071,6 +1088,15 @@
xhci_warn(xhci, "Reset device command completion "
"for disabled slot %u\n", slot_id);
break;
+ case TRB_TYPE(TRB_NEC_GET_FW):
+ if (!(xhci->quirks & XHCI_NEC_HOST)) {
+ xhci->error_bitmask |= 1 << 6;
+ break;
+ }
+ xhci_dbg(xhci, "NEC firmware version %2x.%02x\n",
+ NEC_FW_MAJOR(event->status),
+ NEC_FW_MINOR(event->status));
+ break;
default:
/* Skip over unknown commands on the event ring */
xhci->error_bitmask |= 1 << 6;
@@ -1079,6 +1105,17 @@
inc_deq(xhci, xhci->cmd_ring, false);
}
+static void handle_vendor_event(struct xhci_hcd *xhci,
+ union xhci_trb *event)
+{
+ u32 trb_type;
+
+ trb_type = TRB_FIELD_TO_TYPE(event->generic.field[3]);
+ xhci_dbg(xhci, "Vendor specific event TRB type = %u\n", trb_type);
+ if (trb_type == TRB_NEC_CMD_COMP && (xhci->quirks & XHCI_NEC_HOST))
+ handle_cmd_completion(xhci, &event->event_cmd);
+}
+
static void handle_port_status(struct xhci_hcd *xhci,
union xhci_trb *event)
{
@@ -1659,7 +1696,10 @@
update_ptrs = 0;
break;
default:
- xhci->error_bitmask |= 1 << 3;
+ if ((event->event_cmd.flags & TRB_TYPE_BITMASK) >= TRB_TYPE(48))
+ handle_vendor_event(xhci, event);
+ else
+ xhci->error_bitmask |= 1 << 3;
}
/* Any of the above functions may drop and re-acquire the lock, so check
* to make sure a watchdog timer didn't mark the host as non-responsive.
@@ -1684,9 +1724,12 @@
/*
* Generic function for queueing a TRB on a ring.
* The caller must have checked to make sure there's room on the ring.
+ *
+ * @more_trbs_coming: Will you enqueue more TRBs before calling
+ * prepare_transfer()?
*/
static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
- bool consumer,
+ bool consumer, bool more_trbs_coming,
u32 field1, u32 field2, u32 field3, u32 field4)
{
struct xhci_generic_trb *trb;
@@ -1696,7 +1739,7 @@
trb->field[1] = field2;
trb->field[2] = field3;
trb->field[3] = field4;
- inc_enq(xhci, ring, consumer);
+ inc_enq(xhci, ring, consumer, more_trbs_coming);
}
/*
@@ -1965,6 +2008,7 @@
int trb_buff_len, this_sg_len, running_total;
bool first_trb;
u64 addr;
+ bool more_trbs_coming;
struct xhci_generic_trb *start_trb;
int start_cycle;
@@ -2050,7 +2094,11 @@
length_field = TRB_LEN(trb_buff_len) |
remainder |
TRB_INTR_TARGET(0);
- queue_trb(xhci, ep_ring, false,
+ if (num_trbs > 1)
+ more_trbs_coming = true;
+ else
+ more_trbs_coming = false;
+ queue_trb(xhci, ep_ring, false, more_trbs_coming,
lower_32_bits(addr),
upper_32_bits(addr),
length_field,
@@ -2101,6 +2149,7 @@
int num_trbs;
struct xhci_generic_trb *start_trb;
bool first_trb;
+ bool more_trbs_coming;
int start_cycle;
u32 field, length_field;
@@ -2189,7 +2238,11 @@
length_field = TRB_LEN(trb_buff_len) |
remainder |
TRB_INTR_TARGET(0);
- queue_trb(xhci, ep_ring, false,
+ if (num_trbs > 1)
+ more_trbs_coming = true;
+ else
+ more_trbs_coming = false;
+ queue_trb(xhci, ep_ring, false, more_trbs_coming,
lower_32_bits(addr),
upper_32_bits(addr),
length_field,
@@ -2268,7 +2321,7 @@
/* Queue setup TRB - see section 6.4.1.2.1 */
/* FIXME better way to translate setup_packet into two u32 fields? */
setup = (struct usb_ctrlrequest *) urb->setup_packet;
- queue_trb(xhci, ep_ring, false,
+ queue_trb(xhci, ep_ring, false, true,
/* FIXME endianness is probably going to bite my ass here. */
setup->bRequestType | setup->bRequest << 8 | setup->wValue << 16,
setup->wIndex | setup->wLength << 16,
@@ -2284,7 +2337,7 @@
if (urb->transfer_buffer_length > 0) {
if (setup->bRequestType & USB_DIR_IN)
field |= TRB_DIR_IN;
- queue_trb(xhci, ep_ring, false,
+ queue_trb(xhci, ep_ring, false, true,
lower_32_bits(urb->transfer_dma),
upper_32_bits(urb->transfer_dma),
length_field,
@@ -2301,7 +2354,7 @@
field = 0;
else
field = TRB_DIR_IN;
- queue_trb(xhci, ep_ring, false,
+ queue_trb(xhci, ep_ring, false, false,
0,
0,
TRB_INTR_TARGET(0),
@@ -2338,7 +2391,7 @@
"unfailable commands failed.\n");
return -ENOMEM;
}
- queue_trb(xhci, xhci->cmd_ring, false, field1, field2, field3,
+ queue_trb(xhci, xhci->cmd_ring, false, false, field1, field2, field3,
field4 | xhci->cmd_ring->cycle_state);
return 0;
}
@@ -2378,6 +2431,12 @@
false);
}
+int xhci_queue_vendor_command(struct xhci_hcd *xhci,
+ u32 field1, u32 field2, u32 field3, u32 field4)
+{
+ return queue_command(xhci, field1, field2, field3, field4, false);
+}
+
/* Queue a reset device command TRB */
int xhci_queue_reset_device(struct xhci_hcd *xhci, u32 slot_id)
{
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 40e0a0c..27345cd 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -106,6 +106,33 @@
}
/*
+ * Set the run bit and wait for the host to be running.
+ */
+int xhci_start(struct xhci_hcd *xhci)
+{
+ u32 temp;
+ int ret;
+
+ temp = xhci_readl(xhci, &xhci->op_regs->command);
+ temp |= (CMD_RUN);
+ xhci_dbg(xhci, "// Turn on HC, cmd = 0x%x.\n",
+ temp);
+ xhci_writel(xhci, temp, &xhci->op_regs->command);
+
+ /*
+ * Wait for the HCHalted Status bit to be 0 to indicate the host is
+ * running.
+ */
+ ret = handshake(xhci, &xhci->op_regs->status,
+ STS_HALT, 0, XHCI_MAX_HALT_USEC);
+ if (ret == -ETIMEDOUT)
+ xhci_err(xhci, "Host took too long to start, "
+ "waited %u microseconds.\n",
+ XHCI_MAX_HALT_USEC);
+ return ret;
+}
+
+/*
* Reset a halted HC, and set the internal HC state to HC_STATE_HALT.
*
* This resets pipelines, timers, counters, state machines, etc.
@@ -116,6 +143,7 @@
{
u32 command;
u32 state;
+ int ret;
state = xhci_readl(xhci, &xhci->op_regs->status);
if ((state & STS_HALT) == 0) {
@@ -130,7 +158,17 @@
/* XXX: Why does EHCI set this here? Shouldn't other code do this? */
xhci_to_hcd(xhci)->state = HC_STATE_HALT;
- return handshake(xhci, &xhci->op_regs->command, CMD_RESET, 0, 250 * 1000);
+ ret = handshake(xhci, &xhci->op_regs->command,
+ CMD_RESET, 0, 250 * 1000);
+ if (ret)
+ return ret;
+
+ xhci_dbg(xhci, "Wait for controller to be ready for doorbell rings\n");
+ /*
+ * xHCI cannot write to any doorbells or operational registers other
+ * than status until the "Controller Not Ready" flag is cleared.
+ */
+ return handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000);
}
@@ -448,17 +486,20 @@
if (NUM_TEST_NOOPS > 0)
doorbell = xhci_setup_one_noop(xhci);
+ if (xhci->quirks & XHCI_NEC_HOST)
+ xhci_queue_vendor_command(xhci, 0, 0, 0,
+ TRB_TYPE(TRB_NEC_GET_FW));
- temp = xhci_readl(xhci, &xhci->op_regs->command);
- temp |= (CMD_RUN);
- xhci_dbg(xhci, "// Turn on HC, cmd = 0x%x.\n",
- temp);
- xhci_writel(xhci, temp, &xhci->op_regs->command);
- /* Flush PCI posted writes */
- temp = xhci_readl(xhci, &xhci->op_regs->command);
+ if (xhci_start(xhci)) {
+ xhci_halt(xhci);
+ return -ENODEV;
+ }
+
xhci_dbg(xhci, "// @%p = 0x%x\n", &xhci->op_regs->command, temp);
if (doorbell)
(*doorbell)(xhci);
+ if (xhci->quirks & XHCI_NEC_HOST)
+ xhci_ring_cmd_db(xhci);
xhci_dbg(xhci, "Finished xhci_run\n");
return 0;
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index dada2fb..8b4b7d3 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -925,6 +925,7 @@
/* TRB bit mask */
#define TRB_TYPE_BITMASK (0xfc00)
#define TRB_TYPE(p) ((p) << 10)
+#define TRB_FIELD_TO_TYPE(p) (((p) & TRB_TYPE_BITMASK) >> 10)
/* TRB type IDs */
/* bulk, interrupt, isoc scatter/gather, and control data stage */
#define TRB_NORMAL 1
@@ -992,6 +993,14 @@
#define TRB_MFINDEX_WRAP 39
/* TRB IDs 40-47 reserved, 48-63 is vendor-defined */
+/* Nec vendor-specific command completion event. */
+#define TRB_NEC_CMD_COMP 48
+/* Get NEC firmware revision. */
+#define TRB_NEC_GET_FW 49
+
+#define NEC_FW_MINOR(p) (((p) >> 0) & 0xff)
+#define NEC_FW_MAJOR(p) (((p) >> 8) & 0xff)
+
/*
* TRBS_PER_SEGMENT must be a multiple of 4,
* since the command ring is 64-byte aligned.
@@ -1172,6 +1181,7 @@
unsigned int quirks;
#define XHCI_LINK_TRB_QUIRK (1 << 0)
#define XHCI_RESET_EP_QUIRK (1 << 1)
+#define XHCI_NEC_HOST (1 << 2)
};
/* For testing purposes */
@@ -1379,6 +1389,8 @@
int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id);
int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
u32 slot_id);
+int xhci_queue_vendor_command(struct xhci_hcd *xhci,
+ u32 field1, u32 field2, u32 field3, u32 field4);
int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id,
unsigned int ep_index);
int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index fad70bc..3b795c5 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -219,8 +219,8 @@
return 0;
}
#else
-#define musb_ulpi_read(a, b) NULL
-#define musb_ulpi_write(a, b, c) NULL
+#define musb_ulpi_read NULL
+#define musb_ulpi_write NULL
#endif
static struct otg_io_access_ops musb_ulpi_access = {
@@ -451,10 +451,6 @@
* @param power
*/
-#define STAGE0_MASK (MUSB_INTR_RESUME | MUSB_INTR_SESSREQ \
- | MUSB_INTR_VBUSERROR | MUSB_INTR_CONNECT \
- | MUSB_INTR_RESET)
-
static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
u8 devctl, u8 power)
{
@@ -642,7 +638,7 @@
handled = IRQ_HANDLED;
}
-
+#endif
if (int_usb & MUSB_INTR_SUSPEND) {
DBG(1, "SUSPEND (%s) devctl %02x power %02x\n",
otg_state_string(musb), devctl, power);
@@ -705,6 +701,7 @@
}
}
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
if (int_usb & MUSB_INTR_CONNECT) {
struct usb_hcd *hcd = musb_to_hcd(musb);
void __iomem *mbase = musb->mregs;
@@ -1597,7 +1594,7 @@
/* the core can interrupt us for multiple reasons; docs have
* a generic interrupt flowchart to follow
*/
- if (musb->int_usb & STAGE0_MASK)
+ if (musb->int_usb)
retval |= musb_stage0_irq(musb, musb->int_usb,
devctl, power);
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index b22d02d..91d6779 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -470,7 +470,8 @@
struct musb_context_registers {
-#ifdef CONFIG_PM
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
+ defined(CONFIG_ARCH_OMAP4)
u32 otg_sysconfig, otg_forcestandby;
#endif
u8 power;
@@ -484,7 +485,8 @@
struct musb_csr_regs index_regs[MUSB_C_NUM_EPS];
};
-#ifdef CONFIG_PM
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
+ defined(CONFIG_ARCH_OMAP4)
extern void musb_platform_save_context(struct musb *musb,
struct musb_context_registers *musb_context);
extern void musb_platform_restore_context(struct musb *musb,
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index 1008044..dc66e43 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -132,18 +132,9 @@
if (mode) {
csr |= 1 << MUSB_HSDMA_MODE1_SHIFT;
BUG_ON(len < packet_sz);
-
- if (packet_sz >= 64) {
- csr |= MUSB_HSDMA_BURSTMODE_INCR16
- << MUSB_HSDMA_BURSTMODE_SHIFT;
- } else if (packet_sz >= 32) {
- csr |= MUSB_HSDMA_BURSTMODE_INCR8
- << MUSB_HSDMA_BURSTMODE_SHIFT;
- } else if (packet_sz >= 16) {
- csr |= MUSB_HSDMA_BURSTMODE_INCR4
- << MUSB_HSDMA_BURSTMODE_SHIFT;
- }
}
+ csr |= MUSB_HSDMA_BURSTMODE_INCR16
+ << MUSB_HSDMA_BURSTMODE_SHIFT;
csr |= (musb_channel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT)
| (1 << MUSB_HSDMA_ENABLE_SHIFT)
diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c
index b1b3469..d331b22 100644
--- a/drivers/usb/otg/ulpi.c
+++ b/drivers/usb/otg/ulpi.c
@@ -59,12 +59,17 @@
static int ulpi_init(struct otg_transceiver *otg)
{
- int i, vid, pid;
+ int i, vid, pid, ret;
+ u32 ulpi_id = 0;
- vid = (otg_io_read(otg, ULPI_VENDOR_ID_HIGH) << 8) |
- otg_io_read(otg, ULPI_VENDOR_ID_LOW);
- pid = (otg_io_read(otg, ULPI_PRODUCT_ID_HIGH) << 8) |
- otg_io_read(otg, ULPI_PRODUCT_ID_LOW);
+ for (i = 0; i < 4; i++) {
+ ret = otg_io_read(otg, ULPI_PRODUCT_ID_HIGH - i);
+ if (ret < 0)
+ return ret;
+ ulpi_id = (ulpi_id << 8) | ret;
+ }
+ vid = ulpi_id & 0xffff;
+ pid = ulpi_id >> 16;
pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid);
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 3edda3e..fd35f73 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -1239,8 +1239,7 @@
/* port and serial sanity check */
if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) {
- dev_err(&port->dev,
- "%s: port or port->private is NULL, status=%d\n",
+ pr_err("%s: port or port->private is NULL, status=%d\n",
__func__, status);
return;
}
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 050211a..da7e334 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -653,7 +653,6 @@
{ USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },
{ USB_DEVICE(EVOLUTION_VID, EVO_HYBRID_PID) },
{ USB_DEVICE(EVOLUTION_VID, EVO_RCM4_PID) },
- { USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) },
@@ -2005,6 +2004,8 @@
"urb failed to set to rts/cts flow control\n");
}
+ /* raise DTR/RTS */
+ set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
} else {
/*
* Xon/Xoff code
@@ -2052,6 +2053,8 @@
}
}
+ /* lower DTR/RTS */
+ clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
}
return;
}
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 94d86c3..bbc159a 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -501,13 +501,6 @@
#define CONTEC_COM1USBH_PID 0x8311 /* COM-1(USB)H */
/*
- * Contec products (http://www.contec.com)
- * Submitted by Daniel Sangorrin
- */
-#define CONTEC_VID 0x06CE /* Vendor ID */
-#define CONTEC_COM1USBH_PID 0x8311 /* COM-1(USB)H */
-
-/*
* Definitions for B&B Electronics products.
*/
#define BANDB_VID 0x0856 /* B&B Electronics Vendor ID */
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index f8424d1..585b7e6 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -730,7 +730,6 @@
mos7840_port = urb->context;
if (!mos7840_port) {
dbg("%s", "NULL mos7840_port pointer");
- mos7840_port->read_urb_busy = false;
return;
}
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index 04bb759..93d72eb 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -139,6 +139,7 @@
"Could not set interface, error %d\n",
retval);
retval = -ENODEV;
+ kfree(data);
}
return retval;
}
@@ -155,6 +156,7 @@
"Could not set interface, error %d\n",
retval);
retval = -ENODEV;
+ kfree(data);
}
return retval;
}
@@ -163,6 +165,7 @@
default:
dev_err(&serial->dev->dev,
"unknown number of interfaces: %d\n", nintf);
+ kfree(data);
return -ENODEV;
}
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 0f41c91..df5b6b9 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -637,7 +637,7 @@
};
static struct miscdevice vhost_net_misc = {
- VHOST_NET_MINOR,
+ MISC_DYNAMIC_MINOR,
"vhost-net",
&vhost_net_fops,
};
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 1e6fec4..3d94a14 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -8,6 +8,9 @@
config HAVE_FB_ATMEL
bool
+config HAVE_FB_IMX
+ bool
+
source "drivers/char/agp/Kconfig"
source "drivers/gpu/vga/Kconfig"
@@ -400,9 +403,6 @@
If you plan to use the LCD display with your SA-1100 system, say
Y here.
-config HAVE_FB_IMX
- bool
-
config FB_IMX
tristate "Motorola i.MX LCD support"
depends on FB && (HAVE_FB_IMX || ARCH_MX1 || ARCH_MX2)
diff --git a/drivers/video/aty/mach64_accel.c b/drivers/video/aty/mach64_accel.c
index 51fcc0a..e45833c 100644
--- a/drivers/video/aty/mach64_accel.c
+++ b/drivers/video/aty/mach64_accel.c
@@ -242,7 +242,7 @@
void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
- u32 color = rect->color, dx = rect->dx, width = rect->width, rotation = 0;
+ u32 color, dx = rect->dx, width = rect->width, rotation = 0;
if (par->asleep)
return;
@@ -253,8 +253,11 @@
return;
}
- color |= (rect->color << 8);
- color |= (rect->color << 16);
+ if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+ info->fix.visual == FB_VISUAL_DIRECTCOLOR)
+ color = ((u32 *)(info->pseudo_palette))[rect->color];
+ else
+ color = rect->color;
if (info->var.bits_per_pixel == 24) {
/* In 24 bpp, the engine is in 8 bpp - this requires that all */
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
index 921ca37..3ec2460 100644
--- a/drivers/video/backlight/adp8860_bl.c
+++ b/drivers/video/backlight/adp8860_bl.c
@@ -756,7 +756,6 @@
out1:
backlight_device_unregister(bl);
out2:
- i2c_set_clientdata(client, NULL);
kfree(data);
return ret;
@@ -776,7 +775,6 @@
&adp8860_bl_attr_group);
backlight_device_unregister(data->bl);
- i2c_set_clientdata(client, NULL);
kfree(data);
return 0;
diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c
index e03e60b..2a04b38 100644
--- a/drivers/video/backlight/tosa_bl.c
+++ b/drivers/video/backlight/tosa_bl.c
@@ -119,7 +119,6 @@
err_reg:
data->bl = NULL;
- i2c_set_clientdata(client, NULL);
err_gpio_dir:
gpio_free(TOSA_GPIO_BL_C20MA);
err_gpio_bl:
@@ -133,7 +132,6 @@
backlight_device_unregister(data->bl);
data->bl = NULL;
- i2c_set_clientdata(client, NULL);
gpio_free(TOSA_GPIO_BL_C20MA);
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
index 2c371c0..09f1b9b 100644
--- a/drivers/video/bw2.c
+++ b/drivers/video/bw2.c
@@ -275,7 +275,7 @@
static int __devinit bw2_probe(struct of_device *op, const struct of_device_id *match)
{
- struct device_node *dp = op->node;
+ struct device_node *dp = op->dev.of_node;
struct fb_info *info;
struct bw2_par *par;
int linebytes, err;
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c
index d12e05b..e5dc224 100644
--- a/drivers/video/cg14.c
+++ b/drivers/video/cg14.c
@@ -465,7 +465,7 @@
static int __devinit cg14_probe(struct of_device *op, const struct of_device_id *match)
{
- struct device_node *dp = op->node;
+ struct device_node *dp = op->dev.of_node;
struct fb_info *info;
struct cg14_par *par;
int is_8mb, linebytes, i, err;
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c
index b98f93f..558d73a 100644
--- a/drivers/video/cg3.c
+++ b/drivers/video/cg3.c
@@ -349,7 +349,7 @@
static int __devinit cg3_probe(struct of_device *op,
const struct of_device_id *match)
{
- struct device_node *dp = op->node;
+ struct device_node *dp = op->dev.of_node;
struct fb_info *info;
struct cg3_par *par;
int linebytes, err;
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c
index 073c9b4..6b93ef9 100644
--- a/drivers/video/fb_defio.c
+++ b/drivers/video/fb_defio.c
@@ -100,6 +100,16 @@
/* protect against the workqueue changing the page list */
mutex_lock(&fbdefio->lock);
+ /*
+ * We want the page to remain locked from ->page_mkwrite until
+ * the PTE is marked dirty to avoid page_mkclean() being called
+ * before the PTE is updated, which would leave the page ignored
+ * by defio.
+ * Do this by locking the page here and informing the caller
+ * about it with VM_FAULT_LOCKED.
+ */
+ lock_page(page);
+
/* we loop through the pagelist before adding in order
to keep the pagelist sorted */
list_for_each_entry(cur, &fbdefio->pagelist, lru) {
@@ -121,7 +131,7 @@
/* come back after delay to process the deferred IO */
schedule_delayed_work(&info->deferred_work, fbdefio->delay);
- return 0;
+ return VM_FAULT_LOCKED;
}
static const struct vm_operations_struct fb_deferred_io_vm_ops = {
@@ -155,41 +165,25 @@
{
struct fb_info *info = container_of(work, struct fb_info,
deferred_work.work);
+ struct list_head *node, *next;
+ struct page *cur;
struct fb_deferred_io *fbdefio = info->fbdefio;
- struct page *page, *tmp_page;
- struct list_head *node, *tmp_node;
- struct list_head non_dirty;
-
- INIT_LIST_HEAD(&non_dirty);
/* here we mkclean the pages, then do all deferred IO */
mutex_lock(&fbdefio->lock);
- list_for_each_entry_safe(page, tmp_page, &fbdefio->pagelist, lru) {
- lock_page(page);
- /*
- * The workqueue callback can be triggered after a
- * ->page_mkwrite() call but before the PTE has been marked
- * dirty. In this case page_mkclean() won't "rearm" the page.
- *
- * To avoid this, remove those "non-dirty" pages from the
- * pagelist before calling the driver's callback, then add
- * them back to get processed on the next work iteration.
- * At that time, their PTEs will hopefully be dirty for real.
- */
- if (!page_mkclean(page))
- list_move_tail(&page->lru, &non_dirty);
- unlock_page(page);
+ list_for_each_entry(cur, &fbdefio->pagelist, lru) {
+ lock_page(cur);
+ page_mkclean(cur);
+ unlock_page(cur);
}
/* driver's callback with pagelist */
fbdefio->deferred_io(info, &fbdefio->pagelist);
- /* clear the list... */
- list_for_each_safe(node, tmp_node, &fbdefio->pagelist) {
+ /* clear the list */
+ list_for_each_safe(node, next, &fbdefio->pagelist) {
list_del(node);
}
- /* ... and add back the "non-dirty" pages to the list */
- list_splice_tail(&non_dirty, &fbdefio->pagelist);
mutex_unlock(&fbdefio->lock);
}
@@ -218,7 +212,6 @@
void fb_deferred_io_cleanup(struct fb_info *info)
{
struct fb_deferred_io *fbdefio = info->fbdefio;
- struct list_head *node, *tmp_node;
struct page *page;
int i;
@@ -226,13 +219,6 @@
cancel_delayed_work(&info->deferred_work);
flush_scheduled_work();
- /* the list may have still some non-dirty pages at this point */
- mutex_lock(&fbdefio->lock);
- list_for_each_safe(node, tmp_node, &fbdefio->pagelist) {
- list_del(node);
- }
- mutex_unlock(&fbdefio->lock);
-
/* clear out the mapping that we setup */
for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) {
page = fb_deferred_io_page(info, i);
diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c
index 76e7dac..70b1d9d 100644
--- a/drivers/video/geode/gxfb_core.c
+++ b/drivers/video/geode/gxfb_core.c
@@ -40,7 +40,7 @@
static int vt_switch;
/* Modes relevant to the GX (taken from modedb.c) */
-static struct fb_videomode gx_modedb[] __initdata = {
+static struct fb_videomode gx_modedb[] __devinitdata = {
/* 640x480-60 VESA */
{ NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2,
0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
@@ -110,14 +110,15 @@
#ifdef CONFIG_OLPC
#include <asm/olpc.h>
-static struct fb_videomode gx_dcon_modedb[] __initdata = {
+static struct fb_videomode gx_dcon_modedb[] __devinitdata = {
/* The only mode the DCON has is 1200x900 */
{ NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
FB_VMODE_NONINTERLACED, 0 }
};
-static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
+static void __devinit get_modedb(struct fb_videomode **modedb,
+ unsigned int *size)
{
if (olpc_has_dcon()) {
*modedb = (struct fb_videomode *) gx_dcon_modedb;
@@ -129,7 +130,8 @@
}
#else
-static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
+static void __devinit get_modedb(struct fb_videomode **modedb,
+ unsigned int *size)
{
*modedb = (struct fb_videomode *) gx_modedb;
*size = ARRAY_SIZE(gx_modedb);
@@ -226,7 +228,8 @@
return gx_blank_display(info, blank_mode);
}
-static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
+static int __devinit gxfb_map_video_memory(struct fb_info *info,
+ struct pci_dev *dev)
{
struct gxfb_par *par = info->par;
int ret;
@@ -290,7 +293,7 @@
.fb_imageblit = cfb_imageblit,
};
-static struct fb_info * __init gxfb_init_fbinfo(struct device *dev)
+static struct fb_info *__devinit gxfb_init_fbinfo(struct device *dev)
{
struct gxfb_par *par;
struct fb_info *info;
@@ -371,7 +374,8 @@
}
#endif
-static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int __devinit gxfb_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
{
struct gxfb_par *par;
struct fb_info *info;
@@ -451,7 +455,7 @@
return ret;
}
-static void gxfb_remove(struct pci_dev *pdev)
+static void __devexit gxfb_remove(struct pci_dev *pdev)
{
struct fb_info *info = pci_get_drvdata(pdev);
struct gxfb_par *par = info->par;
diff --git a/drivers/video/geode/lxfb_core.c b/drivers/video/geode/lxfb_core.c
index 1a18da8..39bdbed 100644
--- a/drivers/video/geode/lxfb_core.c
+++ b/drivers/video/geode/lxfb_core.c
@@ -35,7 +35,7 @@
* we try to make it something sane - 640x480-60 is sane
*/
-static struct fb_videomode geode_modedb[] __initdata = {
+static struct fb_videomode geode_modedb[] __devinitdata = {
/* 640x480-60 */
{ NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2,
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
@@ -219,14 +219,15 @@
#ifdef CONFIG_OLPC
#include <asm/olpc.h>
-static struct fb_videomode olpc_dcon_modedb[] __initdata = {
+static struct fb_videomode olpc_dcon_modedb[] __devinitdata = {
/* The only mode the DCON has is 1200x900 */
{ NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
FB_VMODE_NONINTERLACED, 0 }
};
-static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
+static void __devinit get_modedb(struct fb_videomode **modedb,
+ unsigned int *size)
{
if (olpc_has_dcon()) {
*modedb = (struct fb_videomode *) olpc_dcon_modedb;
@@ -238,7 +239,8 @@
}
#else
-static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)
+static void __devinit get_modedb(struct fb_videomode **modedb,
+ unsigned int *size)
{
*modedb = (struct fb_videomode *) geode_modedb;
*size = ARRAY_SIZE(geode_modedb);
@@ -334,7 +336,7 @@
}
-static int __init lxfb_map_video_memory(struct fb_info *info,
+static int __devinit lxfb_map_video_memory(struct fb_info *info,
struct pci_dev *dev)
{
struct lxfb_par *par = info->par;
@@ -412,7 +414,7 @@
.fb_imageblit = cfb_imageblit,
};
-static struct fb_info * __init lxfb_init_fbinfo(struct device *dev)
+static struct fb_info * __devinit lxfb_init_fbinfo(struct device *dev)
{
struct lxfb_par *par;
struct fb_info *info;
@@ -496,7 +498,7 @@
#define lxfb_resume NULL
#endif
-static int __init lxfb_probe(struct pci_dev *pdev,
+static int __devinit lxfb_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct lxfb_par *par;
@@ -588,7 +590,7 @@
return ret;
}
-static void lxfb_remove(struct pci_dev *pdev)
+static void __devexit lxfb_remove(struct pci_dev *pdev)
{
struct fb_info *info = pci_get_drvdata(pdev);
struct lxfb_par *par = info->par;
diff --git a/drivers/video/leo.c b/drivers/video/leo.c
index 3d78953..9e8bf7d 100644
--- a/drivers/video/leo.c
+++ b/drivers/video/leo.c
@@ -550,7 +550,7 @@
static int __devinit leo_probe(struct of_device *op,
const struct of_device_id *match)
{
- struct device_node *dp = op->node;
+ struct device_node *dp = op->dev.of_node;
struct fb_info *info;
struct leo_par *par;
int linebytes, err;
diff --git a/drivers/video/mb862xx/mb862xxfb.c b/drivers/video/mb862xx/mb862xxfb.c
index 0540de4..4e2b8cc 100644
--- a/drivers/video/mb862xx/mb862xxfb.c
+++ b/drivers/video/mb862xx/mb862xxfb.c
@@ -553,7 +553,7 @@
static int __devinit of_platform_mb862xx_probe(struct of_device *ofdev,
const struct of_device_id *id)
{
- struct device_node *np = ofdev->node;
+ struct device_node *np = ofdev->dev.of_node;
struct device *dev = &ofdev->dev;
struct mb862xxfb_par *par;
struct fb_info *info;
diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
index d4cde79..81687ed 100644
--- a/drivers/video/nuc900fb.c
+++ b/drivers/video/nuc900fb.c
@@ -596,8 +596,6 @@
goto release_regs;
}
- nuc900_driver_clksrc_div(&pdev->dev, "ext", 0x2);
-
fbi->clk = clk_get(&pdev->dev, NULL);
if (!fbi->clk || IS_ERR(fbi->clk)) {
printk(KERN_ERR "nuc900-lcd:failed to get lcd clock source\n");
diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c
index 43ab7d8..7767338 100644
--- a/drivers/video/omap/lcdc.c
+++ b/drivers/video/omap/lcdc.c
@@ -572,22 +572,12 @@
/* PM code called only in internal controller mode */
static void omap_lcdc_suspend(void)
{
- if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
- disable_controller();
- omap_stop_lcd_dma();
- }
+ omap_lcdc_set_update_mode(OMAPFB_UPDATE_DISABLED);
}
static void omap_lcdc_resume(void)
{
- if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
- setup_regs();
- load_palette();
- setup_lcd_dma();
- set_load_mode(OMAP_LCDC_LOAD_FRAME);
- enable_irqs(OMAP_LCDC_IRQ_DONE);
- enable_controller();
- }
+ omap_lcdc_set_update_mode(OMAPFB_AUTO_UPDATE);
}
static void omap_lcdc_get_caps(int plane, struct omapfb_caps *caps)
diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c
index 1162603..eada9f1 100644
--- a/drivers/video/omap/rfbi.c
+++ b/drivers/video/omap/rfbi.c
@@ -26,6 +26,7 @@
#include <linux/interrupt.h>
#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/platform_device.h>
#include "omapfb.h"
#include "dispc.h"
@@ -83,13 +84,13 @@
static int rfbi_get_clocks(void)
{
- rfbi.dss_ick = clk_get(&dispc.fbdev->dssdev->dev, "ick");
+ rfbi.dss_ick = clk_get(&rfbi.fbdev->dssdev->dev, "ick");
if (IS_ERR(rfbi.dss_ick)) {
dev_err(rfbi.fbdev->dev, "can't get ick\n");
return PTR_ERR(rfbi.dss_ick);
}
- rfbi.dss1_fck = clk_get(&dispc.fbdev->dssdev->dev, "dss1_fck");
+ rfbi.dss1_fck = clk_get(&rfbi.fbdev->dssdev->dev, "dss1_fck");
if (IS_ERR(rfbi.dss1_fck)) {
dev_err(rfbi.fbdev->dev, "can't get dss1_fck\n");
clk_put(rfbi.dss_ick);
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c
index c85dd40..6552751 100644
--- a/drivers/video/p9100.c
+++ b/drivers/video/p9100.c
@@ -251,7 +251,7 @@
static int __devinit p9100_probe(struct of_device *op, const struct of_device_id *match)
{
- struct device_node *dp = op->node;
+ struct device_node *dp = op->dev.of_node;
struct fb_info *info;
struct p9100_par *par;
int linebytes, err;
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index e8c7699..12c451a 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -991,13 +991,13 @@
priv->ch[j].lcdc = priv;
memcpy(&priv->ch[j].cfg, &pdata->ch[i], sizeof(pdata->ch[i]));
- error = sh_mobile_lcdc_check_interface(&priv->ch[i]);
+ error = sh_mobile_lcdc_check_interface(&priv->ch[j]);
if (error) {
dev_err(&pdev->dev, "unsupported interface type\n");
goto err1;
}
- init_waitqueue_head(&priv->ch[i].frame_end_wait);
- init_completion(&priv->ch[i].vsync_completion);
+ init_waitqueue_head(&priv->ch[j].frame_end_wait);
+ init_completion(&priv->ch[j].vsync_completion);
priv->ch[j].pan_offset = 0;
switch (pdata->ch[i].chan) {
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c
index ef7a7bd..cc039b3 100644
--- a/drivers/video/tcx.c
+++ b/drivers/video/tcx.c
@@ -365,7 +365,7 @@
static int __devinit tcx_probe(struct of_device *op,
const struct of_device_id *match)
{
- struct device_node *dp = op->node;
+ struct device_node *dp = op->dev.of_node;
struct fb_info *info;
struct tcx_par *par;
int linebytes, i, err;
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
index 95896f3..ef8d9d5 100644
--- a/drivers/virtio/virtio_pci.c
+++ b/drivers/virtio/virtio_pci.c
@@ -636,6 +636,9 @@
INIT_LIST_HEAD(&vp_dev->virtqueues);
spin_lock_init(&vp_dev->lock);
+ /* Disable MSI/MSIX to bring device to a known good state. */
+ pci_msi_off(pci_dev);
+
/* enable the device */
err = pci_enable_device(pci_dev);
if (err)
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 1ca8890..afe7e21 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -119,7 +119,7 @@
desc = kmalloc((out + in) * sizeof(struct vring_desc), gfp);
if (!desc)
- return vq->vring.num;
+ return -ENOMEM;
/* Transfer entries from the sg list into the indirect page */
for (i = 0; i < out; i++) {
diff --git a/drivers/watchdog/at32ap700x_wdt.c b/drivers/watchdog/at32ap700x_wdt.c
index 1cddf92..750bc52 100644
--- a/drivers/watchdog/at32ap700x_wdt.c
+++ b/drivers/watchdog/at32ap700x_wdt.c
@@ -346,9 +346,13 @@
} else {
wdt->users = 0;
}
- wdt->miscdev.minor = WATCHDOG_MINOR;
- wdt->miscdev.name = "watchdog";
- wdt->miscdev.fops = &at32_wdt_fops;
+
+ wdt->miscdev.minor = WATCHDOG_MINOR;
+ wdt->miscdev.name = "watchdog";
+ wdt->miscdev.fops = &at32_wdt_fops;
+ wdt->miscdev.parent = &pdev->dev;
+
+ platform_set_drvdata(pdev, wdt);
if (at32_wdt_settimeout(timeout)) {
at32_wdt_settimeout(TIMEOUT_DEFAULT);
@@ -360,17 +364,17 @@
ret = misc_register(&wdt->miscdev);
if (ret) {
dev_dbg(&pdev->dev, "failed to register wdt miscdev\n");
- goto err_iounmap;
+ goto err_register;
}
- platform_set_drvdata(pdev, wdt);
- wdt->miscdev.parent = &pdev->dev;
dev_info(&pdev->dev,
"AT32AP700X WDT at 0x%p, timeout %d sec (nowayout=%d)\n",
wdt->regs, wdt->timeout, nowayout);
return 0;
+err_register:
+ platform_set_drvdata(pdev, NULL);
err_iounmap:
iounmap(wdt->regs);
err_free:
diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c
index ca0f4c6..1df284f 100644
--- a/drivers/watchdog/gef_wdt.c
+++ b/drivers/watchdog/gef_wdt.c
@@ -273,7 +273,7 @@
bus_clk = freq;
/* Map devices registers into memory */
- gef_wdt_regs = of_iomap(dev->node, 0);
+ gef_wdt_regs = of_iomap(dev->dev.of_node, 0);
if (gef_wdt_regs == NULL)
return -ENOMEM;
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index ea25885..2ee7dac 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -330,7 +330,6 @@
}
static struct platform_driver imx2_wdt_driver = {
- .probe = imx2_wdt_probe,
.remove = __exit_p(imx2_wdt_remove),
.shutdown = imx2_wdt_shutdown,
.driver = {
diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c
index 6622335..4cda64d 100644
--- a/drivers/watchdog/mpc8xxx_wdt.c
+++ b/drivers/watchdog/mpc8xxx_wdt.c
@@ -189,7 +189,7 @@
const struct of_device_id *match)
{
int ret;
- struct device_node *np = ofdev->node;
+ struct device_node *np = ofdev->dev.of_node;
struct mpc8xxx_wdt_type *wdt_type = match->data;
u32 freq = fsl_get_sys_freq();
bool enabled;
diff --git a/drivers/watchdog/wm8350_wdt.c b/drivers/watchdog/wm8350_wdt.c
index 89dd7b0..b68d928 100644
--- a/drivers/watchdog/wm8350_wdt.c
+++ b/drivers/watchdog/wm8350_wdt.c
@@ -284,7 +284,7 @@
struct wm8350 *wm8350 = platform_get_drvdata(pdev);
if (!wm8350) {
- dev_err(wm8350->dev, "No driver data supplied\n");
+ pr_err("No driver data supplied\n");
return -ENODEV;
}
diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c
index eab33f1..7b547f5 100644
--- a/drivers/xen/xenbus/xenbus_xs.c
+++ b/drivers/xen/xenbus/xenbus_xs.c
@@ -499,7 +499,7 @@
#define PRINTF_BUFFER_SIZE 4096
char *printf_buffer;
- printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL);
+ printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_NOIO | __GFP_HIGH);
if (printf_buffer == NULL)
return -ENOMEM;
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index 49566c1..811384b 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -56,16 +56,19 @@
#endif
/*
- * User data (stack, data section and bss) needs to be aligned
- * for the same reasons as SLAB memory is, and to the same amount.
- * Avoid duplicating architecture specific code by using the same
- * macro as with SLAB allocation:
+ * User data (data section and bss) needs to be aligned.
+ * We pick 0x20 here because it is the max value elf2flt has always
+ * used in producing FLAT files, and because it seems to be large
+ * enough to make all the gcc alignment related tests happy.
*/
-#ifdef ARCH_SLAB_MINALIGN
-#define FLAT_DATA_ALIGN (ARCH_SLAB_MINALIGN)
-#else
-#define FLAT_DATA_ALIGN (sizeof(void *))
-#endif
+#define FLAT_DATA_ALIGN (0x20)
+
+/*
+ * User data (stack) also needs to be aligned.
+ * Here we can be a bit looser than the data sections since this
+ * needs to only meet arch ABI requirements.
+ */
+#define FLAT_STACK_ALIGN max_t(unsigned long, sizeof(void *), ARCH_SLAB_MINALIGN)
#define RELOC_FAILED 0xff00ff01 /* Relocation incorrect somewhere */
#define UNLOADED_LIB 0x7ff000ff /* Placeholder for unused library */
@@ -129,7 +132,7 @@
sp = (unsigned long *)p;
sp -= (envc + argc + 2) + 1 + (flat_argvp_envp_on_stack() ? 2 : 0);
- sp = (unsigned long *) ((unsigned long)sp & -FLAT_DATA_ALIGN);
+ sp = (unsigned long *) ((unsigned long)sp & -FLAT_STACK_ALIGN);
argv = sp + 1 + (flat_argvp_envp_on_stack() ? 2 : 0);
envp = argv + (argc + 1);
@@ -589,7 +592,7 @@
if (IS_ERR_VALUE(result)) {
printk("Unable to read data+bss, errno %d\n", (int)-result);
do_munmap(current->mm, textpos, text_len);
- do_munmap(current->mm, realdatastart, data_len + extra);
+ do_munmap(current->mm, realdatastart, len);
ret = result;
goto err;
}
@@ -876,7 +879,7 @@
stack_len = TOP_OF_ARGS - bprm->p; /* the strings */
stack_len += (bprm->argc + 1) * sizeof(char *); /* the argv array */
stack_len += (bprm->envc + 1) * sizeof(char *); /* the envp array */
- stack_len += FLAT_DATA_ALIGN - 1; /* reserve for upcoming alignment */
+ stack_len += FLAT_STACK_ALIGN - 1; /* reserve for upcoming alignment */
res = load_flat_file(bprm, &libinfo, 0, &stack_len);
if (IS_ERR_VALUE(res))
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 7346c96..99d6af8 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -706,8 +706,13 @@
* @bdev is about to be opened exclusively. Check @bdev can be opened
* exclusively and mark that an exclusive open is in progress. Each
* successful call to this function must be matched with a call to
- * either bd_claim() or bd_abort_claiming(). If this function
- * succeeds, the matching bd_claim() is guaranteed to succeed.
+ * either bd_finish_claiming() or bd_abort_claiming() (which do not
+ * fail).
+ *
+ * This function is used to gain exclusive access to the block device
+ * without actually causing other exclusive open attempts to fail. It
+ * should be used when the open sequence itself requires exclusive
+ * access but may subsequently fail.
*
* CONTEXT:
* Might sleep.
@@ -734,6 +739,7 @@
return ERR_PTR(-ENXIO);
whole = bdget_disk(disk, 0);
+ module_put(disk->fops->owner);
put_disk(disk);
if (!whole)
return ERR_PTR(-ENOMEM);
@@ -782,15 +788,46 @@
__bd_abort_claiming(whole, holder); /* releases bdev_lock */
}
+/* increment holders when we have a legitimate claim. requires bdev_lock */
+static void __bd_claim(struct block_device *bdev, struct block_device *whole,
+ void *holder)
+{
+ /* note that for a whole device bd_holders
+ * will be incremented twice, and bd_holder will
+ * be set to bd_claim before being set to holder
+ */
+ whole->bd_holders++;
+ whole->bd_holder = bd_claim;
+ bdev->bd_holders++;
+ bdev->bd_holder = holder;
+}
+
+/**
+ * bd_finish_claiming - finish claiming a block device
+ * @bdev: block device of interest (passed to bd_start_claiming())
+ * @whole: whole block device returned by bd_start_claiming()
+ * @holder: holder trying to claim @bdev
+ *
+ * Finish a claiming block started by bd_start_claiming().
+ *
+ * CONTEXT:
+ * Grabs and releases bdev_lock.
+ */
+static void bd_finish_claiming(struct block_device *bdev,
+ struct block_device *whole, void *holder)
+{
+ spin_lock(&bdev_lock);
+ BUG_ON(!bd_may_claim(bdev, whole, holder));
+ __bd_claim(bdev, whole, holder);
+ __bd_abort_claiming(whole, holder); /* not actually an abort */
+}
+
/**
* bd_claim - claim a block device
* @bdev: block device to claim
* @holder: holder trying to claim @bdev
*
- * Try to claim @bdev which must have been opened successfully. This
- * function may be called with or without preceding
- * blk_start_claiming(). In the former case, this function is always
- * successful and terminates the claiming block.
+ * Try to claim @bdev which must have been opened successfully.
*
* CONTEXT:
* Might sleep.
@@ -806,23 +843,10 @@
might_sleep();
spin_lock(&bdev_lock);
-
res = bd_prepare_to_claim(bdev, whole, holder);
- if (res == 0) {
- /* note that for a whole device bd_holders
- * will be incremented twice, and bd_holder will
- * be set to bd_claim before being set to holder
- */
- whole->bd_holders++;
- whole->bd_holder = bd_claim;
- bdev->bd_holders++;
- bdev->bd_holder = holder;
- }
-
- if (whole->bd_claiming)
- __bd_abort_claiming(whole, holder); /* releases bdev_lock */
- else
- spin_unlock(&bdev_lock);
+ if (res == 0)
+ __bd_claim(bdev, whole, holder);
+ spin_unlock(&bdev_lock);
return res;
}
@@ -1476,7 +1500,7 @@
if (whole) {
if (res == 0)
- BUG_ON(bd_claim(bdev, filp) != 0);
+ bd_finish_claiming(bdev, whole, filp);
else
bd_abort_claiming(whole, filp);
}
@@ -1712,7 +1736,7 @@
if ((mode & FMODE_WRITE) && bdev_read_only(bdev))
goto out_blkdev_put;
- BUG_ON(bd_claim(bdev, holder) != 0);
+ bd_finish_claiming(bdev, whole, holder);
return bdev;
out_blkdev_put:
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c
index 8d432cd..2222d16 100644
--- a/fs/btrfs/acl.c
+++ b/fs/btrfs/acl.c
@@ -60,6 +60,8 @@
size = __btrfs_getxattr(inode, name, value, size);
if (size > 0) {
acl = posix_acl_from_xattr(value, size);
+ if (IS_ERR(acl))
+ return acl;
set_cached_acl(inode, type, acl);
}
kfree(value);
@@ -160,6 +162,12 @@
int ret;
struct posix_acl *acl = NULL;
+ if (!is_owner_or_cap(dentry->d_inode))
+ return -EPERM;
+
+ if (!IS_POSIXACL(dentry->d_inode))
+ return -EOPNOTSUPP;
+
if (value) {
acl = posix_acl_from_xattr(value, size);
if (acl == NULL) {
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index f3b287c..34f7c37 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1941,8 +1941,11 @@
btrfs_level_size(tree_root,
btrfs_super_log_root_level(disk_super));
- log_tree_root = kzalloc(sizeof(struct btrfs_root),
- GFP_NOFS);
+ log_tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS);
+ if (!log_tree_root) {
+ err = -ENOMEM;
+ goto fail_trans_kthread;
+ }
__setup_root(nodesize, leafsize, sectorsize, stripesize,
log_tree_root, fs_info, BTRFS_TREE_LOG_OBJECTID);
@@ -1982,6 +1985,10 @@
fs_info->fs_root = btrfs_read_fs_root_no_name(fs_info, &location);
if (!fs_info->fs_root)
goto fail_trans_kthread;
+ if (IS_ERR(fs_info->fs_root)) {
+ err = PTR_ERR(fs_info->fs_root);
+ goto fail_trans_kthread;
+ }
if (!(sb->s_flags & MS_RDONLY)) {
down_read(&fs_info->cleanup_work_sem);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index b9080d7..32d0940 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -4360,7 +4360,8 @@
block_rsv = get_block_rsv(trans, root);
cache = btrfs_lookup_block_group(root->fs_info, buf->start);
- BUG_ON(block_rsv->space_info != cache->space_info);
+ if (block_rsv->space_info != cache->space_info)
+ goto out;
if (btrfs_header_generation(buf) == trans->transid) {
if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) {
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 787b50a..e354c33 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1140,7 +1140,7 @@
/*
* ok we haven't committed the transaction yet, lets do a commit
*/
- if (file && file->private_data)
+ if (file->private_data)
btrfs_ioctl_trans_end(file);
trans = btrfs_start_transaction(root, 0);
@@ -1190,14 +1190,22 @@
static int btrfs_file_mmap(struct file *filp, struct vm_area_struct *vma)
{
- vma->vm_ops = &btrfs_file_vm_ops;
+ struct address_space *mapping = filp->f_mapping;
+
+ if (!mapping->a_ops->readpage)
+ return -ENOEXEC;
+
file_accessed(filp);
+ vma->vm_ops = &btrfs_file_vm_ops;
+ vma->vm_flags |= VM_CAN_NONLINEAR;
+
return 0;
}
const struct file_operations btrfs_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
+ .write = do_sync_write,
.aio_read = generic_file_aio_read,
.splice_read = generic_file_splice_read,
.aio_write = btrfs_file_aio_write,
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index fa6ccc1..1bff92a 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2673,7 +2673,7 @@
struct extent_buffer *eb;
int level;
int ret;
- u64 refs;
+ u64 refs = 1;
for (level = 0; level < BTRFS_MAX_LEVEL; level++) {
if (!path->nodes[level])
@@ -6884,7 +6884,7 @@
if (em->block_start == EXTENT_MAP_HOLE ||
(cur_offset >= inode->i_size &&
!test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) {
- ret = btrfs_prealloc_file_range(inode, 0, cur_offset,
+ ret = btrfs_prealloc_file_range(inode, mode, cur_offset,
last_byte - cur_offset,
1 << inode->i_blkbits,
offset + len,
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 4cdb98c..4dbaf89 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1280,7 +1280,7 @@
trans = btrfs_start_transaction(root, 0);
if (IS_ERR(trans)) {
err = PTR_ERR(trans);
- goto out;
+ goto out_up_write;
}
trans->block_rsv = &root->fs_info->global_block_rsv;
@@ -1845,7 +1845,7 @@
dir_id = btrfs_super_root_dir(&root->fs_info->super_copy);
di = btrfs_lookup_dir_item(trans, root->fs_info->tree_root, path,
dir_id, "default", 7, 1);
- if (!di) {
+ if (IS_ERR_OR_NULL(di)) {
btrfs_free_path(path);
btrfs_end_transaction(trans, root);
printk(KERN_ERR "Umm, you don't have the default dir item, "
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 05d41e5..b37d723 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -784,16 +784,17 @@
struct btrfs_extent_ref_v0 *ref0;
ref0 = btrfs_item_ptr(eb, path1->slots[0],
struct btrfs_extent_ref_v0);
- root = find_tree_root(rc, eb, ref0);
- if (!root->ref_cows)
- cur->cowonly = 1;
if (key.objectid == key.offset) {
+ root = find_tree_root(rc, eb, ref0);
if (root && !should_ignore_root(root))
cur->root = root;
else
list_add(&cur->list, &useless);
break;
}
+ if (is_cowonly_root(btrfs_ref_root_v0(eb,
+ ref0)))
+ cur->cowonly = 1;
}
#else
BUG_ON(key.type == BTRFS_EXTENT_REF_V0_KEY);
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c
index b91ccd9..2d958be 100644
--- a/fs/btrfs/root-tree.c
+++ b/fs/btrfs/root-tree.c
@@ -330,7 +330,6 @@
{
struct btrfs_path *path;
int ret;
- u32 refs;
struct btrfs_root_item *ri;
struct extent_buffer *leaf;
@@ -344,8 +343,6 @@
leaf = path->nodes[0];
ri = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_item);
- refs = btrfs_disk_root_refs(leaf, ri);
- BUG_ON(refs != 0);
ret = btrfs_del_item(trans, root, path);
out:
btrfs_free_path(path);
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index d34b2df..f2393b3 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -360,6 +360,8 @@
*/
dir_id = btrfs_super_root_dir(&root->fs_info->super_copy);
di = btrfs_lookup_dir_item(NULL, root, path, dir_id, "default", 7, 0);
+ if (IS_ERR(di))
+ return ERR_CAST(di);
if (!di) {
/*
* Ok the default dir item isn't there. This is weird since
@@ -390,8 +392,8 @@
location.offset = 0;
inode = btrfs_iget(sb, &location, new_root, &new);
- if (!inode)
- return ERR_PTR(-ENOMEM);
+ if (IS_ERR(inode))
+ return ERR_CAST(inode);
/*
* If we're just mounting the root most subvol put the inode and return
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index ae3e3a3..619b616 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -981,6 +981,46 @@
return 0;
}
+static void __queue_cap_release(struct ceph_mds_session *session,
+ u64 ino, u64 cap_id, u32 migrate_seq,
+ u32 issue_seq)
+{
+ struct ceph_msg *msg;
+ struct ceph_mds_cap_release *head;
+ struct ceph_mds_cap_item *item;
+
+ spin_lock(&session->s_cap_lock);
+ BUG_ON(!session->s_num_cap_releases);
+ msg = list_first_entry(&session->s_cap_releases,
+ struct ceph_msg, list_head);
+
+ dout(" adding %llx release to mds%d msg %p (%d left)\n",
+ ino, session->s_mds, msg, session->s_num_cap_releases);
+
+ BUG_ON(msg->front.iov_len + sizeof(*item) > PAGE_CACHE_SIZE);
+ head = msg->front.iov_base;
+ head->num = cpu_to_le32(le32_to_cpu(head->num) + 1);
+ item = msg->front.iov_base + msg->front.iov_len;
+ item->ino = cpu_to_le64(ino);
+ item->cap_id = cpu_to_le64(cap_id);
+ item->migrate_seq = cpu_to_le32(migrate_seq);
+ item->seq = cpu_to_le32(issue_seq);
+
+ session->s_num_cap_releases--;
+
+ msg->front.iov_len += sizeof(*item);
+ if (le32_to_cpu(head->num) == CEPH_CAPS_PER_RELEASE) {
+ dout(" release msg %p full\n", msg);
+ list_move_tail(&msg->list_head, &session->s_cap_releases_done);
+ } else {
+ dout(" release msg %p at %d/%d (%d)\n", msg,
+ (int)le32_to_cpu(head->num),
+ (int)CEPH_CAPS_PER_RELEASE,
+ (int)msg->front.iov_len);
+ }
+ spin_unlock(&session->s_cap_lock);
+}
+
/*
* Queue cap releases when an inode is dropped from our cache. Since
* inode is about to be destroyed, there is no need for i_lock.
@@ -994,41 +1034,9 @@
while (p) {
struct ceph_cap *cap = rb_entry(p, struct ceph_cap, ci_node);
struct ceph_mds_session *session = cap->session;
- struct ceph_msg *msg;
- struct ceph_mds_cap_release *head;
- struct ceph_mds_cap_item *item;
- spin_lock(&session->s_cap_lock);
- BUG_ON(!session->s_num_cap_releases);
- msg = list_first_entry(&session->s_cap_releases,
- struct ceph_msg, list_head);
-
- dout(" adding %p release to mds%d msg %p (%d left)\n",
- inode, session->s_mds, msg, session->s_num_cap_releases);
-
- BUG_ON(msg->front.iov_len + sizeof(*item) > PAGE_CACHE_SIZE);
- head = msg->front.iov_base;
- head->num = cpu_to_le32(le32_to_cpu(head->num) + 1);
- item = msg->front.iov_base + msg->front.iov_len;
- item->ino = cpu_to_le64(ceph_ino(inode));
- item->cap_id = cpu_to_le64(cap->cap_id);
- item->migrate_seq = cpu_to_le32(cap->mseq);
- item->seq = cpu_to_le32(cap->issue_seq);
-
- session->s_num_cap_releases--;
-
- msg->front.iov_len += sizeof(*item);
- if (le32_to_cpu(head->num) == CEPH_CAPS_PER_RELEASE) {
- dout(" release msg %p full\n", msg);
- list_move_tail(&msg->list_head,
- &session->s_cap_releases_done);
- } else {
- dout(" release msg %p at %d/%d (%d)\n", msg,
- (int)le32_to_cpu(head->num),
- (int)CEPH_CAPS_PER_RELEASE,
- (int)msg->front.iov_len);
- }
- spin_unlock(&session->s_cap_lock);
+ __queue_cap_release(session, ceph_ino(inode), cap->cap_id,
+ cap->mseq, cap->issue_seq);
p = rb_next(p);
__ceph_remove_cap(cap);
}
@@ -2655,7 +2663,7 @@
struct ceph_mds_caps *h;
int mds = session->s_mds;
int op;
- u32 seq;
+ u32 seq, mseq;
struct ceph_vino vino;
u64 cap_id;
u64 size, max_size;
@@ -2675,6 +2683,7 @@
vino.snap = CEPH_NOSNAP;
cap_id = le64_to_cpu(h->cap_id);
seq = le32_to_cpu(h->seq);
+ mseq = le32_to_cpu(h->migrate_seq);
size = le64_to_cpu(h->size);
max_size = le64_to_cpu(h->max_size);
@@ -2689,6 +2698,18 @@
vino.snap, inode);
if (!inode) {
dout(" i don't have ino %llx\n", vino.ino);
+
+ if (op == CEPH_CAP_OP_IMPORT)
+ __queue_cap_release(session, vino.ino, cap_id,
+ mseq, seq);
+
+ /*
+ * send any full release message to try to move things
+ * along for the mds (who clearly thinks we still have this
+ * cap).
+ */
+ ceph_add_cap_releases(mdsc, session, -1);
+ ceph_send_cap_releases(mdsc, session);
goto done;
}
@@ -2714,7 +2735,7 @@
spin_lock(&inode->i_lock);
cap = __get_cap_for_mds(ceph_inode(inode), mds);
if (!cap) {
- dout("no cap on %p ino %llx.%llx from mds%d, releasing\n",
+ dout(" no cap on %p ino %llx.%llx from mds%d\n",
inode, ceph_ino(inode), ceph_snap(inode), mds);
spin_unlock(&inode->i_lock);
goto done;
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 226f5a5..ab47f46 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -827,7 +827,7 @@
spin_lock(&dcache_lock);
spin_lock(&dn->d_lock);
- list_move_tail(&dir->d_subdirs, &dn->d_u.d_child);
+ list_move(&dn->d_u.d_child, &dir->d_subdirs);
dout("set_dentry_offset %p %lld (%p %p)\n", dn, di->offset,
dn->d_u.d_child.prev, dn->d_u.d_child.next);
spin_unlock(&dn->d_lock);
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index b49f128..1766947 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -1066,9 +1066,9 @@
*
* Called under s_mutex.
*/
-static int add_cap_releases(struct ceph_mds_client *mdsc,
- struct ceph_mds_session *session,
- int extra)
+int ceph_add_cap_releases(struct ceph_mds_client *mdsc,
+ struct ceph_mds_session *session,
+ int extra)
{
struct ceph_msg *msg;
struct ceph_mds_cap_release *head;
@@ -1176,8 +1176,8 @@
/*
* called under s_mutex
*/
-static void send_cap_releases(struct ceph_mds_client *mdsc,
- struct ceph_mds_session *session)
+void ceph_send_cap_releases(struct ceph_mds_client *mdsc,
+ struct ceph_mds_session *session)
{
struct ceph_msg *msg;
@@ -1980,7 +1980,7 @@
}
mutex_unlock(&mdsc->mutex);
- add_cap_releases(mdsc, req->r_session, -1);
+ ceph_add_cap_releases(mdsc, req->r_session, -1);
mutex_unlock(&session->s_mutex);
/* kick calling process */
@@ -2433,6 +2433,7 @@
struct ceph_dentry_info *di;
int mds = session->s_mds;
struct ceph_mds_lease *h = msg->front.iov_base;
+ u32 seq;
struct ceph_vino vino;
int mask;
struct qstr dname;
@@ -2446,6 +2447,7 @@
vino.ino = le64_to_cpu(h->ino);
vino.snap = CEPH_NOSNAP;
mask = le16_to_cpu(h->mask);
+ seq = le32_to_cpu(h->seq);
dname.name = (void *)h + sizeof(*h) + sizeof(u32);
dname.len = msg->front.iov_len - sizeof(*h) - sizeof(u32);
if (dname.len != get_unaligned_le32(h+1))
@@ -2456,8 +2458,9 @@
/* lookup inode */
inode = ceph_find_inode(sb, vino);
- dout("handle_lease '%s', mask %d, ino %llx %p\n",
- ceph_lease_op_name(h->action), mask, vino.ino, inode);
+ dout("handle_lease %s, mask %d, ino %llx %p %.*s\n",
+ ceph_lease_op_name(h->action), mask, vino.ino, inode,
+ dname.len, dname.name);
if (inode == NULL) {
dout("handle_lease no inode %llx\n", vino.ino);
goto release;
@@ -2482,7 +2485,8 @@
switch (h->action) {
case CEPH_MDS_LEASE_REVOKE:
if (di && di->lease_session == session) {
- h->seq = cpu_to_le32(di->lease_seq);
+ if (ceph_seq_cmp(di->lease_seq, seq) > 0)
+ h->seq = cpu_to_le32(di->lease_seq);
__ceph_mdsc_drop_dentry_lease(dentry);
}
release = 1;
@@ -2496,7 +2500,7 @@
unsigned long duration =
le32_to_cpu(h->duration_ms) * HZ / 1000;
- di->lease_seq = le32_to_cpu(h->seq);
+ di->lease_seq = seq;
dentry->d_time = di->lease_renew_from + duration;
di->lease_renew_after = di->lease_renew_from +
(duration >> 1);
@@ -2686,10 +2690,10 @@
send_renew_caps(mdsc, s);
else
ceph_con_keepalive(&s->s_con);
- add_cap_releases(mdsc, s, -1);
+ ceph_add_cap_releases(mdsc, s, -1);
if (s->s_state == CEPH_MDS_SESSION_OPEN ||
s->s_state == CEPH_MDS_SESSION_HUNG)
- send_cap_releases(mdsc, s);
+ ceph_send_cap_releases(mdsc, s);
mutex_unlock(&s->s_mutex);
ceph_put_mds_session(s);
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
index d9936c4..b292fa4 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -322,6 +322,12 @@
kref_put(&req->r_kref, ceph_mdsc_release_request);
}
+extern int ceph_add_cap_releases(struct ceph_mds_client *mdsc,
+ struct ceph_mds_session *session,
+ int extra);
+extern void ceph_send_cap_releases(struct ceph_mds_client *mdsc,
+ struct ceph_mds_session *session);
+
extern void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc);
extern char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *base,
diff --git a/fs/ceph/mon_client.c b/fs/ceph/mon_client.c
index 21c62e9..07a5399 100644
--- a/fs/ceph/mon_client.c
+++ b/fs/ceph/mon_client.c
@@ -400,6 +400,8 @@
ceph_msg_put(req->reply);
if (req->request)
ceph_msg_put(req->request);
+
+ kfree(req);
}
static void put_generic_request(struct ceph_mon_generic_request *req)
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index 4e0bee2..fa87f51 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -89,7 +89,7 @@
buf->f_files = le64_to_cpu(st.num_objects);
buf->f_ffree = -1;
- buf->f_namelen = PATH_MAX;
+ buf->f_namelen = NAME_MAX;
buf->f_frsize = PAGE_CACHE_SIZE;
/* leave fsid little-endian, regardless of host endianness */
@@ -926,7 +926,7 @@
/*
* construct our own bdi so we can control readahead, etc.
*/
-static atomic_long_t bdi_seq = ATOMIC_INIT(0);
+static atomic_long_t bdi_seq = ATOMIC_LONG_INIT(0);
static int ceph_register_bdi(struct super_block *sb, struct ceph_client *client)
{
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 78c02eb..484e52b 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -473,14 +473,24 @@
return 0;
}
+void cifs_drop_inode(struct inode *inode)
+{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
+ return generic_drop_inode(inode);
+
+ return generic_delete_inode(inode);
+}
+
static const struct super_operations cifs_super_ops = {
.put_super = cifs_put_super,
.statfs = cifs_statfs,
.alloc_inode = cifs_alloc_inode,
.destroy_inode = cifs_destroy_inode,
-/* .drop_inode = generic_delete_inode,
- .delete_inode = cifs_delete_inode, */ /* Do not need above two
- functions unless later we add lazy close of inodes or unless the
+ .drop_inode = cifs_drop_inode,
+/* .delete_inode = cifs_delete_inode, */ /* Do not need above
+ function unless later we add lazy close of inodes or unless the
kernel forgets to call us with the same number of releases (closes)
as opens */
.show_options = cifs_show_options,
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index fb1657e..fb6318b 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -106,7 +106,6 @@
__u16 fileHandle, struct file *file,
struct vfsmount *mnt, unsigned int oflags);
extern int cifs_posix_open(char *full_path, struct inode **pinode,
- struct vfsmount *mnt,
struct super_block *sb,
int mode, int oflags,
__u32 *poplock, __u16 *pnetfid, int xid);
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 391816b..e7ae78b 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -25,6 +25,7 @@
#include <linux/slab.h>
#include <linux/namei.h>
#include <linux/mount.h>
+#include <linux/file.h>
#include "cifsfs.h"
#include "cifspdu.h"
#include "cifsglob.h"
@@ -184,12 +185,13 @@
}
write_unlock(&GlobalSMBSeslock);
+ file->private_data = pCifsFile;
+
return pCifsFile;
}
int cifs_posix_open(char *full_path, struct inode **pinode,
- struct vfsmount *mnt, struct super_block *sb,
- int mode, int oflags,
+ struct super_block *sb, int mode, int oflags,
__u32 *poplock, __u16 *pnetfid, int xid)
{
int rc;
@@ -258,19 +260,6 @@
cifs_fattr_to_inode(*pinode, &fattr);
}
- /*
- * cifs_fill_filedata() takes care of setting cifsFileInfo pointer to
- * file->private_data.
- */
- if (mnt) {
- struct cifsFileInfo *pfile_info;
-
- pfile_info = cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt,
- oflags);
- if (pfile_info == NULL)
- rc = -ENOMEM;
- }
-
posix_open_ret:
kfree(presp_data);
return rc;
@@ -298,7 +287,6 @@
int create_options = CREATE_NOT_DIR;
__u32 oplock = 0;
int oflags;
- bool posix_create = false;
/*
* BB below access is probably too much for mknod to request
* but we have to do query and setpathinfo so requesting
@@ -339,7 +327,6 @@
(CIFS_UNIX_POSIX_PATH_OPS_CAP &
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
rc = cifs_posix_open(full_path, &newinode,
- nd ? nd->path.mnt : NULL,
inode->i_sb, mode, oflags, &oplock, &fileHandle, xid);
/* EIO could indicate that (posix open) operation is not
supported, despite what server claimed in capability
@@ -347,7 +334,6 @@
handled in posix open */
if (rc == 0) {
- posix_create = true;
if (newinode == NULL) /* query inode info */
goto cifs_create_get_file_info;
else /* success, no need to query */
@@ -478,21 +464,28 @@
else
cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);
- /* nfsd case - nfs srv does not set nd */
- if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) {
- /* mknod case - do not leave file open */
- CIFSSMBClose(xid, tcon, fileHandle);
- } else if (!(posix_create) && (newinode)) {
+ if (newinode && nd && (nd->flags & LOOKUP_OPEN)) {
struct cifsFileInfo *pfile_info;
- /*
- * cifs_fill_filedata() takes care of setting cifsFileInfo
- * pointer to file->private_data.
- */
- pfile_info = cifs_new_fileinfo(newinode, fileHandle, NULL,
+ struct file *filp;
+
+ filp = lookup_instantiate_filp(nd, direntry, generic_file_open);
+ if (IS_ERR(filp)) {
+ rc = PTR_ERR(filp);
+ CIFSSMBClose(xid, tcon, fileHandle);
+ goto cifs_create_out;
+ }
+
+ pfile_info = cifs_new_fileinfo(newinode, fileHandle, filp,
nd->path.mnt, oflags);
- if (pfile_info == NULL)
+ if (pfile_info == NULL) {
+ fput(filp);
+ CIFSSMBClose(xid, tcon, fileHandle);
rc = -ENOMEM;
+ }
+ } else {
+ CIFSSMBClose(xid, tcon, fileHandle);
}
+
cifs_create_out:
kfree(buf);
kfree(full_path);
@@ -636,6 +629,7 @@
bool posix_open = false;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
+ struct cifsFileInfo *cfile;
struct inode *newInode = NULL;
char *full_path = NULL;
struct file *filp;
@@ -703,7 +697,7 @@
if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
(nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
(nd->intent.open.flags & O_CREAT)) {
- rc = cifs_posix_open(full_path, &newInode, nd->path.mnt,
+ rc = cifs_posix_open(full_path, &newInode,
parent_dir_inode->i_sb,
nd->intent.open.create_mode,
nd->intent.open.flags, &oplock,
@@ -733,8 +727,25 @@
else
direntry->d_op = &cifs_dentry_ops;
d_add(direntry, newInode);
- if (posix_open)
- filp = lookup_instantiate_filp(nd, direntry, NULL);
+ if (posix_open) {
+ filp = lookup_instantiate_filp(nd, direntry,
+ generic_file_open);
+ if (IS_ERR(filp)) {
+ rc = PTR_ERR(filp);
+ CIFSSMBClose(xid, pTcon, fileHandle);
+ goto lookup_out;
+ }
+
+ cfile = cifs_new_fileinfo(newInode, fileHandle, filp,
+ nd->path.mnt,
+ nd->intent.open.flags);
+ if (cfile == NULL) {
+ fput(filp);
+ CIFSSMBClose(xid, pTcon, fileHandle);
+ rc = -ENOMEM;
+ goto lookup_out;
+ }
+ }
/* since paths are not looked up by component - the parent
directories are presumed to be good here */
renew_parental_timestamps(direntry);
@@ -755,6 +766,7 @@
is a common return code */
}
+lookup_out:
kfree(full_path);
FreeXid(xid);
return ERR_PTR(rc);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index f1ff785..409e4f5 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -162,44 +162,12 @@
return 0;
}
-static struct cifsFileInfo *
-cifs_fill_filedata(struct file *file)
-{
- struct list_head *tmp;
- struct cifsFileInfo *pCifsFile = NULL;
- struct cifsInodeInfo *pCifsInode = NULL;
-
- /* search inode for this file and fill in file->private_data */
- pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
- read_lock(&GlobalSMBSeslock);
- list_for_each(tmp, &pCifsInode->openFileList) {
- pCifsFile = list_entry(tmp, struct cifsFileInfo, flist);
- if ((pCifsFile->pfile == NULL) &&
- (pCifsFile->pid == current->tgid)) {
- /* mode set in cifs_create */
-
- /* needed for writepage */
- pCifsFile->pfile = file;
- file->private_data = pCifsFile;
- break;
- }
- }
- read_unlock(&GlobalSMBSeslock);
-
- if (file->private_data != NULL) {
- return pCifsFile;
- } else if ((file->f_flags & O_CREAT) && (file->f_flags & O_EXCL))
- cERROR(1, "could not find file instance for "
- "new file %p", file);
- return NULL;
-}
-
/* all arguments to this function must be checked for validity in caller */
-static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
- struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile,
+static inline int cifs_open_inode_helper(struct inode *inode,
struct cifsTconInfo *pTcon, int *oplock, FILE_ALL_INFO *buf,
char *full_path, int xid)
{
+ struct cifsInodeInfo *pCifsInode = CIFS_I(inode);
struct timespec temp;
int rc;
@@ -213,36 +181,35 @@
/* if not oplocked, invalidate inode pages if mtime or file
size changed */
temp = cifs_NTtimeToUnix(buf->LastWriteTime);
- if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) &&
- (file->f_path.dentry->d_inode->i_size ==
+ if (timespec_equal(&inode->i_mtime, &temp) &&
+ (inode->i_size ==
(loff_t)le64_to_cpu(buf->EndOfFile))) {
cFYI(1, "inode unchanged on server");
} else {
- if (file->f_path.dentry->d_inode->i_mapping) {
+ if (inode->i_mapping) {
/* BB no need to lock inode until after invalidate
since namei code should already have it locked? */
- rc = filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping);
+ rc = filemap_write_and_wait(inode->i_mapping);
if (rc != 0)
- CIFS_I(file->f_path.dentry->d_inode)->write_behind_rc = rc;
+ pCifsInode->write_behind_rc = rc;
}
cFYI(1, "invalidating remote inode since open detected it "
"changed");
- invalidate_remote_inode(file->f_path.dentry->d_inode);
+ invalidate_remote_inode(inode);
}
client_can_cache:
if (pTcon->unix_ext)
- rc = cifs_get_inode_info_unix(&file->f_path.dentry->d_inode,
- full_path, inode->i_sb, xid);
+ rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
+ xid);
else
- rc = cifs_get_inode_info(&file->f_path.dentry->d_inode,
- full_path, buf, inode->i_sb, xid, NULL);
+ rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
+ xid, NULL);
if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) {
pCifsInode->clientCanCacheAll = true;
pCifsInode->clientCanCacheRead = true;
- cFYI(1, "Exclusive Oplock granted on inode %p",
- file->f_path.dentry->d_inode);
+ cFYI(1, "Exclusive Oplock granted on inode %p", inode);
} else if ((*oplock & 0xF) == OPLOCK_READ)
pCifsInode->clientCanCacheRead = true;
@@ -256,7 +223,7 @@
__u32 oplock;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *tcon;
- struct cifsFileInfo *pCifsFile;
+ struct cifsFileInfo *pCifsFile = NULL;
struct cifsInodeInfo *pCifsInode;
char *full_path = NULL;
int desiredAccess;
@@ -270,12 +237,6 @@
tcon = cifs_sb->tcon;
pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
- pCifsFile = cifs_fill_filedata(file);
- if (pCifsFile) {
- rc = 0;
- FreeXid(xid);
- return rc;
- }
full_path = build_path_from_dentry(file->f_path.dentry);
if (full_path == NULL) {
@@ -299,8 +260,7 @@
int oflags = (int) cifs_posix_convert_flags(file->f_flags);
oflags |= SMB_O_CREAT;
/* can not refresh inode info since size could be stale */
- rc = cifs_posix_open(full_path, &inode, file->f_path.mnt,
- inode->i_sb,
+ rc = cifs_posix_open(full_path, &inode, inode->i_sb,
cifs_sb->mnt_file_mode /* ignored */,
oflags, &oplock, &netfid, xid);
if (rc == 0) {
@@ -308,9 +268,20 @@
/* no need for special case handling of setting mode
on read only files needed here */
- pCifsFile = cifs_fill_filedata(file);
- cifs_posix_open_inode_helper(inode, file, pCifsInode,
- oplock, netfid);
+ rc = cifs_posix_open_inode_helper(inode, file,
+ pCifsInode, oplock, netfid);
+ if (rc != 0) {
+ CIFSSMBClose(xid, tcon, netfid);
+ goto out;
+ }
+
+ pCifsFile = cifs_new_fileinfo(inode, netfid, file,
+ file->f_path.mnt,
+ oflags);
+ if (pCifsFile == NULL) {
+ CIFSSMBClose(xid, tcon, netfid);
+ rc = -ENOMEM;
+ }
goto out;
} else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
if (tcon->ses->serverNOS)
@@ -391,17 +362,17 @@
goto out;
}
+ rc = cifs_open_inode_helper(inode, tcon, &oplock, buf, full_path, xid);
+ if (rc != 0)
+ goto out;
+
pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt,
file->f_flags);
- file->private_data = pCifsFile;
- if (file->private_data == NULL) {
+ if (pCifsFile == NULL) {
rc = -ENOMEM;
goto out;
}
- rc = cifs_open_inode_helper(inode, file, pCifsInode, pCifsFile, tcon,
- &oplock, buf, full_path, xid);
-
if (oplock & CIFS_CREATE_ACTION) {
/* time to set mode which we can not set earlier due to
problems creating new read-only files */
@@ -513,8 +484,7 @@
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
int oflags = (int) cifs_posix_convert_flags(file->f_flags);
/* can not refresh inode info since size could be stale */
- rc = cifs_posix_open(full_path, NULL, file->f_path.mnt,
- inode->i_sb,
+ rc = cifs_posix_open(full_path, NULL, inode->i_sb,
cifs_sb->mnt_file_mode /* ignored */,
oflags, &oplock, &netfid, xid);
if (rc == 0) {
@@ -1952,6 +1922,7 @@
bytes_read -= PAGE_CACHE_SIZE;
continue;
}
+ page_cache_release(page);
target = kmap_atomic(page, KM_USER0);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 62b324f..6f0683c 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1401,6 +1401,10 @@
if (rc == 0 || rc != -ETXTBSY)
return rc;
+ /* open-file renames don't work across directories */
+ if (to_dentry->d_parent != from_dentry->d_parent)
+ return rc;
+
/* open the file to be renamed -- we need DELETE perms */
rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE,
CREATE_NOT_DIR, &srcfid, &oplock, NULL,
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 7707389..0a57cb7 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -730,15 +730,7 @@
/* calculate session key */
setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
- if (first_time) /* should this be moved into common code
- with similar ntlmv2 path? */
- /* cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key,
- response BB FIXME, v2_sess_key); */
-
- /* copy session key */
-
- /* memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE);
- bcc_ptr += LM2_SESS_KEY_SIZE; */
+ /* FIXME: calculate MAC key */
memcpy(bcc_ptr, (char *)v2_sess_key,
sizeof(struct ntlmv2_resp));
bcc_ptr += sizeof(struct ntlmv2_resp);
diff --git a/fs/compat.c b/fs/compat.c
index f0b391c..6490d21 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -626,7 +626,7 @@
tot_len += len;
if (tot_len < tmp) /* maths overflow on the compat_ssize_t */
goto out;
- if (!access_ok(vrfy_dir(type), buf, len)) {
+ if (!access_ok(vrfy_dir(type), compat_ptr(buf), len)) {
ret = -EFAULT;
goto out;
}
diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c
index 4164514..cf78d44 100644
--- a/fs/configfs/inode.c
+++ b/fs/configfs/inode.c
@@ -72,10 +72,6 @@
if (!sd)
return -EINVAL;
- error = simple_setattr(dentry, iattr);
- if (error)
- return error;
-
sd_iattr = sd->s_iattr;
if (!sd_iattr) {
/* setting attributes for the first time, allocate now */
@@ -89,9 +85,12 @@
sd_iattr->ia_atime = sd_iattr->ia_mtime = sd_iattr->ia_ctime = CURRENT_TIME;
sd->s_iattr = sd_iattr;
}
-
/* attributes were changed atleast once in past */
+ error = simple_setattr(dentry, iattr);
+ if (error)
+ return error;
+
if (ia_valid & ATTR_UID)
sd_iattr->ia_uid = iattr->ia_uid;
if (ia_valid & ATTR_GID)
diff --git a/fs/dcache.c b/fs/dcache.c
index d96047b..c8c78ba 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -590,6 +590,8 @@
up_read(&sb->s_umount);
}
spin_lock(&sb_lock);
+ /* lock was dropped, must reset next */
+ list_safe_reset_next(sb, n, s_list);
count -= pruned;
__put_super(sb);
/* more work left to do? */
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index ca7e2a0..2bcc043 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -200,6 +200,7 @@
return error;
else {
inode->i_mode = mode;
+ inode->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(inode);
if (error == 0)
acl = NULL;
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 1921443..3675088 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -1552,7 +1552,7 @@
if (error)
return error;
}
- if (iattr->ia_valid & ATTR_SIZE) {
+ if (iattr->ia_valid & ATTR_SIZE && iattr->ia_size != inode->i_size) {
error = ext2_setsize(inode, iattr->ia_size);
if (error)
return error;
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index 01552ab..8a11fe2 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -205,6 +205,7 @@
return error;
else {
inode->i_mode = mode;
+ inode->i_ctime = CURRENT_TIME_SEC;
ext3_mark_inode_dirty(handle, inode);
if (error == 0)
acl = NULL;
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 19df61c..42272d6 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -4942,20 +4942,26 @@
/* Propagate flags from i_flags to EXT4_I(inode)->i_flags */
void ext4_get_inode_flags(struct ext4_inode_info *ei)
{
- unsigned int flags = ei->vfs_inode.i_flags;
+ unsigned int vfs_fl;
+ unsigned long old_fl, new_fl;
- ei->i_flags &= ~(EXT4_SYNC_FL|EXT4_APPEND_FL|
- EXT4_IMMUTABLE_FL|EXT4_NOATIME_FL|EXT4_DIRSYNC_FL);
- if (flags & S_SYNC)
- ei->i_flags |= EXT4_SYNC_FL;
- if (flags & S_APPEND)
- ei->i_flags |= EXT4_APPEND_FL;
- if (flags & S_IMMUTABLE)
- ei->i_flags |= EXT4_IMMUTABLE_FL;
- if (flags & S_NOATIME)
- ei->i_flags |= EXT4_NOATIME_FL;
- if (flags & S_DIRSYNC)
- ei->i_flags |= EXT4_DIRSYNC_FL;
+ do {
+ vfs_fl = ei->vfs_inode.i_flags;
+ old_fl = ei->i_flags;
+ new_fl = old_fl & ~(EXT4_SYNC_FL|EXT4_APPEND_FL|
+ EXT4_IMMUTABLE_FL|EXT4_NOATIME_FL|
+ EXT4_DIRSYNC_FL);
+ if (vfs_fl & S_SYNC)
+ new_fl |= EXT4_SYNC_FL;
+ if (vfs_fl & S_APPEND)
+ new_fl |= EXT4_APPEND_FL;
+ if (vfs_fl & S_IMMUTABLE)
+ new_fl |= EXT4_IMMUTABLE_FL;
+ if (vfs_fl & S_NOATIME)
+ new_fl |= EXT4_NOATIME_FL;
+ if (vfs_fl & S_DIRSYNC)
+ new_fl |= EXT4_DIRSYNC_FL;
+ } while (cmpxchg(&ei->i_flags, old_fl, new_fl) != old_fl);
}
static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode,
@@ -5191,7 +5197,7 @@
*/
raw_inode->i_blocks_lo = cpu_to_le32(i_blocks);
raw_inode->i_blocks_high = 0;
- ei->i_flags &= ~EXT4_HUGE_FILE_FL;
+ ext4_clear_inode_flag(inode, EXT4_INODE_HUGE_FILE);
return 0;
}
if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE))
@@ -5204,9 +5210,9 @@
*/
raw_inode->i_blocks_lo = cpu_to_le32(i_blocks);
raw_inode->i_blocks_high = cpu_to_le16(i_blocks >> 32);
- ei->i_flags &= ~EXT4_HUGE_FILE_FL;
+ ext4_clear_inode_flag(inode, EXT4_INODE_HUGE_FILE);
} else {
- ei->i_flags |= EXT4_HUGE_FILE_FL;
+ ext4_set_inode_flag(inode, EXT4_INODE_HUGE_FILE);
/* i_block is stored in file system block size */
i_blocks = i_blocks >> (inode->i_blkbits - 9);
raw_inode->i_blocks_lo = cpu_to_le32(i_blocks);
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
index 3a6c92a..52abfa1 100644
--- a/fs/ext4/move_extent.c
+++ b/fs/ext4/move_extent.c
@@ -960,6 +960,9 @@
return -EINVAL;
}
+ if (IS_IMMUTABLE(donor_inode) || IS_APPEND(donor_inode))
+ return -EPERM;
+
/* Ext4 move extent does not support swapfile */
if (IS_SWAPFILE(orig_inode) || IS_SWAPFILE(donor_inode)) {
ext4_debug("ext4 move extent: The argument files should "
diff --git a/fs/fcntl.c b/fs/fcntl.c
index f74d270..9d175d6 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -274,7 +274,7 @@
ret = copy_from_user(&owner, owner_p, sizeof(owner));
if (ret)
- return ret;
+ return -EFAULT;
switch (owner.type) {
case F_OWNER_TID:
@@ -332,8 +332,11 @@
}
read_unlock(&filp->f_owner.lock);
- if (!ret)
+ if (!ret) {
ret = copy_to_user(owner_p, &owner, sizeof(owner));
+ if (ret)
+ ret = -EFAULT;
+ }
return ret;
}
@@ -730,12 +733,14 @@
{
while (fa) {
struct fown_struct *fown;
+ unsigned long flags;
+
if (fa->magic != FASYNC_MAGIC) {
printk(KERN_ERR "kill_fasync: bad magic number in "
"fasync_struct!\n");
return;
}
- spin_lock(&fa->fa_lock);
+ spin_lock_irqsave(&fa->fa_lock, flags);
if (fa->fa_file) {
fown = &fa->fa_file->f_owner;
/* Don't send SIGURG to processes which have not set a
@@ -744,7 +749,7 @@
if (!(sig == SIGURG && fown->signum == 0))
send_sigio(fown, fa->fa_fd, band);
}
- spin_unlock(&fa->fa_lock);
+ spin_unlock_irqrestore(&fa->fa_lock, flags);
fa = rcu_dereference(fa->fa_next);
}
}
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index ea8592b..0609607 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -45,7 +45,6 @@
unsigned int for_kupdate:1;
unsigned int range_cyclic:1;
unsigned int for_background:1;
- unsigned int sb_pinned:1;
};
/*
@@ -64,24 +63,16 @@
};
enum {
- WS_USED_B = 0,
- WS_ONSTACK_B,
+ WS_INPROGRESS = 0,
+ WS_ONSTACK,
};
-#define WS_USED (1 << WS_USED_B)
-#define WS_ONSTACK (1 << WS_ONSTACK_B)
-
-static inline bool bdi_work_on_stack(struct bdi_work *work)
-{
- return test_bit(WS_ONSTACK_B, &work->state);
-}
-
static inline void bdi_work_init(struct bdi_work *work,
struct wb_writeback_args *args)
{
INIT_RCU_HEAD(&work->rcu_head);
work->args = *args;
- work->state = WS_USED;
+ __set_bit(WS_INPROGRESS, &work->state);
}
/**
@@ -96,43 +87,16 @@
return !list_empty(&bdi->work_list);
}
-static void bdi_work_clear(struct bdi_work *work)
-{
- clear_bit(WS_USED_B, &work->state);
- smp_mb__after_clear_bit();
- /*
- * work can have disappeared at this point. bit waitq functions
- * should be able to tolerate this, provided bdi_sched_wait does
- * not dereference it's pointer argument.
- */
- wake_up_bit(&work->state, WS_USED_B);
-}
-
static void bdi_work_free(struct rcu_head *head)
{
struct bdi_work *work = container_of(head, struct bdi_work, rcu_head);
- if (!bdi_work_on_stack(work))
+ clear_bit(WS_INPROGRESS, &work->state);
+ smp_mb__after_clear_bit();
+ wake_up_bit(&work->state, WS_INPROGRESS);
+
+ if (!test_bit(WS_ONSTACK, &work->state))
kfree(work);
- else
- bdi_work_clear(work);
-}
-
-static void wb_work_complete(struct bdi_work *work)
-{
- const enum writeback_sync_modes sync_mode = work->args.sync_mode;
- int onstack = bdi_work_on_stack(work);
-
- /*
- * For allocated work, we can clear the done/seen bit right here.
- * For on-stack work, we need to postpone both the clear and free
- * to after the RCU grace period, since the stack could be invalidated
- * as soon as bdi_work_clear() has done the wakeup.
- */
- if (!onstack)
- bdi_work_clear(work);
- if (sync_mode == WB_SYNC_NONE || onstack)
- call_rcu(&work->rcu_head, bdi_work_free);
}
static void wb_clear_pending(struct bdi_writeback *wb, struct bdi_work *work)
@@ -148,7 +112,7 @@
list_del_rcu(&work->list);
spin_unlock(&bdi->wb_lock);
- wb_work_complete(work);
+ call_rcu(&work->rcu_head, bdi_work_free);
}
}
@@ -186,15 +150,14 @@
* Used for on-stack allocated work items. The caller needs to wait until
* the wb threads have acked the work before it's safe to continue.
*/
-static void bdi_wait_on_work_clear(struct bdi_work *work)
+static void bdi_wait_on_work_done(struct bdi_work *work)
{
- wait_on_bit(&work->state, WS_USED_B, bdi_sched_wait,
+ wait_on_bit(&work->state, WS_INPROGRESS, bdi_sched_wait,
TASK_UNINTERRUPTIBLE);
}
static void bdi_alloc_queue_work(struct backing_dev_info *bdi,
- struct wb_writeback_args *args,
- int wait)
+ struct wb_writeback_args *args)
{
struct bdi_work *work;
@@ -206,8 +169,6 @@
if (work) {
bdi_work_init(work, args);
bdi_queue_work(bdi, work);
- if (wait)
- bdi_wait_on_work_clear(work);
} else {
struct bdi_writeback *wb = &bdi->wb;
@@ -217,72 +178,65 @@
}
/**
- * bdi_sync_writeback - start and wait for writeback
- * @bdi: the backing device to write from
+ * bdi_queue_work_onstack - start and wait for writeback
* @sb: write inodes from this super_block
*
* Description:
- * This does WB_SYNC_ALL data integrity writeback and waits for the
- * IO to complete. Callers must hold the sb s_umount semaphore for
+ * This function initiates writeback and waits for the operation to
+ * complete. Callers must hold the sb s_umount semaphore for
* reading, to avoid having the super disappear before we are done.
*/
-static void bdi_sync_writeback(struct backing_dev_info *bdi,
- struct super_block *sb)
+static void bdi_queue_work_onstack(struct wb_writeback_args *args)
{
- struct wb_writeback_args args = {
- .sb = sb,
- .sync_mode = WB_SYNC_ALL,
- .nr_pages = LONG_MAX,
- .range_cyclic = 0,
- /*
- * Setting sb_pinned is not necessary for WB_SYNC_ALL, but
- * lets make it explicitly clear.
- */
- .sb_pinned = 1,
- };
struct bdi_work work;
- bdi_work_init(&work, &args);
- work.state |= WS_ONSTACK;
+ bdi_work_init(&work, args);
+ __set_bit(WS_ONSTACK, &work.state);
- bdi_queue_work(bdi, &work);
- bdi_wait_on_work_clear(&work);
+ bdi_queue_work(args->sb->s_bdi, &work);
+ bdi_wait_on_work_done(&work);
}
/**
* bdi_start_writeback - start writeback
* @bdi: the backing device to write from
- * @sb: write inodes from this super_block
* @nr_pages: the number of pages to write
- * @sb_locked: caller already holds sb umount sem.
*
* Description:
* This does WB_SYNC_NONE opportunistic writeback. The IO is only
* started when this function returns, we make no guarentees on
- * completion. Caller specifies whether sb umount sem is held already or not.
+ * completion. Caller need not hold sb s_umount semaphore.
*
*/
-void bdi_start_writeback(struct backing_dev_info *bdi, struct super_block *sb,
- long nr_pages, int sb_locked)
+void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages)
{
struct wb_writeback_args args = {
- .sb = sb,
.sync_mode = WB_SYNC_NONE,
.nr_pages = nr_pages,
.range_cyclic = 1,
- .sb_pinned = sb_locked,
};
- /*
- * We treat @nr_pages=0 as the special case to do background writeback,
- * ie. to sync pages until the background dirty threshold is reached.
- */
- if (!nr_pages) {
- args.nr_pages = LONG_MAX;
- args.for_background = 1;
- }
+ bdi_alloc_queue_work(bdi, &args);
+}
- bdi_alloc_queue_work(bdi, &args, sb_locked);
+/**
+ * bdi_start_background_writeback - start background writeback
+ * @bdi: the backing device to write from
+ *
+ * Description:
+ * This does WB_SYNC_NONE background writeback. The IO is only
+ * started when this function returns, we make no guarentees on
+ * completion. Caller need not hold sb s_umount semaphore.
+ */
+void bdi_start_background_writeback(struct backing_dev_info *bdi)
+{
+ struct wb_writeback_args args = {
+ .sync_mode = WB_SYNC_NONE,
+ .nr_pages = LONG_MAX,
+ .for_background = 1,
+ .range_cyclic = 1,
+ };
+ bdi_alloc_queue_work(bdi, &args);
}
/*
@@ -572,48 +526,30 @@
return ret;
}
-static void unpin_sb_for_writeback(struct super_block *sb)
-{
- up_read(&sb->s_umount);
- put_super(sb);
-}
-
-enum sb_pin_state {
- SB_PINNED,
- SB_NOT_PINNED,
- SB_PIN_FAILED
-};
-
/*
- * For WB_SYNC_NONE writeback, the caller does not have the sb pinned
+ * For background writeback the caller does not have the sb pinned
* before calling writeback. So make sure that we do pin it, so it doesn't
* go away while we are writing inodes from it.
*/
-static enum sb_pin_state pin_sb_for_writeback(struct writeback_control *wbc,
- struct super_block *sb)
+static bool pin_sb_for_writeback(struct super_block *sb)
{
- /*
- * Caller must already hold the ref for this
- */
- if (wbc->sync_mode == WB_SYNC_ALL || wbc->sb_pinned) {
- WARN_ON(!rwsem_is_locked(&sb->s_umount));
- return SB_NOT_PINNED;
- }
spin_lock(&sb_lock);
+ if (list_empty(&sb->s_instances)) {
+ spin_unlock(&sb_lock);
+ return false;
+ }
+
sb->s_count++;
+ spin_unlock(&sb_lock);
+
if (down_read_trylock(&sb->s_umount)) {
- if (sb->s_root) {
- spin_unlock(&sb_lock);
- return SB_PINNED;
- }
- /*
- * umounted, drop rwsem again and fall through to failure
- */
+ if (sb->s_root)
+ return true;
up_read(&sb->s_umount);
}
- sb->s_count--;
- spin_unlock(&sb_lock);
- return SB_PIN_FAILED;
+
+ put_super(sb);
+ return false;
}
/*
@@ -692,24 +628,31 @@
struct inode *inode = list_entry(wb->b_io.prev,
struct inode, i_list);
struct super_block *sb = inode->i_sb;
- enum sb_pin_state state;
- if (wbc->sb && sb != wbc->sb) {
- /* super block given and doesn't
- match, skip this inode */
- redirty_tail(inode);
- continue;
+ if (wbc->sb) {
+ /*
+ * We are requested to write out inodes for a specific
+ * superblock. This means we already have s_umount
+ * taken by the caller which also waits for us to
+ * complete the writeout.
+ */
+ if (sb != wbc->sb) {
+ redirty_tail(inode);
+ continue;
+ }
+
+ WARN_ON(!rwsem_is_locked(&sb->s_umount));
+
+ ret = writeback_sb_inodes(sb, wb, wbc);
+ } else {
+ if (!pin_sb_for_writeback(sb)) {
+ requeue_io(inode);
+ continue;
+ }
+ ret = writeback_sb_inodes(sb, wb, wbc);
+ drop_super(sb);
}
- state = pin_sb_for_writeback(wbc, sb);
- if (state == SB_PIN_FAILED) {
- requeue_io(inode);
- continue;
- }
- ret = writeback_sb_inodes(sb, wb, wbc);
-
- if (state == SB_PINNED)
- unpin_sb_for_writeback(sb);
if (ret)
break;
}
@@ -769,7 +712,6 @@
.for_kupdate = args->for_kupdate,
.for_background = args->for_background,
.range_cyclic = args->range_cyclic,
- .sb_pinned = args->sb_pinned,
};
unsigned long oldest_jif;
long wrote = 0;
@@ -912,7 +854,6 @@
while ((work = get_next_work_item(bdi, wb)) != NULL) {
struct wb_writeback_args args = work->args;
- int post_clear;
/*
* Override sync mode, in case we must wait for completion
@@ -920,13 +861,11 @@
if (force_wait)
work->args.sync_mode = args.sync_mode = WB_SYNC_ALL;
- post_clear = WB_SYNC_ALL || args.sb_pinned;
-
/*
* If this isn't a data integrity operation, just notify
* that we have seen this work and we are now starting it.
*/
- if (!post_clear)
+ if (!test_bit(WS_ONSTACK, &work->state))
wb_clear_pending(wb, work);
wrote += wb_writeback(wb, &args);
@@ -935,7 +874,7 @@
* This is a data integrity writeback, so only do the
* notification when we have completed the work.
*/
- if (post_clear)
+ if (test_bit(WS_ONSTACK, &work->state))
wb_clear_pending(wb, work);
}
@@ -993,40 +932,30 @@
}
/*
- * Schedule writeback for all backing devices. This does WB_SYNC_NONE
- * writeback, for integrity writeback see bdi_sync_writeback().
- */
-static void bdi_writeback_all(struct super_block *sb, long nr_pages)
-{
- struct wb_writeback_args args = {
- .sb = sb,
- .nr_pages = nr_pages,
- .sync_mode = WB_SYNC_NONE,
- };
- struct backing_dev_info *bdi;
-
- rcu_read_lock();
-
- list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) {
- if (!bdi_has_dirty_io(bdi))
- continue;
-
- bdi_alloc_queue_work(bdi, &args, 0);
- }
-
- rcu_read_unlock();
-}
-
-/*
* Start writeback of `nr_pages' pages. If `nr_pages' is zero, write back
* the whole world.
*/
void wakeup_flusher_threads(long nr_pages)
{
- if (nr_pages == 0)
- nr_pages = global_page_state(NR_FILE_DIRTY) +
+ struct backing_dev_info *bdi;
+ struct wb_writeback_args args = {
+ .sync_mode = WB_SYNC_NONE,
+ };
+
+ if (nr_pages) {
+ args.nr_pages = nr_pages;
+ } else {
+ args.nr_pages = global_page_state(NR_FILE_DIRTY) +
global_page_state(NR_UNSTABLE_NFS);
- bdi_writeback_all(NULL, nr_pages);
+ }
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) {
+ if (!bdi_has_dirty_io(bdi))
+ continue;
+ bdi_alloc_queue_work(bdi, &args);
+ }
+ rcu_read_unlock();
}
static noinline void block_dump___mark_inode_dirty(struct inode *inode)
@@ -1220,18 +1149,6 @@
iput(old_inode);
}
-static void __writeback_inodes_sb(struct super_block *sb, int sb_locked)
-{
- unsigned long nr_dirty = global_page_state(NR_FILE_DIRTY);
- unsigned long nr_unstable = global_page_state(NR_UNSTABLE_NFS);
- long nr_to_write;
-
- nr_to_write = nr_dirty + nr_unstable +
- (inodes_stat.nr_inodes - inodes_stat.nr_unused);
-
- bdi_start_writeback(sb->s_bdi, sb, nr_to_write, sb_locked);
-}
-
/**
* writeback_inodes_sb - writeback dirty inodes from given super_block
* @sb: the superblock
@@ -1243,23 +1160,23 @@
*/
void writeback_inodes_sb(struct super_block *sb)
{
- __writeback_inodes_sb(sb, 0);
+ unsigned long nr_dirty = global_page_state(NR_FILE_DIRTY);
+ unsigned long nr_unstable = global_page_state(NR_UNSTABLE_NFS);
+ struct wb_writeback_args args = {
+ .sb = sb,
+ .sync_mode = WB_SYNC_NONE,
+ };
+
+ WARN_ON(!rwsem_is_locked(&sb->s_umount));
+
+ args.nr_pages = nr_dirty + nr_unstable +
+ (inodes_stat.nr_inodes - inodes_stat.nr_unused);
+
+ bdi_queue_work_onstack(&args);
}
EXPORT_SYMBOL(writeback_inodes_sb);
/**
- * writeback_inodes_sb_locked - writeback dirty inodes from given super_block
- * @sb: the superblock
- *
- * Like writeback_inodes_sb(), except the caller already holds the
- * sb umount sem.
- */
-void writeback_inodes_sb_locked(struct super_block *sb)
-{
- __writeback_inodes_sb(sb, 1);
-}
-
-/**
* writeback_inodes_sb_if_idle - start writeback if none underway
* @sb: the superblock
*
@@ -1269,7 +1186,9 @@
int writeback_inodes_sb_if_idle(struct super_block *sb)
{
if (!writeback_in_progress(sb->s_bdi)) {
+ down_read(&sb->s_umount);
writeback_inodes_sb(sb);
+ up_read(&sb->s_umount);
return 1;
} else
return 0;
@@ -1285,7 +1204,16 @@
*/
void sync_inodes_sb(struct super_block *sb)
{
- bdi_sync_writeback(sb->s_bdi, sb);
+ struct wb_writeback_args args = {
+ .sb = sb,
+ .sync_mode = WB_SYNC_ALL,
+ .nr_pages = LONG_MAX,
+ .range_cyclic = 0,
+ };
+
+ WARN_ON(!rwsem_is_locked(&sb->s_umount));
+
+ bdi_queue_work_onstack(&args);
wait_sb_inodes(sb);
}
EXPORT_SYMBOL(sync_inodes_sb);
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
index a33aab6..54a92fd 100644
--- a/fs/jffs2/acl.c
+++ b/fs/jffs2/acl.c
@@ -234,8 +234,9 @@
if (inode->i_mode != mode) {
struct iattr attr;
- attr.ia_valid = ATTR_MODE;
+ attr.ia_valid = ATTR_MODE | ATTR_CTIME;
attr.ia_mode = mode;
+ attr.ia_ctime = CURRENT_TIME_SEC;
rc = jffs2_do_setattr(inode, &attr);
if (rc < 0)
return rc;
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 7aa4417..166062a 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -222,15 +222,18 @@
dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime));
jffs2_free_raw_inode(ri);
- d_instantiate(dentry, inode);
D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld\n",
inode->i_ino, inode->i_mode, inode->i_nlink,
f->inocache->pino_nlink, inode->i_mapping->nrpages));
+
+ d_instantiate(dentry, inode);
+ unlock_new_inode(inode);
return 0;
fail:
make_bad_inode(inode);
+ unlock_new_inode(inode);
iput(inode);
jffs2_free_raw_inode(ri);
return ret;
@@ -360,8 +363,8 @@
/* Eeek. Wave bye bye */
mutex_unlock(&f->sem);
jffs2_complete_reservation(c);
- jffs2_clear_inode(inode);
- return PTR_ERR(fn);
+ ret = PTR_ERR(fn);
+ goto fail;
}
/* We use f->target field to store the target path. */
@@ -370,8 +373,8 @@
printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1);
mutex_unlock(&f->sem);
jffs2_complete_reservation(c);
- jffs2_clear_inode(inode);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto fail;
}
memcpy(f->target, target, targetlen + 1);
@@ -386,30 +389,24 @@
jffs2_complete_reservation(c);
ret = jffs2_init_security(inode, dir_i);
- if (ret) {
- jffs2_clear_inode(inode);
- return ret;
- }
+ if (ret)
+ goto fail;
+
ret = jffs2_init_acl_post(inode);
- if (ret) {
- jffs2_clear_inode(inode);
- return ret;
- }
+ if (ret)
+ goto fail;
ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
- if (ret) {
- /* Eep. */
- jffs2_clear_inode(inode);
- return ret;
- }
+ if (ret)
+ goto fail;
rd = jffs2_alloc_raw_dirent();
if (!rd) {
/* Argh. Now we treat it like a normal delete */
jffs2_complete_reservation(c);
- jffs2_clear_inode(inode);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto fail;
}
dir_f = JFFS2_INODE_INFO(dir_i);
@@ -437,8 +434,8 @@
jffs2_complete_reservation(c);
jffs2_free_raw_dirent(rd);
mutex_unlock(&dir_f->sem);
- jffs2_clear_inode(inode);
- return PTR_ERR(fd);
+ ret = PTR_ERR(fd);
+ goto fail;
}
dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime));
@@ -453,7 +450,14 @@
jffs2_complete_reservation(c);
d_instantiate(dentry, inode);
+ unlock_new_inode(inode);
return 0;
+
+ fail:
+ make_bad_inode(inode);
+ unlock_new_inode(inode);
+ iput(inode);
+ return ret;
}
@@ -519,8 +523,8 @@
/* Eeek. Wave bye bye */
mutex_unlock(&f->sem);
jffs2_complete_reservation(c);
- jffs2_clear_inode(inode);
- return PTR_ERR(fn);
+ ret = PTR_ERR(fn);
+ goto fail;
}
/* No data here. Only a metadata node, which will be
obsoleted by the first data write
@@ -531,30 +535,24 @@
jffs2_complete_reservation(c);
ret = jffs2_init_security(inode, dir_i);
- if (ret) {
- jffs2_clear_inode(inode);
- return ret;
- }
+ if (ret)
+ goto fail;
+
ret = jffs2_init_acl_post(inode);
- if (ret) {
- jffs2_clear_inode(inode);
- return ret;
- }
+ if (ret)
+ goto fail;
ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
- if (ret) {
- /* Eep. */
- jffs2_clear_inode(inode);
- return ret;
- }
+ if (ret)
+ goto fail;
rd = jffs2_alloc_raw_dirent();
if (!rd) {
/* Argh. Now we treat it like a normal delete */
jffs2_complete_reservation(c);
- jffs2_clear_inode(inode);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto fail;
}
dir_f = JFFS2_INODE_INFO(dir_i);
@@ -582,8 +580,8 @@
jffs2_complete_reservation(c);
jffs2_free_raw_dirent(rd);
mutex_unlock(&dir_f->sem);
- jffs2_clear_inode(inode);
- return PTR_ERR(fd);
+ ret = PTR_ERR(fd);
+ goto fail;
}
dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime));
@@ -599,7 +597,14 @@
jffs2_complete_reservation(c);
d_instantiate(dentry, inode);
+ unlock_new_inode(inode);
return 0;
+
+ fail:
+ make_bad_inode(inode);
+ unlock_new_inode(inode);
+ iput(inode);
+ return ret;
}
static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry)
@@ -693,8 +698,8 @@
/* Eeek. Wave bye bye */
mutex_unlock(&f->sem);
jffs2_complete_reservation(c);
- jffs2_clear_inode(inode);
- return PTR_ERR(fn);
+ ret = PTR_ERR(fn);
+ goto fail;
}
/* No data here. Only a metadata node, which will be
obsoleted by the first data write
@@ -705,30 +710,24 @@
jffs2_complete_reservation(c);
ret = jffs2_init_security(inode, dir_i);
- if (ret) {
- jffs2_clear_inode(inode);
- return ret;
- }
+ if (ret)
+ goto fail;
+
ret = jffs2_init_acl_post(inode);
- if (ret) {
- jffs2_clear_inode(inode);
- return ret;
- }
+ if (ret)
+ goto fail;
ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
- if (ret) {
- /* Eep. */
- jffs2_clear_inode(inode);
- return ret;
- }
+ if (ret)
+ goto fail;
rd = jffs2_alloc_raw_dirent();
if (!rd) {
/* Argh. Now we treat it like a normal delete */
jffs2_complete_reservation(c);
- jffs2_clear_inode(inode);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto fail;
}
dir_f = JFFS2_INODE_INFO(dir_i);
@@ -759,8 +758,8 @@
jffs2_complete_reservation(c);
jffs2_free_raw_dirent(rd);
mutex_unlock(&dir_f->sem);
- jffs2_clear_inode(inode);
- return PTR_ERR(fd);
+ ret = PTR_ERR(fd);
+ goto fail;
}
dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime));
@@ -775,8 +774,14 @@
jffs2_complete_reservation(c);
d_instantiate(dentry, inode);
-
+ unlock_new_inode(inode);
return 0;
+
+ fail:
+ make_bad_inode(inode);
+ unlock_new_inode(inode);
+ iput(inode);
+ return ret;
}
static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 8bc2c80..459d39d 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -465,7 +465,12 @@
inode->i_blocks = 0;
inode->i_size = 0;
- insert_inode_hash(inode);
+ if (insert_inode_locked(inode) < 0) {
+ make_bad_inode(inode);
+ unlock_new_inode(inode);
+ iput(inode);
+ return ERR_PTR(-EINVAL);
+ }
return inode;
}
diff --git a/fs/libfs.c b/fs/libfs.c
index 09e1016..dcaf972 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -489,7 +489,8 @@
* unique inode values later for this filesystem, then you must take care
* to pass it an appropriate max_reserved value to avoid collisions.
*/
-int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files)
+int simple_fill_super(struct super_block *s, unsigned long magic,
+ struct tree_descr *files)
{
struct inode *inode;
struct dentry *root;
diff --git a/fs/minix/dir.c b/fs/minix/dir.c
index 9196958..1dbf921 100644
--- a/fs/minix/dir.c
+++ b/fs/minix/dir.c
@@ -75,10 +75,6 @@
if (!IS_ERR(page))
kmap(page);
return page;
-
-fail:
- dir_put_page(page);
- return ERR_PTR(-EIO);
}
static inline void *minix_next_entry(void *de, struct minix_sb_info *sbi)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 7ec9b34..d25b525 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -1286,6 +1286,55 @@
#endif /* CONFIG_NFS_V4_1 */
}
+static int nfs4_server_common_setup(struct nfs_server *server,
+ struct nfs_fh *mntfh)
+{
+ struct nfs_fattr *fattr;
+ int error;
+
+ BUG_ON(!server->nfs_client);
+ BUG_ON(!server->nfs_client->rpc_ops);
+ BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
+
+ fattr = nfs_alloc_fattr();
+ if (fattr == NULL)
+ return -ENOMEM;
+
+ /* We must ensure the session is initialised first */
+ error = nfs4_init_session(server);
+ if (error < 0)
+ goto out;
+
+ /* Probe the root fh to retrieve its FSID and filehandle */
+ error = nfs4_get_rootfh(server, mntfh);
+ if (error < 0)
+ goto out;
+
+ dprintk("Server FSID: %llx:%llx\n",
+ (unsigned long long) server->fsid.major,
+ (unsigned long long) server->fsid.minor);
+ dprintk("Mount FH: %d\n", mntfh->size);
+
+ nfs4_session_set_rwsize(server);
+
+ error = nfs_probe_fsinfo(server, mntfh, fattr);
+ if (error < 0)
+ goto out;
+
+ if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
+ server->namelen = NFS4_MAXNAMLEN;
+
+ spin_lock(&nfs_client_lock);
+ list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
+ list_add_tail(&server->master_link, &nfs_volume_list);
+ spin_unlock(&nfs_client_lock);
+
+ server->mount_time = jiffies;
+out:
+ nfs_free_fattr(fattr);
+ return error;
+}
+
/*
* Create a version 4 volume record
*/
@@ -1346,7 +1395,6 @@
struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
struct nfs_fh *mntfh)
{
- struct nfs_fattr *fattr;
struct nfs_server *server;
int error;
@@ -1356,55 +1404,19 @@
if (!server)
return ERR_PTR(-ENOMEM);
- error = -ENOMEM;
- fattr = nfs_alloc_fattr();
- if (fattr == NULL)
- goto error;
-
/* set up the general RPC client */
error = nfs4_init_server(server, data);
if (error < 0)
goto error;
- BUG_ON(!server->nfs_client);
- BUG_ON(!server->nfs_client->rpc_ops);
- BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
-
- error = nfs4_init_session(server);
+ error = nfs4_server_common_setup(server, mntfh);
if (error < 0)
goto error;
- /* Probe the root fh to retrieve its FSID */
- error = nfs4_get_rootfh(server, mntfh);
- if (error < 0)
- goto error;
-
- dprintk("Server FSID: %llx:%llx\n",
- (unsigned long long) server->fsid.major,
- (unsigned long long) server->fsid.minor);
- dprintk("Mount FH: %d\n", mntfh->size);
-
- nfs4_session_set_rwsize(server);
-
- error = nfs_probe_fsinfo(server, mntfh, fattr);
- if (error < 0)
- goto error;
-
- if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
- server->namelen = NFS4_MAXNAMLEN;
-
- spin_lock(&nfs_client_lock);
- list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
- list_add_tail(&server->master_link, &nfs_volume_list);
- spin_unlock(&nfs_client_lock);
-
- server->mount_time = jiffies;
dprintk("<-- nfs4_create_server() = %p\n", server);
- nfs_free_fattr(fattr);
return server;
error:
- nfs_free_fattr(fattr);
nfs_free_server(server);
dprintk("<-- nfs4_create_server() = error %d\n", error);
return ERR_PTR(error);
@@ -1418,7 +1430,6 @@
{
struct nfs_client *parent_client;
struct nfs_server *server, *parent_server;
- struct nfs_fattr *fattr;
int error;
dprintk("--> nfs4_create_referral_server()\n");
@@ -1427,11 +1438,6 @@
if (!server)
return ERR_PTR(-ENOMEM);
- error = -ENOMEM;
- fattr = nfs_alloc_fattr();
- if (fattr == NULL)
- goto error;
-
parent_server = NFS_SB(data->sb);
parent_client = parent_server->nfs_client;
@@ -1456,40 +1462,14 @@
if (error < 0)
goto error;
- BUG_ON(!server->nfs_client);
- BUG_ON(!server->nfs_client->rpc_ops);
- BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
-
- /* Probe the root fh to retrieve its FSID and filehandle */
- error = nfs4_get_rootfh(server, mntfh);
+ error = nfs4_server_common_setup(server, mntfh);
if (error < 0)
goto error;
- /* probe the filesystem info for this server filesystem */
- error = nfs_probe_fsinfo(server, mntfh, fattr);
- if (error < 0)
- goto error;
-
- if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
- server->namelen = NFS4_MAXNAMLEN;
-
- dprintk("Referral FSID: %llx:%llx\n",
- (unsigned long long) server->fsid.major,
- (unsigned long long) server->fsid.minor);
-
- spin_lock(&nfs_client_lock);
- list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
- list_add_tail(&server->master_link, &nfs_volume_list);
- spin_unlock(&nfs_client_lock);
-
- server->mount_time = jiffies;
-
- nfs_free_fattr(fattr);
dprintk("<-- nfs_create_referral_server() = %p\n", server);
return server;
error:
- nfs_free_fattr(fattr);
nfs_free_server(server);
dprintk("<-- nfs4_create_referral_server() = error %d\n", error);
return ERR_PTR(error);
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c
index 7428f7d..a70e446 100644
--- a/fs/nfs/getroot.c
+++ b/fs/nfs/getroot.c
@@ -146,7 +146,7 @@
goto out;
}
- if (!(fsinfo.fattr->valid & NFS_ATTR_FATTR_MODE)
+ if (!(fsinfo.fattr->valid & NFS_ATTR_FATTR_TYPE)
|| !S_ISDIR(fsinfo.fattr->mode)) {
printk(KERN_ERR "nfs4_get_rootfh:"
" getroot encountered non-directory\n");
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 6bdef28..65c8dae 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -862,8 +862,8 @@
bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
*p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
*p++ = cpu_to_be32(0);
- *p++ = cpu_to_be32(iap->ia_mtime.tv_sec);
- *p++ = cpu_to_be32(iap->ia_mtime.tv_nsec);
+ *p++ = cpu_to_be32(iap->ia_atime.tv_sec);
+ *p++ = cpu_to_be32(iap->ia_atime.tv_nsec);
}
else if (iap->ia_valid & ATTR_ATIME) {
bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 04214fc..f9df16d 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -570,6 +570,22 @@
nfs_show_mountd_netid(m, nfss, showdefaults);
}
+#ifdef CONFIG_NFS_V4
+static void nfs_show_nfsv4_options(struct seq_file *m, struct nfs_server *nfss,
+ int showdefaults)
+{
+ struct nfs_client *clp = nfss->nfs_client;
+
+ seq_printf(m, ",clientaddr=%s", clp->cl_ipaddr);
+ seq_printf(m, ",minorversion=%u", clp->cl_minorversion);
+}
+#else
+static void nfs_show_nfsv4_options(struct seq_file *m, struct nfs_server *nfss,
+ int showdefaults)
+{
+}
+#endif
+
/*
* Describe the mount options in force on this server representation
*/
@@ -631,11 +647,9 @@
if (version != 4)
nfs_show_mountd_options(m, nfss, showdefaults);
+ else
+ nfs_show_nfsv4_options(m, nfss, showdefaults);
-#ifdef CONFIG_NFS_V4
- if (clp->rpc_ops->version == 4)
- seq_printf(m, ",clientaddr=%s", clp->cl_ipaddr);
-#endif
if (nfss->options & NFS_OPTION_FSCACHE)
seq_printf(m, ",fsc");
}
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 12f7109..4a27347 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -4122,8 +4122,8 @@
nfs4_lock_state();
nfs4_release_reclaim();
__nfs4_state_shutdown();
- nfsd4_destroy_callback_queue();
nfs4_unlock_state();
+ nfsd4_destroy_callback_queue();
}
/*
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index ebbf3b6..3c11112 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -443,8 +443,7 @@
if (size_change)
put_write_access(inode);
if (!err)
- if (EX_ISSYNC(fhp->fh_export))
- write_inode_now(inode, 1);
+ commit_metadata(fhp);
out:
return err;
diff --git a/fs/nilfs2/btree.h b/fs/nilfs2/btree.h
index af638d5..43c8c5b 100644
--- a/fs/nilfs2/btree.h
+++ b/fs/nilfs2/btree.h
@@ -75,8 +75,6 @@
extern struct kmem_cache *nilfs_btree_path_cache;
-int nilfs_btree_path_cache_init(void);
-void nilfs_btree_path_cache_destroy(void);
int nilfs_btree_init(struct nilfs_bmap *);
int nilfs_btree_convert_and_insert(struct nilfs_bmap *, __u64, __u64,
const __u64 *, const __u64 *, int);
diff --git a/fs/nilfs2/segbuf.h b/fs/nilfs2/segbuf.h
index fdf1c3b..85fbb66 100644
--- a/fs/nilfs2/segbuf.h
+++ b/fs/nilfs2/segbuf.h
@@ -127,8 +127,6 @@
extern struct kmem_cache *nilfs_segbuf_cachep;
-int __init nilfs_init_segbuf_cache(void);
-void nilfs_destroy_segbuf_cache(void);
struct nilfs_segment_buffer *nilfs_segbuf_new(struct super_block *);
void nilfs_segbuf_free(struct nilfs_segment_buffer *);
void nilfs_segbuf_map(struct nilfs_segment_buffer *, __u64, unsigned long,
diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h
index dca1423..01e20db 100644
--- a/fs/nilfs2/segment.h
+++ b/fs/nilfs2/segment.h
@@ -221,8 +221,6 @@
extern struct kmem_cache *nilfs_transaction_cachep;
/* segment.c */
-extern int nilfs_init_transaction_cache(void);
-extern void nilfs_destroy_transaction_cache(void);
extern void nilfs_relax_pressure_in_lock(struct super_block *);
extern int nilfs_construct_segment(struct super_block *);
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index 03b34b7..414ef68 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -1130,13 +1130,13 @@
static void nilfs_destroy_cachep(void)
{
- if (nilfs_inode_cachep)
+ if (nilfs_inode_cachep)
kmem_cache_destroy(nilfs_inode_cachep);
- if (nilfs_transaction_cachep)
+ if (nilfs_transaction_cachep)
kmem_cache_destroy(nilfs_transaction_cachep);
- if (nilfs_segbuf_cachep)
+ if (nilfs_segbuf_cachep)
kmem_cache_destroy(nilfs_segbuf_cachep);
- if (nilfs_btree_path_cache)
+ if (nilfs_btree_path_cache)
kmem_cache_destroy(nilfs_btree_path_cache);
}
diff --git a/fs/ocfs2/reservations.c b/fs/ocfs2/reservations.c
index 4065002..d8b6e42 100644
--- a/fs/ocfs2/reservations.c
+++ b/fs/ocfs2/reservations.c
@@ -26,7 +26,6 @@
#include <linux/fs.h>
#include <linux/types.h>
-#include <linux/slab.h>
#include <linux/highmem.h>
#include <linux/bitops.h>
#include <linux/list.h>
diff --git a/fs/pipe.c b/fs/pipe.c
index db6eaab..279eef9 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -26,9 +26,14 @@
/*
* The max size that a non-root user is allowed to grow the pipe. Can
- * be set by root in /proc/sys/fs/pipe-max-pages
+ * be set by root in /proc/sys/fs/pipe-max-size
*/
-unsigned int pipe_max_pages = PIPE_DEF_BUFFERS * 16;
+unsigned int pipe_max_size = 1048576;
+
+/*
+ * Minimum pipe size, as required by POSIX
+ */
+unsigned int pipe_min_size = PAGE_SIZE;
/*
* We use a start+len construction, which provides full use of the
@@ -1118,26 +1123,20 @@
* Allocate a new array of pipe buffers and copy the info over. Returns the
* pipe size if successful, or return -ERROR on error.
*/
-static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg)
+static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long nr_pages)
{
struct pipe_buffer *bufs;
/*
- * Must be a power-of-2 currently
- */
- if (!is_power_of_2(arg))
- return -EINVAL;
-
- /*
* We can shrink the pipe, if arg >= pipe->nrbufs. Since we don't
* expect a lot of shrink+grow operations, just free and allocate
* again like we would do for growing. If the pipe currently
* contains more buffers than arg, then return busy.
*/
- if (arg < pipe->nrbufs)
+ if (nr_pages < pipe->nrbufs)
return -EBUSY;
- bufs = kcalloc(arg, sizeof(struct pipe_buffer), GFP_KERNEL);
+ bufs = kcalloc(nr_pages, sizeof(struct pipe_buffer), GFP_KERNEL);
if (unlikely(!bufs))
return -ENOMEM;
@@ -1146,20 +1145,56 @@
* and adjust the indexes.
*/
if (pipe->nrbufs) {
- const unsigned int tail = pipe->nrbufs & (pipe->buffers - 1);
- const unsigned int head = pipe->nrbufs - tail;
+ unsigned int tail;
+ unsigned int head;
+ tail = pipe->curbuf + pipe->nrbufs;
+ if (tail < pipe->buffers)
+ tail = 0;
+ else
+ tail &= (pipe->buffers - 1);
+
+ head = pipe->nrbufs - tail;
if (head)
memcpy(bufs, pipe->bufs + pipe->curbuf, head * sizeof(struct pipe_buffer));
if (tail)
- memcpy(bufs + head, pipe->bufs + pipe->curbuf, tail * sizeof(struct pipe_buffer));
+ memcpy(bufs + head, pipe->bufs, tail * sizeof(struct pipe_buffer));
}
pipe->curbuf = 0;
kfree(pipe->bufs);
pipe->bufs = bufs;
- pipe->buffers = arg;
- return arg;
+ pipe->buffers = nr_pages;
+ return nr_pages * PAGE_SIZE;
+}
+
+/*
+ * Currently we rely on the pipe array holding a power-of-2 number
+ * of pages.
+ */
+static inline unsigned int round_pipe_size(unsigned int size)
+{
+ unsigned long nr_pages;
+
+ nr_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ return roundup_pow_of_two(nr_pages) << PAGE_SHIFT;
+}
+
+/*
+ * This should work even if CONFIG_PROC_FS isn't set, as proc_dointvec_minmax
+ * will return an error.
+ */
+int pipe_proc_fn(struct ctl_table *table, int write, void __user *buf,
+ size_t *lenp, loff_t *ppos)
+{
+ int ret;
+
+ ret = proc_dointvec_minmax(table, write, buf, lenp, ppos);
+ if (ret < 0 || !write)
+ return ret;
+
+ pipe_max_size = round_pipe_size(pipe_max_size);
+ return ret;
}
long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
@@ -1174,23 +1209,25 @@
mutex_lock(&pipe->inode->i_mutex);
switch (cmd) {
- case F_SETPIPE_SZ:
- if (!capable(CAP_SYS_ADMIN) && arg > pipe_max_pages) {
- ret = -EINVAL;
+ case F_SETPIPE_SZ: {
+ unsigned int size, nr_pages;
+
+ size = round_pipe_size(arg);
+ nr_pages = size >> PAGE_SHIFT;
+
+ ret = -EINVAL;
+ if (!nr_pages)
+ goto out;
+
+ if (!capable(CAP_SYS_RESOURCE) && size > pipe_max_size) {
+ ret = -EPERM;
goto out;
}
- /*
- * The pipe needs to be at least 2 pages large to
- * guarantee POSIX behaviour.
- */
- if (arg < 2) {
- ret = -EINVAL;
- goto out;
- }
- ret = pipe_set_size(pipe, arg);
+ ret = pipe_set_size(pipe, nr_pages);
break;
+ }
case F_GETPIPE_SZ:
- ret = pipe->buffers;
+ ret = pipe->buffers * PAGE_SIZE;
break;
default:
ret = -EINVAL;
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
index ce94801..d9396a4 100644
--- a/fs/proc/proc_devtree.c
+++ b/fs/proc/proc_devtree.c
@@ -209,6 +209,9 @@
for (pp = np->properties; pp != NULL; pp = pp->next) {
p = pp->name;
+ if (strchr(p, '/'))
+ continue;
+
if (duplicate_name(de, p))
p = fixup_name(np, de, p);
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
index 46d4b5d..cb6306e 100644
--- a/fs/proc/task_nommu.c
+++ b/fs/proc/task_nommu.c
@@ -122,11 +122,20 @@
return size;
}
+static void pad_len_spaces(struct seq_file *m, int len)
+{
+ len = 25 + sizeof(void*) * 6 - len;
+ if (len < 1)
+ len = 1;
+ seq_printf(m, "%*c", len, ' ');
+}
+
/*
* display a single VMA to a sequenced file
*/
static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma)
{
+ struct mm_struct *mm = vma->vm_mm;
unsigned long ino = 0;
struct file *file;
dev_t dev = 0;
@@ -155,11 +164,14 @@
MAJOR(dev), MINOR(dev), ino, &len);
if (file) {
- len = 25 + sizeof(void *) * 6 - len;
- if (len < 1)
- len = 1;
- seq_printf(m, "%*c", len, ' ');
+ pad_len_spaces(m, len);
seq_path(m, &file->f_path, "");
+ } else if (mm) {
+ if (vma->vm_start <= mm->start_stack &&
+ vma->vm_end >= mm->start_stack) {
+ pad_len_spaces(m, len);
+ seq_puts(m, "[stack]");
+ }
}
seq_putc(m, '\n');
diff --git a/fs/splice.c b/fs/splice.c
index ac22b00..740e6b9 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -354,7 +354,7 @@
break;
error = add_to_page_cache_lru(page, mapping, index,
- mapping_gfp_mask(mapping));
+ GFP_KERNEL);
if (unlikely(error)) {
page_cache_release(page);
if (error == -EEXIST)
diff --git a/fs/super.c b/fs/super.c
index 5c35bc7..938119a 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -374,6 +374,8 @@
up_read(&sb->s_umount);
spin_lock(&sb_lock);
+ /* lock was dropped, must reset next */
+ list_safe_reset_next(sb, n, s_list);
__put_super(sb);
}
}
@@ -405,6 +407,8 @@
up_read(&sb->s_umount);
spin_lock(&sb_lock);
+ /* lock was dropped, must reset next */
+ list_safe_reset_next(sb, n, s_list);
__put_super(sb);
}
spin_unlock(&sb_lock);
@@ -585,6 +589,8 @@
}
up_write(&sb->s_umount);
spin_lock(&sb_lock);
+ /* lock was dropped, must reset next */
+ list_safe_reset_next(sb, n, s_list);
__put_super(sb);
}
spin_unlock(&sb_lock);
diff --git a/fs/sync.c b/fs/sync.c
index c9f83f4..15aa6f0 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -42,7 +42,7 @@
if (wait)
sync_inodes_sb(sb);
else
- writeback_inodes_sb_locked(sb);
+ writeback_inodes_sb(sb);
if (sb->s_op->sync_fs)
sb->s_op->sync_fs(sb, wait);
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index bde1a4c..0835a3b 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -117,11 +117,13 @@
if (error)
goto out;
+ error = sysfs_sd_setattr(sd, iattr);
+ if (error)
+ goto out;
+
/* this ignores size changes */
generic_setattr(inode, iattr);
- error = sysfs_sd_setattr(sd, iattr);
-
out:
mutex_unlock(&sysfs_mutex);
return error;
diff --git a/fs/sysv/ialloc.c b/fs/sysv/ialloc.c
index bbd69bd..fcc498e 100644
--- a/fs/sysv/ialloc.c
+++ b/fs/sysv/ialloc.c
@@ -25,6 +25,7 @@
#include <linux/stat.h>
#include <linux/string.h>
#include <linux/buffer_head.h>
+#include <linux/writeback.h>
#include "sysv.h"
/* We don't trust the value of
@@ -139,6 +140,9 @@
struct inode *inode;
sysv_ino_t ino;
unsigned count;
+ struct writeback_control wbc = {
+ .sync_mode = WB_SYNC_NONE
+ };
inode = new_inode(sb);
if (!inode)
@@ -168,7 +172,7 @@
insert_inode_hash(inode);
mark_inode_dirty(inode);
- sysv_write_inode(inode, 0); /* ensure inode not allocated again */
+ sysv_write_inode(inode, &wbc); /* ensure inode not allocated again */
mark_inode_dirty(inode); /* cleared by sysv_write_inode() */
/* That's it. */
unlock_super(sb);
diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c
index 076ca50..c8ff0d1 100644
--- a/fs/ubifs/budget.c
+++ b/fs/ubifs/budget.c
@@ -62,7 +62,9 @@
*/
static void shrink_liability(struct ubifs_info *c, int nr_to_write)
{
+ down_read(&c->vfs_sb->s_umount);
writeback_inodes_sb(c->vfs_sb);
+ up_read(&c->vfs_sb->s_umount);
}
/**
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 089eaca..34640d6 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -1333,6 +1333,21 @@
trace_xfs_writepage(inode, page, 0);
/*
+ * Refuse to write the page out if we are called from reclaim context.
+ *
+ * This is primarily to avoid stack overflows when called from deep
+ * used stacks in random callers for direct reclaim, but disabling
+ * reclaim for kswap is a nice side-effect as kswapd causes rather
+ * suboptimal I/O patters, too.
+ *
+ * This should really be done by the core VM, but until that happens
+ * filesystems like XFS, btrfs and ext4 have to take care of this
+ * by themselves.
+ */
+ if (current->flags & PF_MEMALLOC)
+ goto out_fail;
+
+ /*
* We need a transaction if:
* 1. There are delalloc buffers on the page
* 2. The page is uptodate and we have unmapped buffers
@@ -1366,14 +1381,6 @@
if (!page_has_buffers(page))
create_empty_buffers(page, 1 << inode->i_blkbits, 0);
-
- /*
- * VM calculation for nr_to_write seems off. Bump it way
- * up, this gets simple streaming writes zippy again.
- * To be reviewed again after Jens' writeback changes.
- */
- wbc->nr_to_write *= 4;
-
/*
* Convert delayed allocate, unwritten or unmapped space
* to real space and flush out to disk.
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 9c8019c..44f0b2d 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -585,11 +585,20 @@
bf.l_len = len;
xfs_ilock(ip, XFS_IOLOCK_EXCL);
+
+ /* check the new inode size is valid before allocating */
+ if (!(mode & FALLOC_FL_KEEP_SIZE) &&
+ offset + len > i_size_read(inode)) {
+ new_size = offset + len;
+ error = inode_newsize_ok(inode, new_size);
+ if (error)
+ goto out_unlock;
+ }
+
error = -xfs_change_file_space(ip, XFS_IOC_RESVSP, &bf,
0, XFS_ATTR_NOLOCK);
- if (!error && !(mode & FALLOC_FL_KEEP_SIZE) &&
- offset + len > i_size_read(inode))
- new_size = offset + len;
+ if (error)
+ goto out_unlock;
/* Change file size if needed */
if (new_size) {
@@ -600,6 +609,7 @@
error = -xfs_setattr(ip, &iattr, XFS_ATTR_NOLOCK);
}
+out_unlock:
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
out_error:
return error;
diff --git a/fs/xfs/linux-2.6/xfs_quotaops.c b/fs/xfs/linux-2.6/xfs_quotaops.c
index 9ac8aea..067cafb 100644
--- a/fs/xfs/linux-2.6/xfs_quotaops.c
+++ b/fs/xfs/linux-2.6/xfs_quotaops.c
@@ -23,7 +23,6 @@
#include "xfs_ag.h"
#include "xfs_mount.h"
#include "xfs_quota.h"
-#include "xfs_log.h"
#include "xfs_trans.h"
#include "xfs_bmap_btree.h"
#include "xfs_inode.h"
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c
index 3884e20..ef7f021 100644
--- a/fs/xfs/linux-2.6/xfs_sync.c
+++ b/fs/xfs/linux-2.6/xfs_sync.c
@@ -164,10 +164,6 @@
struct xfs_perag *pag;
pag = xfs_perag_get(mp, ag);
- if (!pag->pag_ici_init) {
- xfs_perag_put(pag);
- continue;
- }
error = xfs_inode_ag_walk(mp, pag, execute, flags, tag,
exclusive, &nr);
xfs_perag_put(pag);
@@ -867,12 +863,7 @@
down_read(&xfs_mount_list_lock);
list_for_each_entry(mp, &xfs_mount_list, m_mplist) {
for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) {
-
pag = xfs_perag_get(mp, ag);
- if (!pag->pag_ici_init) {
- xfs_perag_put(pag);
- continue;
- }
reclaimable += pag->pag_ici_reclaimable;
xfs_perag_put(pag);
}
diff --git a/fs/xfs/linux-2.6/xfs_trace.c b/fs/xfs/linux-2.6/xfs_trace.c
index 207fa77..d12be84 100644
--- a/fs/xfs/linux-2.6/xfs_trace.c
+++ b/fs/xfs/linux-2.6/xfs_trace.c
@@ -50,7 +50,6 @@
#include "quota/xfs_dquot_item.h"
#include "quota/xfs_dquot.h"
#include "xfs_log_recover.h"
-#include "xfs_buf_item.h"
#include "xfs_inode_item.h"
/*
diff --git a/fs/xfs/linux-2.6/xfs_trace.h b/fs/xfs/linux-2.6/xfs_trace.h
index ff6bc79..73d5aa1 100644
--- a/fs/xfs/linux-2.6/xfs_trace.h
+++ b/fs/xfs/linux-2.6/xfs_trace.h
@@ -82,33 +82,6 @@
)
)
-#define DEFINE_PERAG_REF_EVENT(name) \
-TRACE_EVENT(name, \
- TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, int refcount, \
- unsigned long caller_ip), \
- TP_ARGS(mp, agno, refcount, caller_ip), \
- TP_STRUCT__entry( \
- __field(dev_t, dev) \
- __field(xfs_agnumber_t, agno) \
- __field(int, refcount) \
- __field(unsigned long, caller_ip) \
- ), \
- TP_fast_assign( \
- __entry->dev = mp->m_super->s_dev; \
- __entry->agno = agno; \
- __entry->refcount = refcount; \
- __entry->caller_ip = caller_ip; \
- ), \
- TP_printk("dev %d:%d agno %u refcount %d caller %pf", \
- MAJOR(__entry->dev), MINOR(__entry->dev), \
- __entry->agno, \
- __entry->refcount, \
- (char *)__entry->caller_ip) \
-);
-
-DEFINE_PERAG_REF_EVENT(xfs_perag_get)
-DEFINE_PERAG_REF_EVENT(xfs_perag_put)
-
#define DEFINE_ATTR_LIST_EVENT(name) \
DEFINE_EVENT(xfs_attr_list_class, name, \
TP_PROTO(struct xfs_attr_list_context *ctx), \
@@ -122,6 +95,37 @@
DEFINE_ATTR_LIST_EVENT(xfs_attr_list_wrong_blk);
DEFINE_ATTR_LIST_EVENT(xfs_attr_list_notfound);
+DECLARE_EVENT_CLASS(xfs_perag_class,
+ TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, int refcount,
+ unsigned long caller_ip),
+ TP_ARGS(mp, agno, refcount, caller_ip),
+ TP_STRUCT__entry(
+ __field(dev_t, dev)
+ __field(xfs_agnumber_t, agno)
+ __field(int, refcount)
+ __field(unsigned long, caller_ip)
+ ),
+ TP_fast_assign(
+ __entry->dev = mp->m_super->s_dev;
+ __entry->agno = agno;
+ __entry->refcount = refcount;
+ __entry->caller_ip = caller_ip;
+ ),
+ TP_printk("dev %d:%d agno %u refcount %d caller %pf",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ __entry->agno,
+ __entry->refcount,
+ (char *)__entry->caller_ip)
+);
+
+#define DEFINE_PERAG_REF_EVENT(name) \
+DEFINE_EVENT(xfs_perag_class, name, \
+ TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, int refcount, \
+ unsigned long caller_ip), \
+ TP_ARGS(mp, agno, refcount, caller_ip))
+DEFINE_PERAG_REF_EVENT(xfs_perag_get);
+DEFINE_PERAG_REF_EVENT(xfs_perag_put);
+
TRACE_EVENT(xfs_attr_list_node_descend,
TP_PROTO(struct xfs_attr_list_context *ctx,
struct xfs_da_node_entry *btree),
@@ -775,165 +779,181 @@
DEFINE_LOGGRANT_EVENT(xfs_log_ungrant_exit);
DEFINE_LOGGRANT_EVENT(xfs_log_ungrant_sub);
-#define DEFINE_RW_EVENT(name) \
-TRACE_EVENT(name, \
- TP_PROTO(struct xfs_inode *ip, size_t count, loff_t offset, int flags), \
- TP_ARGS(ip, count, offset, flags), \
- TP_STRUCT__entry( \
- __field(dev_t, dev) \
- __field(xfs_ino_t, ino) \
- __field(xfs_fsize_t, size) \
- __field(xfs_fsize_t, new_size) \
- __field(loff_t, offset) \
- __field(size_t, count) \
- __field(int, flags) \
- ), \
- TP_fast_assign( \
- __entry->dev = VFS_I(ip)->i_sb->s_dev; \
- __entry->ino = ip->i_ino; \
- __entry->size = ip->i_d.di_size; \
- __entry->new_size = ip->i_new_size; \
- __entry->offset = offset; \
- __entry->count = count; \
- __entry->flags = flags; \
- ), \
- TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx " \
- "offset 0x%llx count 0x%zx ioflags %s", \
- MAJOR(__entry->dev), MINOR(__entry->dev), \
- __entry->ino, \
- __entry->size, \
- __entry->new_size, \
- __entry->offset, \
- __entry->count, \
- __print_flags(__entry->flags, "|", XFS_IO_FLAGS)) \
+DECLARE_EVENT_CLASS(xfs_file_class,
+ TP_PROTO(struct xfs_inode *ip, size_t count, loff_t offset, int flags),
+ TP_ARGS(ip, count, offset, flags),
+ TP_STRUCT__entry(
+ __field(dev_t, dev)
+ __field(xfs_ino_t, ino)
+ __field(xfs_fsize_t, size)
+ __field(xfs_fsize_t, new_size)
+ __field(loff_t, offset)
+ __field(size_t, count)
+ __field(int, flags)
+ ),
+ TP_fast_assign(
+ __entry->dev = VFS_I(ip)->i_sb->s_dev;
+ __entry->ino = ip->i_ino;
+ __entry->size = ip->i_d.di_size;
+ __entry->new_size = ip->i_new_size;
+ __entry->offset = offset;
+ __entry->count = count;
+ __entry->flags = flags;
+ ),
+ TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx "
+ "offset 0x%llx count 0x%zx ioflags %s",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ __entry->ino,
+ __entry->size,
+ __entry->new_size,
+ __entry->offset,
+ __entry->count,
+ __print_flags(__entry->flags, "|", XFS_IO_FLAGS))
)
+
+#define DEFINE_RW_EVENT(name) \
+DEFINE_EVENT(xfs_file_class, name, \
+ TP_PROTO(struct xfs_inode *ip, size_t count, loff_t offset, int flags), \
+ TP_ARGS(ip, count, offset, flags))
DEFINE_RW_EVENT(xfs_file_read);
DEFINE_RW_EVENT(xfs_file_buffered_write);
DEFINE_RW_EVENT(xfs_file_direct_write);
DEFINE_RW_EVENT(xfs_file_splice_read);
DEFINE_RW_EVENT(xfs_file_splice_write);
+DECLARE_EVENT_CLASS(xfs_page_class,
+ TP_PROTO(struct inode *inode, struct page *page, unsigned long off),
+ TP_ARGS(inode, page, off),
+ TP_STRUCT__entry(
+ __field(dev_t, dev)
+ __field(xfs_ino_t, ino)
+ __field(pgoff_t, pgoff)
+ __field(loff_t, size)
+ __field(unsigned long, offset)
+ __field(int, delalloc)
+ __field(int, unmapped)
+ __field(int, unwritten)
+ ),
+ TP_fast_assign(
+ int delalloc = -1, unmapped = -1, unwritten = -1;
-#define DEFINE_PAGE_EVENT(name) \
-TRACE_EVENT(name, \
- TP_PROTO(struct inode *inode, struct page *page, unsigned long off), \
- TP_ARGS(inode, page, off), \
- TP_STRUCT__entry( \
- __field(dev_t, dev) \
- __field(xfs_ino_t, ino) \
- __field(pgoff_t, pgoff) \
- __field(loff_t, size) \
- __field(unsigned long, offset) \
- __field(int, delalloc) \
- __field(int, unmapped) \
- __field(int, unwritten) \
- ), \
- TP_fast_assign( \
- int delalloc = -1, unmapped = -1, unwritten = -1; \
- \
- if (page_has_buffers(page)) \
- xfs_count_page_state(page, &delalloc, \
- &unmapped, &unwritten); \
- __entry->dev = inode->i_sb->s_dev; \
- __entry->ino = XFS_I(inode)->i_ino; \
- __entry->pgoff = page_offset(page); \
- __entry->size = i_size_read(inode); \
- __entry->offset = off; \
- __entry->delalloc = delalloc; \
- __entry->unmapped = unmapped; \
- __entry->unwritten = unwritten; \
- ), \
- TP_printk("dev %d:%d ino 0x%llx pgoff 0x%lx size 0x%llx offset %lx " \
- "delalloc %d unmapped %d unwritten %d", \
- MAJOR(__entry->dev), MINOR(__entry->dev), \
- __entry->ino, \
- __entry->pgoff, \
- __entry->size, \
- __entry->offset, \
- __entry->delalloc, \
- __entry->unmapped, \
- __entry->unwritten) \
+ if (page_has_buffers(page))
+ xfs_count_page_state(page, &delalloc,
+ &unmapped, &unwritten);
+ __entry->dev = inode->i_sb->s_dev;
+ __entry->ino = XFS_I(inode)->i_ino;
+ __entry->pgoff = page_offset(page);
+ __entry->size = i_size_read(inode);
+ __entry->offset = off;
+ __entry->delalloc = delalloc;
+ __entry->unmapped = unmapped;
+ __entry->unwritten = unwritten;
+ ),
+ TP_printk("dev %d:%d ino 0x%llx pgoff 0x%lx size 0x%llx offset %lx "
+ "delalloc %d unmapped %d unwritten %d",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ __entry->ino,
+ __entry->pgoff,
+ __entry->size,
+ __entry->offset,
+ __entry->delalloc,
+ __entry->unmapped,
+ __entry->unwritten)
)
+
+#define DEFINE_PAGE_EVENT(name) \
+DEFINE_EVENT(xfs_page_class, name, \
+ TP_PROTO(struct inode *inode, struct page *page, unsigned long off), \
+ TP_ARGS(inode, page, off))
DEFINE_PAGE_EVENT(xfs_writepage);
DEFINE_PAGE_EVENT(xfs_releasepage);
DEFINE_PAGE_EVENT(xfs_invalidatepage);
-#define DEFINE_IOMAP_EVENT(name) \
-TRACE_EVENT(name, \
- TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count, \
- int flags, struct xfs_bmbt_irec *irec), \
- TP_ARGS(ip, offset, count, flags, irec), \
- TP_STRUCT__entry( \
- __field(dev_t, dev) \
- __field(xfs_ino_t, ino) \
- __field(loff_t, size) \
- __field(loff_t, new_size) \
- __field(loff_t, offset) \
- __field(size_t, count) \
- __field(int, flags) \
- __field(xfs_fileoff_t, startoff) \
- __field(xfs_fsblock_t, startblock) \
- __field(xfs_filblks_t, blockcount) \
- ), \
- TP_fast_assign( \
- __entry->dev = VFS_I(ip)->i_sb->s_dev; \
- __entry->ino = ip->i_ino; \
- __entry->size = ip->i_d.di_size; \
- __entry->new_size = ip->i_new_size; \
- __entry->offset = offset; \
- __entry->count = count; \
- __entry->flags = flags; \
- __entry->startoff = irec ? irec->br_startoff : 0; \
- __entry->startblock = irec ? irec->br_startblock : 0; \
- __entry->blockcount = irec ? irec->br_blockcount : 0; \
- ), \
- TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx " \
- "offset 0x%llx count %zd flags %s " \
- "startoff 0x%llx startblock %lld blockcount 0x%llx", \
- MAJOR(__entry->dev), MINOR(__entry->dev), \
- __entry->ino, \
- __entry->size, \
- __entry->new_size, \
- __entry->offset, \
- __entry->count, \
- __print_flags(__entry->flags, "|", BMAPI_FLAGS), \
- __entry->startoff, \
- (__int64_t)__entry->startblock, \
- __entry->blockcount) \
+DECLARE_EVENT_CLASS(xfs_iomap_class,
+ TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count,
+ int flags, struct xfs_bmbt_irec *irec),
+ TP_ARGS(ip, offset, count, flags, irec),
+ TP_STRUCT__entry(
+ __field(dev_t, dev)
+ __field(xfs_ino_t, ino)
+ __field(loff_t, size)
+ __field(loff_t, new_size)
+ __field(loff_t, offset)
+ __field(size_t, count)
+ __field(int, flags)
+ __field(xfs_fileoff_t, startoff)
+ __field(xfs_fsblock_t, startblock)
+ __field(xfs_filblks_t, blockcount)
+ ),
+ TP_fast_assign(
+ __entry->dev = VFS_I(ip)->i_sb->s_dev;
+ __entry->ino = ip->i_ino;
+ __entry->size = ip->i_d.di_size;
+ __entry->new_size = ip->i_new_size;
+ __entry->offset = offset;
+ __entry->count = count;
+ __entry->flags = flags;
+ __entry->startoff = irec ? irec->br_startoff : 0;
+ __entry->startblock = irec ? irec->br_startblock : 0;
+ __entry->blockcount = irec ? irec->br_blockcount : 0;
+ ),
+ TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx "
+ "offset 0x%llx count %zd flags %s "
+ "startoff 0x%llx startblock %lld blockcount 0x%llx",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ __entry->ino,
+ __entry->size,
+ __entry->new_size,
+ __entry->offset,
+ __entry->count,
+ __print_flags(__entry->flags, "|", BMAPI_FLAGS),
+ __entry->startoff,
+ (__int64_t)__entry->startblock,
+ __entry->blockcount)
)
+
+#define DEFINE_IOMAP_EVENT(name) \
+DEFINE_EVENT(xfs_iomap_class, name, \
+ TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count, \
+ int flags, struct xfs_bmbt_irec *irec), \
+ TP_ARGS(ip, offset, count, flags, irec))
DEFINE_IOMAP_EVENT(xfs_iomap_enter);
DEFINE_IOMAP_EVENT(xfs_iomap_found);
DEFINE_IOMAP_EVENT(xfs_iomap_alloc);
-#define DEFINE_SIMPLE_IO_EVENT(name) \
-TRACE_EVENT(name, \
- TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count), \
- TP_ARGS(ip, offset, count), \
- TP_STRUCT__entry( \
- __field(dev_t, dev) \
- __field(xfs_ino_t, ino) \
- __field(loff_t, size) \
- __field(loff_t, new_size) \
- __field(loff_t, offset) \
- __field(size_t, count) \
- ), \
- TP_fast_assign( \
- __entry->dev = VFS_I(ip)->i_sb->s_dev; \
- __entry->ino = ip->i_ino; \
- __entry->size = ip->i_d.di_size; \
- __entry->new_size = ip->i_new_size; \
- __entry->offset = offset; \
- __entry->count = count; \
- ), \
- TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx " \
- "offset 0x%llx count %zd", \
- MAJOR(__entry->dev), MINOR(__entry->dev), \
- __entry->ino, \
- __entry->size, \
- __entry->new_size, \
- __entry->offset, \
- __entry->count) \
+DECLARE_EVENT_CLASS(xfs_simple_io_class,
+ TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count),
+ TP_ARGS(ip, offset, count),
+ TP_STRUCT__entry(
+ __field(dev_t, dev)
+ __field(xfs_ino_t, ino)
+ __field(loff_t, size)
+ __field(loff_t, new_size)
+ __field(loff_t, offset)
+ __field(size_t, count)
+ ),
+ TP_fast_assign(
+ __entry->dev = VFS_I(ip)->i_sb->s_dev;
+ __entry->ino = ip->i_ino;
+ __entry->size = ip->i_d.di_size;
+ __entry->new_size = ip->i_new_size;
+ __entry->offset = offset;
+ __entry->count = count;
+ ),
+ TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx "
+ "offset 0x%llx count %zd",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ __entry->ino,
+ __entry->size,
+ __entry->new_size,
+ __entry->offset,
+ __entry->count)
);
+
+#define DEFINE_SIMPLE_IO_EVENT(name) \
+DEFINE_EVENT(xfs_simple_io_class, name, \
+ TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count), \
+ TP_ARGS(ip, offset, count))
DEFINE_SIMPLE_IO_EVENT(xfs_delalloc_enospc);
DEFINE_SIMPLE_IO_EVENT(xfs_unwritten_convert);
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 38e7641..2d8b7bc 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -249,8 +249,10 @@
if (!xfs_Gqm) {
xfs_Gqm = xfs_Gqm_init();
- if (!xfs_Gqm)
+ if (!xfs_Gqm) {
+ mutex_unlock(&xfs_Gqm_lock);
return ENOMEM;
+ }
}
/*
diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h
index 401f364..4917d4e 100644
--- a/fs/xfs/xfs_ag.h
+++ b/fs/xfs/xfs_ag.h
@@ -227,7 +227,6 @@
atomic_t pagf_fstrms; /* # of filestreams active in this AG */
- int pag_ici_init; /* incore inode cache initialised */
rwlock_t pag_ici_lock; /* incore inode lock */
struct radix_tree_root pag_ici_root; /* incore inode cache root */
int pag_ici_reclaimable; /* reclaimable inodes */
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index 6845db9..75df75f 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -382,9 +382,6 @@
/* get the perag structure and ensure that it's inode capable */
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ino));
- if (!pag->pagi_inodeok)
- return EINVAL;
- ASSERT(pag->pag_ici_init);
agino = XFS_INO_TO_AGINO(mp, ino);
again:
@@ -744,30 +741,24 @@
}
#ifdef DEBUG
-/*
- * Debug-only routine, without additional rw_semaphore APIs, we can
- * now only answer requests regarding whether we hold the lock for write
- * (reader state is outside our visibility, we only track writer state).
- *
- * Note: this means !xfs_isilocked would give false positives, so don't do that.
- */
int
xfs_isilocked(
xfs_inode_t *ip,
uint lock_flags)
{
- if ((lock_flags & (XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)) ==
- XFS_ILOCK_EXCL) {
- if (!ip->i_lock.mr_writer)
- return 0;
+ if (lock_flags & (XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)) {
+ if (!(lock_flags & XFS_ILOCK_SHARED))
+ return !!ip->i_lock.mr_writer;
+ return rwsem_is_locked(&ip->i_lock.mr_lock);
}
- if ((lock_flags & (XFS_IOLOCK_EXCL|XFS_IOLOCK_SHARED)) ==
- XFS_IOLOCK_EXCL) {
- if (!ip->i_iolock.mr_writer)
- return 0;
+ if (lock_flags & (XFS_IOLOCK_EXCL|XFS_IOLOCK_SHARED)) {
+ if (!(lock_flags & XFS_IOLOCK_SHARED))
+ return !!ip->i_iolock.mr_writer;
+ return rwsem_is_locked(&ip->i_iolock.mr_lock);
}
- return 1;
+ ASSERT(0);
+ return 0;
}
#endif
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 8cd6e8d..d53c39d 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1940,10 +1940,10 @@
int blks_per_cluster;
int nbufs;
int ninodes;
- int i, j, found, pre_flushed;
+ int i, j;
xfs_daddr_t blkno;
xfs_buf_t *bp;
- xfs_inode_t *ip, **ip_found;
+ xfs_inode_t *ip;
xfs_inode_log_item_t *iip;
xfs_log_item_t *lip;
struct xfs_perag *pag;
@@ -1960,89 +1960,29 @@
nbufs = XFS_IALLOC_BLOCKS(mp) / blks_per_cluster;
}
- ip_found = kmem_alloc(ninodes * sizeof(xfs_inode_t *), KM_NOFS);
-
for (j = 0; j < nbufs; j++, inum += ninodes) {
+ int found = 0;
+
blkno = XFS_AGB_TO_DADDR(mp, XFS_INO_TO_AGNO(mp, inum),
XFS_INO_TO_AGBNO(mp, inum));
-
/*
- * Look for each inode in memory and attempt to lock it,
- * we can be racing with flush and tail pushing here.
- * any inode we get the locks on, add to an array of
- * inode items to process later.
- *
- * The get the buffer lock, we could beat a flush
- * or tail pushing thread to the lock here, in which
- * case they will go looking for the inode buffer
- * and fail, we need some other form of interlock
- * here.
+ * We obtain and lock the backing buffer first in the process
+ * here, as we have to ensure that any dirty inode that we
+ * can't get the flush lock on is attached to the buffer.
+ * If we scan the in-memory inodes first, then buffer IO can
+ * complete before we get a lock on it, and hence we may fail
+ * to mark all the active inodes on the buffer stale.
*/
- found = 0;
- for (i = 0; i < ninodes; i++) {
- read_lock(&pag->pag_ici_lock);
- ip = radix_tree_lookup(&pag->pag_ici_root,
- XFS_INO_TO_AGINO(mp, (inum + i)));
-
- /* Inode not in memory or we found it already,
- * nothing to do
- */
- if (!ip || xfs_iflags_test(ip, XFS_ISTALE)) {
- read_unlock(&pag->pag_ici_lock);
- continue;
- }
-
- if (xfs_inode_clean(ip)) {
- read_unlock(&pag->pag_ici_lock);
- continue;
- }
-
- /* If we can get the locks then add it to the
- * list, otherwise by the time we get the bp lock
- * below it will already be attached to the
- * inode buffer.
- */
-
- /* This inode will already be locked - by us, lets
- * keep it that way.
- */
-
- if (ip == free_ip) {
- if (xfs_iflock_nowait(ip)) {
- xfs_iflags_set(ip, XFS_ISTALE);
- if (xfs_inode_clean(ip)) {
- xfs_ifunlock(ip);
- } else {
- ip_found[found++] = ip;
- }
- }
- read_unlock(&pag->pag_ici_lock);
- continue;
- }
-
- if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) {
- if (xfs_iflock_nowait(ip)) {
- xfs_iflags_set(ip, XFS_ISTALE);
-
- if (xfs_inode_clean(ip)) {
- xfs_ifunlock(ip);
- xfs_iunlock(ip, XFS_ILOCK_EXCL);
- } else {
- ip_found[found++] = ip;
- }
- } else {
- xfs_iunlock(ip, XFS_ILOCK_EXCL);
- }
- }
- read_unlock(&pag->pag_ici_lock);
- }
-
- bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, blkno,
+ bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, blkno,
mp->m_bsize * blks_per_cluster,
XBF_LOCK);
- pre_flushed = 0;
+ /*
+ * Walk the inodes already attached to the buffer and mark them
+ * stale. These will all have the flush locks held, so an
+ * in-memory inode walk can't lock them.
+ */
lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);
while (lip) {
if (lip->li_type == XFS_LI_INODE) {
@@ -2053,21 +1993,64 @@
&iip->ili_flush_lsn,
&iip->ili_item.li_lsn);
xfs_iflags_set(iip->ili_inode, XFS_ISTALE);
- pre_flushed++;
+ found++;
}
lip = lip->li_bio_list;
}
- for (i = 0; i < found; i++) {
- ip = ip_found[i];
- iip = ip->i_itemp;
+ /*
+ * For each inode in memory attempt to add it to the inode
+ * buffer and set it up for being staled on buffer IO
+ * completion. This is safe as we've locked out tail pushing
+ * and flushing by locking the buffer.
+ *
+ * We have already marked every inode that was part of a
+ * transaction stale above, which means there is no point in
+ * even trying to lock them.
+ */
+ for (i = 0; i < ninodes; i++) {
+ read_lock(&pag->pag_ici_lock);
+ ip = radix_tree_lookup(&pag->pag_ici_root,
+ XFS_INO_TO_AGINO(mp, (inum + i)));
+ /* Inode not in memory or stale, nothing to do */
+ if (!ip || xfs_iflags_test(ip, XFS_ISTALE)) {
+ read_unlock(&pag->pag_ici_lock);
+ continue;
+ }
+
+ /* don't try to lock/unlock the current inode */
+ if (ip != free_ip &&
+ !xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) {
+ read_unlock(&pag->pag_ici_lock);
+ continue;
+ }
+ read_unlock(&pag->pag_ici_lock);
+
+ if (!xfs_iflock_nowait(ip)) {
+ if (ip != free_ip)
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+ continue;
+ }
+
+ xfs_iflags_set(ip, XFS_ISTALE);
+ if (xfs_inode_clean(ip)) {
+ ASSERT(ip != free_ip);
+ xfs_ifunlock(ip);
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+ continue;
+ }
+
+ iip = ip->i_itemp;
if (!iip) {
+ /* inode with unlogged changes only */
+ ASSERT(ip != free_ip);
ip->i_update_core = 0;
xfs_ifunlock(ip);
xfs_iunlock(ip, XFS_ILOCK_EXCL);
continue;
}
+ found++;
iip->ili_last_fields = iip->ili_format.ilf_fields;
iip->ili_format.ilf_fields = 0;
@@ -2078,17 +2061,16 @@
xfs_buf_attach_iodone(bp,
(void(*)(xfs_buf_t*,xfs_log_item_t*))
xfs_istale_done, (xfs_log_item_t *)iip);
- if (ip != free_ip) {
+
+ if (ip != free_ip)
xfs_iunlock(ip, XFS_ILOCK_EXCL);
- }
}
- if (found || pre_flushed)
+ if (found)
xfs_trans_stale_inode_buf(tp, bp);
xfs_trans_binval(tp, bp);
}
- kmem_free(ip_found);
xfs_perag_put(pag);
}
@@ -2649,8 +2631,6 @@
int i;
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
- ASSERT(pag->pagi_inodeok);
- ASSERT(pag->pag_ici_init);
inodes_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog;
ilist_size = inodes_per_cluster * sizeof(xfs_inode_t *);
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 14a69ae..ed0684c 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -132,15 +132,10 @@
int nbblks,
xfs_buf_t *bp)
{
- xfs_daddr_t offset;
- xfs_caddr_t ptr;
+ xfs_daddr_t offset = blk_no & ((xfs_daddr_t)log->l_sectBBsize - 1);
- offset = blk_no & ((xfs_daddr_t) log->l_sectBBsize - 1);
- ptr = XFS_BUF_PTR(bp) + BBTOB(offset);
-
- ASSERT(ptr + BBTOB(nbblks) <= XFS_BUF_PTR(bp) + XFS_BUF_SIZE(bp));
-
- return ptr;
+ ASSERT(BBTOB(offset + nbblks) <= XFS_BUF_SIZE(bp));
+ return XFS_BUF_PTR(bp) + BBTOB(offset);
}
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index d7bf38c..d59f4e8 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -268,10 +268,10 @@
#if XFS_BIG_BLKNOS /* Limited by ULONG_MAX of page cache index */
if (nblocks >> (PAGE_CACHE_SHIFT - sbp->sb_blocklog) > ULONG_MAX)
- return E2BIG;
+ return EFBIG;
#else /* Limited by UINT_MAX of sectors */
if (nblocks << (sbp->sb_blocklog - BBSHIFT) > UINT_MAX)
- return E2BIG;
+ return EFBIG;
#endif
return 0;
}
@@ -393,7 +393,7 @@
xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) {
xfs_fs_mount_cmn_err(flags,
"file system too large to be mounted on this system.");
- return XFS_ERROR(E2BIG);
+ return XFS_ERROR(EFBIG);
}
if (unlikely(sbp->sb_inprogress)) {
@@ -413,17 +413,6 @@
return 0;
}
-STATIC void
-xfs_initialize_perag_icache(
- xfs_perag_t *pag)
-{
- if (!pag->pag_ici_init) {
- rwlock_init(&pag->pag_ici_lock);
- INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC);
- pag->pag_ici_init = 1;
- }
-}
-
int
xfs_initialize_perag(
xfs_mount_t *mp,
@@ -436,13 +425,8 @@
xfs_agino_t agino;
xfs_ino_t ino;
xfs_sb_t *sbp = &mp->m_sb;
- xfs_ino_t max_inum = XFS_MAXINUMBER_32;
int error = -ENOMEM;
- /* Check to see if the filesystem can overflow 32 bit inodes */
- agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0);
- ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino);
-
/*
* Walk the current per-ag tree so we don't try to initialise AGs
* that already exist (growfs case). Allocate and insert all the
@@ -456,11 +440,18 @@
}
if (!first_initialised)
first_initialised = index;
+
pag = kmem_zalloc(sizeof(*pag), KM_MAYFAIL);
if (!pag)
goto out_unwind;
+ pag->pag_agno = index;
+ pag->pag_mount = mp;
+ rwlock_init(&pag->pag_ici_lock);
+ INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC);
+
if (radix_tree_preload(GFP_NOFS))
goto out_unwind;
+
spin_lock(&mp->m_perag_lock);
if (radix_tree_insert(&mp->m_perag_tree, index, pag)) {
BUG();
@@ -469,25 +460,26 @@
error = -EEXIST;
goto out_unwind;
}
- pag->pag_agno = index;
- pag->pag_mount = mp;
spin_unlock(&mp->m_perag_lock);
radix_tree_preload_end();
}
- /* Clear the mount flag if no inode can overflow 32 bits
- * on this filesystem, or if specifically requested..
+ /*
+ * If we mount with the inode64 option, or no inode overflows
+ * the legacy 32-bit address space clear the inode32 option.
*/
- if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && ino > max_inum) {
- mp->m_flags |= XFS_MOUNT_32BITINODES;
- } else {
- mp->m_flags &= ~XFS_MOUNT_32BITINODES;
- }
+ agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0);
+ ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino);
- /* If we can overflow then setup the ag headers accordingly */
+ if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && ino > XFS_MAXINUMBER_32)
+ mp->m_flags |= XFS_MOUNT_32BITINODES;
+ else
+ mp->m_flags &= ~XFS_MOUNT_32BITINODES;
+
if (mp->m_flags & XFS_MOUNT_32BITINODES) {
- /* Calculate how much should be reserved for inodes to
- * meet the max inode percentage.
+ /*
+ * Calculate how much should be reserved for inodes to meet
+ * the max inode percentage.
*/
if (mp->m_maxicount) {
__uint64_t icount;
@@ -500,30 +492,28 @@
} else {
max_metadata = agcount;
}
+
for (index = 0; index < agcount; index++) {
ino = XFS_AGINO_TO_INO(mp, index, agino);
- if (ino > max_inum) {
+ if (ino > XFS_MAXINUMBER_32) {
index++;
break;
}
- /* This ag is preferred for inodes */
pag = xfs_perag_get(mp, index);
pag->pagi_inodeok = 1;
if (index < max_metadata)
pag->pagf_metadata = 1;
- xfs_initialize_perag_icache(pag);
xfs_perag_put(pag);
}
} else {
- /* Setup default behavior for smaller filesystems */
for (index = 0; index < agcount; index++) {
pag = xfs_perag_get(mp, index);
pag->pagi_inodeok = 1;
- xfs_initialize_perag_icache(pag);
xfs_perag_put(pag);
}
}
+
if (maxagi)
*maxagi = index;
return 0;
@@ -1009,7 +999,7 @@
d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) {
cmn_err(CE_WARN, "XFS: size check 1 failed");
- return XFS_ERROR(E2BIG);
+ return XFS_ERROR(EFBIG);
}
error = xfs_read_buf(mp, mp->m_ddev_targp,
d - XFS_FSS_TO_BB(mp, 1),
@@ -1019,7 +1009,7 @@
} else {
cmn_err(CE_WARN, "XFS: size check 2 failed");
if (error == ENOSPC)
- error = XFS_ERROR(E2BIG);
+ error = XFS_ERROR(EFBIG);
return error;
}
@@ -1027,7 +1017,7 @@
d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) {
cmn_err(CE_WARN, "XFS: size check 3 failed");
- return XFS_ERROR(E2BIG);
+ return XFS_ERROR(EFBIG);
}
error = xfs_read_buf(mp, mp->m_logdev_targp,
d - XFS_FSB_TO_BB(mp, 1),
@@ -1037,7 +1027,7 @@
} else {
cmn_err(CE_WARN, "XFS: size check 3 failed");
if (error == ENOSPC)
- error = XFS_ERROR(E2BIG);
+ error = XFS_ERROR(EFBIG);
return error;
}
}
@@ -1254,7 +1244,7 @@
* Allocate and initialize the per-ag data.
*/
spin_lock_init(&mp->m_perag_lock);
- INIT_RADIX_TREE(&mp->m_perag_tree, GFP_NOFS);
+ INIT_RADIX_TREE(&mp->m_perag_tree, GFP_ATOMIC);
error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi);
if (error) {
cmn_err(CE_WARN, "XFS: Failed per-ag init: %d", error);
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 6be05f7..1644551 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -2247,7 +2247,7 @@
cmn_err(CE_WARN, "XFS: realtime mount -- %llu != %llu",
(unsigned long long) XFS_BB_TO_FSB(mp, d),
(unsigned long long) mp->m_sb.sb_rblocks);
- return XFS_ERROR(E2BIG);
+ return XFS_ERROR(EFBIG);
}
error = xfs_read_buf(mp, mp->m_rtdev_targp,
d - XFS_FSB_TO_BB(mp, 1),
@@ -2256,7 +2256,7 @@
cmn_err(CE_WARN,
"XFS: realtime mount -- xfs_read_buf failed, returned %d", error);
if (error == ENOSPC)
- return XFS_ERROR(E2BIG);
+ return XFS_ERROR(EFBIG);
return error;
}
xfs_buf_relse(bp);
diff --git a/fs/xfs/xfs_rtalloc.h b/fs/xfs/xfs_rtalloc.h
index b2d67ad..ff614c2 100644
--- a/fs/xfs/xfs_rtalloc.h
+++ b/fs/xfs/xfs_rtalloc.h
@@ -147,7 +147,16 @@
# define xfs_rtfree_extent(t,b,l) (ENOSYS)
# define xfs_rtpick_extent(m,t,l,rb) (ENOSYS)
# define xfs_growfs_rt(mp,in) (ENOSYS)
-# define xfs_rtmount_init(m) (((mp)->m_sb.sb_rblocks == 0)? 0 : (ENOSYS))
+static inline int /* error */
+xfs_rtmount_init(
+ xfs_mount_t *mp) /* file system mount structure */
+{
+ if (mp->m_sb.sb_rblocks == 0)
+ return 0;
+
+ cmn_err(CE_WARN, "XFS: Not built with CONFIG_XFS_RT");
+ return ENOSYS;
+}
# define xfs_rtmount_inodes(m) (((mp)->m_sb.sb_rblocks == 0)? 0 : (ENOSYS))
# define xfs_rtunmount_inodes(m)
#endif /* CONFIG_XFS_RT */
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index ce558ef..28547df 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -48,134 +48,489 @@
kmem_zone_t *xfs_trans_zone;
+
/*
- * Reservation functions here avoid a huge stack in xfs_trans_init
- * due to register overflow from temporaries in the calculations.
+ * Various log reservation values.
+ *
+ * These are based on the size of the file system block because that is what
+ * most transactions manipulate. Each adds in an additional 128 bytes per
+ * item logged to try to account for the overhead of the transaction mechanism.
+ *
+ * Note: Most of the reservations underestimate the number of allocation
+ * groups into which they could free extents in the xfs_bmap_finish() call.
+ * This is because the number in the worst case is quite high and quite
+ * unusual. In order to fix this we need to change xfs_bmap_finish() to free
+ * extents in only a single AG at a time. This will require changes to the
+ * EFI code as well, however, so that the EFI for the extents not freed is
+ * logged again in each transaction. See SGI PV #261917.
+ *
+ * Reservation functions here avoid a huge stack in xfs_trans_init due to
+ * register overflow from temporaries in the calculations.
+ */
+
+
+/*
+ * In a write transaction we can allocate a maximum of 2
+ * extents. This gives:
+ * the inode getting the new extents: inode size
+ * the inode's bmap btree: max depth * block size
+ * the agfs of the ags from which the extents are allocated: 2 * sector
+ * the superblock free block counter: sector size
+ * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
+ * And the bmap_finish transaction can free bmap blocks in a join:
+ * the agfs of the ags containing the blocks: 2 * sector size
+ * the agfls of the ags containing the blocks: 2 * sector size
+ * the super block free block counter: sector size
+ * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
*/
STATIC uint
-xfs_calc_write_reservation(xfs_mount_t *mp)
+xfs_calc_write_reservation(
+ struct xfs_mount *mp)
{
- return XFS_CALC_WRITE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+ return XFS_DQUOT_LOGRES(mp) +
+ MAX((mp->m_sb.sb_inodesize +
+ XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)) +
+ 2 * mp->m_sb.sb_sectsize +
+ mp->m_sb.sb_sectsize +
+ XFS_ALLOCFREE_LOG_RES(mp, 2) +
+ 128 * (4 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) +
+ XFS_ALLOCFREE_LOG_COUNT(mp, 2))),
+ (2 * mp->m_sb.sb_sectsize +
+ 2 * mp->m_sb.sb_sectsize +
+ mp->m_sb.sb_sectsize +
+ XFS_ALLOCFREE_LOG_RES(mp, 2) +
+ 128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))));
}
+/*
+ * In truncating a file we free up to two extents at once. We can modify:
+ * the inode being truncated: inode size
+ * the inode's bmap btree: (max depth + 1) * block size
+ * And the bmap_finish transaction can free the blocks and bmap blocks:
+ * the agf for each of the ags: 4 * sector size
+ * the agfl for each of the ags: 4 * sector size
+ * the super block to reflect the freed blocks: sector size
+ * worst case split in allocation btrees per extent assuming 4 extents:
+ * 4 exts * 2 trees * (2 * max depth - 1) * block size
+ * the inode btree: max depth * blocksize
+ * the allocation btrees: 2 trees * (max depth - 1) * block size
+ */
STATIC uint
-xfs_calc_itruncate_reservation(xfs_mount_t *mp)
+xfs_calc_itruncate_reservation(
+ struct xfs_mount *mp)
{
- return XFS_CALC_ITRUNCATE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+ return XFS_DQUOT_LOGRES(mp) +
+ MAX((mp->m_sb.sb_inodesize +
+ XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1) +
+ 128 * (2 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK))),
+ (4 * mp->m_sb.sb_sectsize +
+ 4 * mp->m_sb.sb_sectsize +
+ mp->m_sb.sb_sectsize +
+ XFS_ALLOCFREE_LOG_RES(mp, 4) +
+ 128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4)) +
+ 128 * 5 +
+ XFS_ALLOCFREE_LOG_RES(mp, 1) +
+ 128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels +
+ XFS_ALLOCFREE_LOG_COUNT(mp, 1))));
}
+/*
+ * In renaming a files we can modify:
+ * the four inodes involved: 4 * inode size
+ * the two directory btrees: 2 * (max depth + v2) * dir block size
+ * the two directory bmap btrees: 2 * max depth * block size
+ * And the bmap_finish transaction can free dir and bmap blocks (two sets
+ * of bmap blocks) giving:
+ * the agf for the ags in which the blocks live: 3 * sector size
+ * the agfl for the ags in which the blocks live: 3 * sector size
+ * the superblock for the free block count: sector size
+ * the allocation btrees: 3 exts * 2 trees * (2 * max depth - 1) * block size
+ */
STATIC uint
-xfs_calc_rename_reservation(xfs_mount_t *mp)
+xfs_calc_rename_reservation(
+ struct xfs_mount *mp)
{
- return XFS_CALC_RENAME_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+ return XFS_DQUOT_LOGRES(mp) +
+ MAX((4 * mp->m_sb.sb_inodesize +
+ 2 * XFS_DIROP_LOG_RES(mp) +
+ 128 * (4 + 2 * XFS_DIROP_LOG_COUNT(mp))),
+ (3 * mp->m_sb.sb_sectsize +
+ 3 * mp->m_sb.sb_sectsize +
+ mp->m_sb.sb_sectsize +
+ XFS_ALLOCFREE_LOG_RES(mp, 3) +
+ 128 * (7 + XFS_ALLOCFREE_LOG_COUNT(mp, 3))));
}
+/*
+ * For creating a link to an inode:
+ * the parent directory inode: inode size
+ * the linked inode: inode size
+ * the directory btree could split: (max depth + v2) * dir block size
+ * the directory bmap btree could join or split: (max depth + v2) * blocksize
+ * And the bmap_finish transaction can free some bmap blocks giving:
+ * the agf for the ag in which the blocks live: sector size
+ * the agfl for the ag in which the blocks live: sector size
+ * the superblock for the free block count: sector size
+ * the allocation btrees: 2 trees * (2 * max depth - 1) * block size
+ */
STATIC uint
-xfs_calc_link_reservation(xfs_mount_t *mp)
+xfs_calc_link_reservation(
+ struct xfs_mount *mp)
{
- return XFS_CALC_LINK_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+ return XFS_DQUOT_LOGRES(mp) +
+ MAX((mp->m_sb.sb_inodesize +
+ mp->m_sb.sb_inodesize +
+ XFS_DIROP_LOG_RES(mp) +
+ 128 * (2 + XFS_DIROP_LOG_COUNT(mp))),
+ (mp->m_sb.sb_sectsize +
+ mp->m_sb.sb_sectsize +
+ mp->m_sb.sb_sectsize +
+ XFS_ALLOCFREE_LOG_RES(mp, 1) +
+ 128 * (3 + XFS_ALLOCFREE_LOG_COUNT(mp, 1))));
}
+/*
+ * For removing a directory entry we can modify:
+ * the parent directory inode: inode size
+ * the removed inode: inode size
+ * the directory btree could join: (max depth + v2) * dir block size
+ * the directory bmap btree could join or split: (max depth + v2) * blocksize
+ * And the bmap_finish transaction can free the dir and bmap blocks giving:
+ * the agf for the ag in which the blocks live: 2 * sector size
+ * the agfl for the ag in which the blocks live: 2 * sector size
+ * the superblock for the free block count: sector size
+ * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
+ */
STATIC uint
-xfs_calc_remove_reservation(xfs_mount_t *mp)
+xfs_calc_remove_reservation(
+ struct xfs_mount *mp)
{
- return XFS_CALC_REMOVE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+ return XFS_DQUOT_LOGRES(mp) +
+ MAX((mp->m_sb.sb_inodesize +
+ mp->m_sb.sb_inodesize +
+ XFS_DIROP_LOG_RES(mp) +
+ 128 * (2 + XFS_DIROP_LOG_COUNT(mp))),
+ (2 * mp->m_sb.sb_sectsize +
+ 2 * mp->m_sb.sb_sectsize +
+ mp->m_sb.sb_sectsize +
+ XFS_ALLOCFREE_LOG_RES(mp, 2) +
+ 128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))));
}
+/*
+ * For symlink we can modify:
+ * the parent directory inode: inode size
+ * the new inode: inode size
+ * the inode btree entry: 1 block
+ * the directory btree: (max depth + v2) * dir block size
+ * the directory inode's bmap btree: (max depth + v2) * block size
+ * the blocks for the symlink: 1 kB
+ * Or in the first xact we allocate some inodes giving:
+ * the agi and agf of the ag getting the new inodes: 2 * sectorsize
+ * the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize
+ * the inode btree: max depth * blocksize
+ * the allocation btrees: 2 trees * (2 * max depth - 1) * block size
+ */
STATIC uint
-xfs_calc_symlink_reservation(xfs_mount_t *mp)
+xfs_calc_symlink_reservation(
+ struct xfs_mount *mp)
{
- return XFS_CALC_SYMLINK_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+ return XFS_DQUOT_LOGRES(mp) +
+ MAX((mp->m_sb.sb_inodesize +
+ mp->m_sb.sb_inodesize +
+ XFS_FSB_TO_B(mp, 1) +
+ XFS_DIROP_LOG_RES(mp) +
+ 1024 +
+ 128 * (4 + XFS_DIROP_LOG_COUNT(mp))),
+ (2 * mp->m_sb.sb_sectsize +
+ XFS_FSB_TO_B(mp, XFS_IALLOC_BLOCKS(mp)) +
+ XFS_FSB_TO_B(mp, mp->m_in_maxlevels) +
+ XFS_ALLOCFREE_LOG_RES(mp, 1) +
+ 128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels +
+ XFS_ALLOCFREE_LOG_COUNT(mp, 1))));
}
+/*
+ * For create we can modify:
+ * the parent directory inode: inode size
+ * the new inode: inode size
+ * the inode btree entry: block size
+ * the superblock for the nlink flag: sector size
+ * the directory btree: (max depth + v2) * dir block size
+ * the directory inode's bmap btree: (max depth + v2) * block size
+ * Or in the first xact we allocate some inodes giving:
+ * the agi and agf of the ag getting the new inodes: 2 * sectorsize
+ * the superblock for the nlink flag: sector size
+ * the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize
+ * the inode btree: max depth * blocksize
+ * the allocation btrees: 2 trees * (max depth - 1) * block size
+ */
STATIC uint
-xfs_calc_create_reservation(xfs_mount_t *mp)
+xfs_calc_create_reservation(
+ struct xfs_mount *mp)
{
- return XFS_CALC_CREATE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+ return XFS_DQUOT_LOGRES(mp) +
+ MAX((mp->m_sb.sb_inodesize +
+ mp->m_sb.sb_inodesize +
+ mp->m_sb.sb_sectsize +
+ XFS_FSB_TO_B(mp, 1) +
+ XFS_DIROP_LOG_RES(mp) +
+ 128 * (3 + XFS_DIROP_LOG_COUNT(mp))),
+ (3 * mp->m_sb.sb_sectsize +
+ XFS_FSB_TO_B(mp, XFS_IALLOC_BLOCKS(mp)) +
+ XFS_FSB_TO_B(mp, mp->m_in_maxlevels) +
+ XFS_ALLOCFREE_LOG_RES(mp, 1) +
+ 128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels +
+ XFS_ALLOCFREE_LOG_COUNT(mp, 1))));
}
+/*
+ * Making a new directory is the same as creating a new file.
+ */
STATIC uint
-xfs_calc_mkdir_reservation(xfs_mount_t *mp)
+xfs_calc_mkdir_reservation(
+ struct xfs_mount *mp)
{
- return XFS_CALC_MKDIR_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+ return xfs_calc_create_reservation(mp);
}
+/*
+ * In freeing an inode we can modify:
+ * the inode being freed: inode size
+ * the super block free inode counter: sector size
+ * the agi hash list and counters: sector size
+ * the inode btree entry: block size
+ * the on disk inode before ours in the agi hash list: inode cluster size
+ * the inode btree: max depth * blocksize
+ * the allocation btrees: 2 trees * (max depth - 1) * block size
+ */
STATIC uint
-xfs_calc_ifree_reservation(xfs_mount_t *mp)
+xfs_calc_ifree_reservation(
+ struct xfs_mount *mp)
{
- return XFS_CALC_IFREE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+ return XFS_DQUOT_LOGRES(mp) +
+ mp->m_sb.sb_inodesize +
+ mp->m_sb.sb_sectsize +
+ mp->m_sb.sb_sectsize +
+ XFS_FSB_TO_B(mp, 1) +
+ MAX((__uint16_t)XFS_FSB_TO_B(mp, 1),
+ XFS_INODE_CLUSTER_SIZE(mp)) +
+ 128 * 5 +
+ XFS_ALLOCFREE_LOG_RES(mp, 1) +
+ 128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels +
+ XFS_ALLOCFREE_LOG_COUNT(mp, 1));
}
+/*
+ * When only changing the inode we log the inode and possibly the superblock
+ * We also add a bit of slop for the transaction stuff.
+ */
STATIC uint
-xfs_calc_ichange_reservation(xfs_mount_t *mp)
+xfs_calc_ichange_reservation(
+ struct xfs_mount *mp)
{
- return XFS_CALC_ICHANGE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+ return XFS_DQUOT_LOGRES(mp) +
+ mp->m_sb.sb_inodesize +
+ mp->m_sb.sb_sectsize +
+ 512;
+
}
+/*
+ * Growing the data section of the filesystem.
+ * superblock
+ * agi and agf
+ * allocation btrees
+ */
STATIC uint
-xfs_calc_growdata_reservation(xfs_mount_t *mp)
+xfs_calc_growdata_reservation(
+ struct xfs_mount *mp)
{
- return XFS_CALC_GROWDATA_LOG_RES(mp);
+ return mp->m_sb.sb_sectsize * 3 +
+ XFS_ALLOCFREE_LOG_RES(mp, 1) +
+ 128 * (3 + XFS_ALLOCFREE_LOG_COUNT(mp, 1));
}
+/*
+ * Growing the rt section of the filesystem.
+ * In the first set of transactions (ALLOC) we allocate space to the
+ * bitmap or summary files.
+ * superblock: sector size
+ * agf of the ag from which the extent is allocated: sector size
+ * bmap btree for bitmap/summary inode: max depth * blocksize
+ * bitmap/summary inode: inode size
+ * allocation btrees for 1 block alloc: 2 * (2 * maxdepth - 1) * blocksize
+ */
STATIC uint
-xfs_calc_growrtalloc_reservation(xfs_mount_t *mp)
+xfs_calc_growrtalloc_reservation(
+ struct xfs_mount *mp)
{
- return XFS_CALC_GROWRTALLOC_LOG_RES(mp);
+ return 2 * mp->m_sb.sb_sectsize +
+ XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)) +
+ mp->m_sb.sb_inodesize +
+ XFS_ALLOCFREE_LOG_RES(mp, 1) +
+ 128 * (3 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) +
+ XFS_ALLOCFREE_LOG_COUNT(mp, 1));
}
+/*
+ * Growing the rt section of the filesystem.
+ * In the second set of transactions (ZERO) we zero the new metadata blocks.
+ * one bitmap/summary block: blocksize
+ */
STATIC uint
-xfs_calc_growrtzero_reservation(xfs_mount_t *mp)
+xfs_calc_growrtzero_reservation(
+ struct xfs_mount *mp)
{
- return XFS_CALC_GROWRTZERO_LOG_RES(mp);
+ return mp->m_sb.sb_blocksize + 128;
}
+/*
+ * Growing the rt section of the filesystem.
+ * In the third set of transactions (FREE) we update metadata without
+ * allocating any new blocks.
+ * superblock: sector size
+ * bitmap inode: inode size
+ * summary inode: inode size
+ * one bitmap block: blocksize
+ * summary blocks: new summary size
+ */
STATIC uint
-xfs_calc_growrtfree_reservation(xfs_mount_t *mp)
+xfs_calc_growrtfree_reservation(
+ struct xfs_mount *mp)
{
- return XFS_CALC_GROWRTFREE_LOG_RES(mp);
+ return mp->m_sb.sb_sectsize +
+ 2 * mp->m_sb.sb_inodesize +
+ mp->m_sb.sb_blocksize +
+ mp->m_rsumsize +
+ 128 * 5;
}
+/*
+ * Logging the inode modification timestamp on a synchronous write.
+ * inode
+ */
STATIC uint
-xfs_calc_swrite_reservation(xfs_mount_t *mp)
+xfs_calc_swrite_reservation(
+ struct xfs_mount *mp)
{
- return XFS_CALC_SWRITE_LOG_RES(mp);
+ return mp->m_sb.sb_inodesize + 128;
}
+/*
+ * Logging the inode mode bits when writing a setuid/setgid file
+ * inode
+ */
STATIC uint
xfs_calc_writeid_reservation(xfs_mount_t *mp)
{
- return XFS_CALC_WRITEID_LOG_RES(mp);
+ return mp->m_sb.sb_inodesize + 128;
}
+/*
+ * Converting the inode from non-attributed to attributed.
+ * the inode being converted: inode size
+ * agf block and superblock (for block allocation)
+ * the new block (directory sized)
+ * bmap blocks for the new directory block
+ * allocation btrees
+ */
STATIC uint
-xfs_calc_addafork_reservation(xfs_mount_t *mp)
+xfs_calc_addafork_reservation(
+ struct xfs_mount *mp)
{
- return XFS_CALC_ADDAFORK_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+ return XFS_DQUOT_LOGRES(mp) +
+ mp->m_sb.sb_inodesize +
+ mp->m_sb.sb_sectsize * 2 +
+ mp->m_dirblksize +
+ XFS_FSB_TO_B(mp, XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1) +
+ XFS_ALLOCFREE_LOG_RES(mp, 1) +
+ 128 * (4 + XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1 +
+ XFS_ALLOCFREE_LOG_COUNT(mp, 1));
}
+/*
+ * Removing the attribute fork of a file
+ * the inode being truncated: inode size
+ * the inode's bmap btree: max depth * block size
+ * And the bmap_finish transaction can free the blocks and bmap blocks:
+ * the agf for each of the ags: 4 * sector size
+ * the agfl for each of the ags: 4 * sector size
+ * the super block to reflect the freed blocks: sector size
+ * worst case split in allocation btrees per extent assuming 4 extents:
+ * 4 exts * 2 trees * (2 * max depth - 1) * block size
+ */
STATIC uint
-xfs_calc_attrinval_reservation(xfs_mount_t *mp)
+xfs_calc_attrinval_reservation(
+ struct xfs_mount *mp)
{
- return XFS_CALC_ATTRINVAL_LOG_RES(mp);
+ return MAX((mp->m_sb.sb_inodesize +
+ XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) +
+ 128 * (1 + XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK))),
+ (4 * mp->m_sb.sb_sectsize +
+ 4 * mp->m_sb.sb_sectsize +
+ mp->m_sb.sb_sectsize +
+ XFS_ALLOCFREE_LOG_RES(mp, 4) +
+ 128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4))));
}
+/*
+ * Setting an attribute.
+ * the inode getting the attribute
+ * the superblock for allocations
+ * the agfs extents are allocated from
+ * the attribute btree * max depth
+ * the inode allocation btree
+ * Since attribute transaction space is dependent on the size of the attribute,
+ * the calculation is done partially at mount time and partially at runtime.
+ */
STATIC uint
-xfs_calc_attrset_reservation(xfs_mount_t *mp)
+xfs_calc_attrset_reservation(
+ struct xfs_mount *mp)
{
- return XFS_CALC_ATTRSET_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+ return XFS_DQUOT_LOGRES(mp) +
+ mp->m_sb.sb_inodesize +
+ mp->m_sb.sb_sectsize +
+ XFS_FSB_TO_B(mp, XFS_DA_NODE_MAXDEPTH) +
+ 128 * (2 + XFS_DA_NODE_MAXDEPTH);
}
+/*
+ * Removing an attribute.
+ * the inode: inode size
+ * the attribute btree could join: max depth * block size
+ * the inode bmap btree could join or split: max depth * block size
+ * And the bmap_finish transaction can free the attr blocks freed giving:
+ * the agf for the ag in which the blocks live: 2 * sector size
+ * the agfl for the ag in which the blocks live: 2 * sector size
+ * the superblock for the free block count: sector size
+ * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
+ */
STATIC uint
-xfs_calc_attrrm_reservation(xfs_mount_t *mp)
+xfs_calc_attrrm_reservation(
+ struct xfs_mount *mp)
{
- return XFS_CALC_ATTRRM_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
+ return XFS_DQUOT_LOGRES(mp) +
+ MAX((mp->m_sb.sb_inodesize +
+ XFS_FSB_TO_B(mp, XFS_DA_NODE_MAXDEPTH) +
+ XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) +
+ 128 * (1 + XFS_DA_NODE_MAXDEPTH +
+ XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK))),
+ (2 * mp->m_sb.sb_sectsize +
+ 2 * mp->m_sb.sb_sectsize +
+ mp->m_sb.sb_sectsize +
+ XFS_ALLOCFREE_LOG_RES(mp, 2) +
+ 128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))));
}
+/*
+ * Clearing a bad agino number in an agi hash bucket.
+ */
STATIC uint
-xfs_calc_clear_agi_bucket_reservation(xfs_mount_t *mp)
+xfs_calc_clear_agi_bucket_reservation(
+ struct xfs_mount *mp)
{
- return XFS_CALC_CLEAR_AGI_BUCKET_LOG_RES(mp);
+ return mp->m_sb.sb_sectsize + 128;
}
/*
@@ -184,11 +539,10 @@
*/
void
xfs_trans_init(
- xfs_mount_t *mp)
+ struct xfs_mount *mp)
{
- xfs_trans_reservations_t *resp;
+ struct xfs_trans_reservations *resp = &mp->m_reservations;
- resp = &(mp->m_reservations);
resp->tr_write = xfs_calc_write_reservation(mp);
resp->tr_itruncate = xfs_calc_itruncate_reservation(mp);
resp->tr_rename = xfs_calc_rename_reservation(mp);
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 8c69e78..e639e8e 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -300,24 +300,6 @@
/*
- * Various log reservation values.
- * These are based on the size of the file system block
- * because that is what most transactions manipulate.
- * Each adds in an additional 128 bytes per item logged to
- * try to account for the overhead of the transaction mechanism.
- *
- * Note:
- * Most of the reservations underestimate the number of allocation
- * groups into which they could free extents in the xfs_bmap_finish()
- * call. This is because the number in the worst case is quite high
- * and quite unusual. In order to fix this we need to change
- * xfs_bmap_finish() to free extents in only a single AG at a time.
- * This will require changes to the EFI code as well, however, so that
- * the EFI for the extents not freed is logged again in each transaction.
- * See bug 261917.
- */
-
-/*
* Per-extent log reservation for the allocation btree changes
* involved in freeing or allocating an extent.
* 2 trees * (2 blocks/level * max depth - 1) * block size
@@ -341,429 +323,36 @@
(XFS_DAENTER_BLOCKS(mp, XFS_DATA_FORK) + \
XFS_DAENTER_BMAPS(mp, XFS_DATA_FORK) + 1)
-/*
- * In a write transaction we can allocate a maximum of 2
- * extents. This gives:
- * the inode getting the new extents: inode size
- * the inode's bmap btree: max depth * block size
- * the agfs of the ags from which the extents are allocated: 2 * sector
- * the superblock free block counter: sector size
- * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
- * And the bmap_finish transaction can free bmap blocks in a join:
- * the agfs of the ags containing the blocks: 2 * sector size
- * the agfls of the ags containing the blocks: 2 * sector size
- * the super block free block counter: sector size
- * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
- */
-#define XFS_CALC_WRITE_LOG_RES(mp) \
- (MAX( \
- ((mp)->m_sb.sb_inodesize + \
- XFS_FSB_TO_B((mp), XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)) + \
- (2 * (mp)->m_sb.sb_sectsize) + \
- (mp)->m_sb.sb_sectsize + \
- XFS_ALLOCFREE_LOG_RES(mp, 2) + \
- (128 * (4 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + XFS_ALLOCFREE_LOG_COUNT(mp, 2)))),\
- ((2 * (mp)->m_sb.sb_sectsize) + \
- (2 * (mp)->m_sb.sb_sectsize) + \
- (mp)->m_sb.sb_sectsize + \
- XFS_ALLOCFREE_LOG_RES(mp, 2) + \
- (128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))))))
#define XFS_WRITE_LOG_RES(mp) ((mp)->m_reservations.tr_write)
-
-/*
- * In truncating a file we free up to two extents at once. We can modify:
- * the inode being truncated: inode size
- * the inode's bmap btree: (max depth + 1) * block size
- * And the bmap_finish transaction can free the blocks and bmap blocks:
- * the agf for each of the ags: 4 * sector size
- * the agfl for each of the ags: 4 * sector size
- * the super block to reflect the freed blocks: sector size
- * worst case split in allocation btrees per extent assuming 4 extents:
- * 4 exts * 2 trees * (2 * max depth - 1) * block size
- * the inode btree: max depth * blocksize
- * the allocation btrees: 2 trees * (max depth - 1) * block size
- */
-#define XFS_CALC_ITRUNCATE_LOG_RES(mp) \
- (MAX( \
- ((mp)->m_sb.sb_inodesize + \
- XFS_FSB_TO_B((mp), XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1) + \
- (128 * (2 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)))), \
- ((4 * (mp)->m_sb.sb_sectsize) + \
- (4 * (mp)->m_sb.sb_sectsize) + \
- (mp)->m_sb.sb_sectsize + \
- XFS_ALLOCFREE_LOG_RES(mp, 4) + \
- (128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4))) + \
- (128 * 5) + \
- XFS_ALLOCFREE_LOG_RES(mp, 1) + \
- (128 * (2 + XFS_IALLOC_BLOCKS(mp) + (mp)->m_in_maxlevels + \
- XFS_ALLOCFREE_LOG_COUNT(mp, 1))))))
-
#define XFS_ITRUNCATE_LOG_RES(mp) ((mp)->m_reservations.tr_itruncate)
-
-/*
- * In renaming a files we can modify:
- * the four inodes involved: 4 * inode size
- * the two directory btrees: 2 * (max depth + v2) * dir block size
- * the two directory bmap btrees: 2 * max depth * block size
- * And the bmap_finish transaction can free dir and bmap blocks (two sets
- * of bmap blocks) giving:
- * the agf for the ags in which the blocks live: 3 * sector size
- * the agfl for the ags in which the blocks live: 3 * sector size
- * the superblock for the free block count: sector size
- * the allocation btrees: 3 exts * 2 trees * (2 * max depth - 1) * block size
- */
-#define XFS_CALC_RENAME_LOG_RES(mp) \
- (MAX( \
- ((4 * (mp)->m_sb.sb_inodesize) + \
- (2 * XFS_DIROP_LOG_RES(mp)) + \
- (128 * (4 + 2 * XFS_DIROP_LOG_COUNT(mp)))), \
- ((3 * (mp)->m_sb.sb_sectsize) + \
- (3 * (mp)->m_sb.sb_sectsize) + \
- (mp)->m_sb.sb_sectsize + \
- XFS_ALLOCFREE_LOG_RES(mp, 3) + \
- (128 * (7 + XFS_ALLOCFREE_LOG_COUNT(mp, 3))))))
-
#define XFS_RENAME_LOG_RES(mp) ((mp)->m_reservations.tr_rename)
-
-/*
- * For creating a link to an inode:
- * the parent directory inode: inode size
- * the linked inode: inode size
- * the directory btree could split: (max depth + v2) * dir block size
- * the directory bmap btree could join or split: (max depth + v2) * blocksize
- * And the bmap_finish transaction can free some bmap blocks giving:
- * the agf for the ag in which the blocks live: sector size
- * the agfl for the ag in which the blocks live: sector size
- * the superblock for the free block count: sector size
- * the allocation btrees: 2 trees * (2 * max depth - 1) * block size
- */
-#define XFS_CALC_LINK_LOG_RES(mp) \
- (MAX( \
- ((mp)->m_sb.sb_inodesize + \
- (mp)->m_sb.sb_inodesize + \
- XFS_DIROP_LOG_RES(mp) + \
- (128 * (2 + XFS_DIROP_LOG_COUNT(mp)))), \
- ((mp)->m_sb.sb_sectsize + \
- (mp)->m_sb.sb_sectsize + \
- (mp)->m_sb.sb_sectsize + \
- XFS_ALLOCFREE_LOG_RES(mp, 1) + \
- (128 * (3 + XFS_ALLOCFREE_LOG_COUNT(mp, 1))))))
-
#define XFS_LINK_LOG_RES(mp) ((mp)->m_reservations.tr_link)
-
-/*
- * For removing a directory entry we can modify:
- * the parent directory inode: inode size
- * the removed inode: inode size
- * the directory btree could join: (max depth + v2) * dir block size
- * the directory bmap btree could join or split: (max depth + v2) * blocksize
- * And the bmap_finish transaction can free the dir and bmap blocks giving:
- * the agf for the ag in which the blocks live: 2 * sector size
- * the agfl for the ag in which the blocks live: 2 * sector size
- * the superblock for the free block count: sector size
- * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
- */
-#define XFS_CALC_REMOVE_LOG_RES(mp) \
- (MAX( \
- ((mp)->m_sb.sb_inodesize + \
- (mp)->m_sb.sb_inodesize + \
- XFS_DIROP_LOG_RES(mp) + \
- (128 * (2 + XFS_DIROP_LOG_COUNT(mp)))), \
- ((2 * (mp)->m_sb.sb_sectsize) + \
- (2 * (mp)->m_sb.sb_sectsize) + \
- (mp)->m_sb.sb_sectsize + \
- XFS_ALLOCFREE_LOG_RES(mp, 2) + \
- (128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))))))
-
#define XFS_REMOVE_LOG_RES(mp) ((mp)->m_reservations.tr_remove)
-
-/*
- * For symlink we can modify:
- * the parent directory inode: inode size
- * the new inode: inode size
- * the inode btree entry: 1 block
- * the directory btree: (max depth + v2) * dir block size
- * the directory inode's bmap btree: (max depth + v2) * block size
- * the blocks for the symlink: 1 kB
- * Or in the first xact we allocate some inodes giving:
- * the agi and agf of the ag getting the new inodes: 2 * sectorsize
- * the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize
- * the inode btree: max depth * blocksize
- * the allocation btrees: 2 trees * (2 * max depth - 1) * block size
- */
-#define XFS_CALC_SYMLINK_LOG_RES(mp) \
- (MAX( \
- ((mp)->m_sb.sb_inodesize + \
- (mp)->m_sb.sb_inodesize + \
- XFS_FSB_TO_B(mp, 1) + \
- XFS_DIROP_LOG_RES(mp) + \
- 1024 + \
- (128 * (4 + XFS_DIROP_LOG_COUNT(mp)))), \
- (2 * (mp)->m_sb.sb_sectsize + \
- XFS_FSB_TO_B((mp), XFS_IALLOC_BLOCKS((mp))) + \
- XFS_FSB_TO_B((mp), (mp)->m_in_maxlevels) + \
- XFS_ALLOCFREE_LOG_RES(mp, 1) + \
- (128 * (2 + XFS_IALLOC_BLOCKS(mp) + (mp)->m_in_maxlevels + \
- XFS_ALLOCFREE_LOG_COUNT(mp, 1))))))
-
#define XFS_SYMLINK_LOG_RES(mp) ((mp)->m_reservations.tr_symlink)
-
-/*
- * For create we can modify:
- * the parent directory inode: inode size
- * the new inode: inode size
- * the inode btree entry: block size
- * the superblock for the nlink flag: sector size
- * the directory btree: (max depth + v2) * dir block size
- * the directory inode's bmap btree: (max depth + v2) * block size
- * Or in the first xact we allocate some inodes giving:
- * the agi and agf of the ag getting the new inodes: 2 * sectorsize
- * the superblock for the nlink flag: sector size
- * the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize
- * the inode btree: max depth * blocksize
- * the allocation btrees: 2 trees * (max depth - 1) * block size
- */
-#define XFS_CALC_CREATE_LOG_RES(mp) \
- (MAX( \
- ((mp)->m_sb.sb_inodesize + \
- (mp)->m_sb.sb_inodesize + \
- (mp)->m_sb.sb_sectsize + \
- XFS_FSB_TO_B(mp, 1) + \
- XFS_DIROP_LOG_RES(mp) + \
- (128 * (3 + XFS_DIROP_LOG_COUNT(mp)))), \
- (3 * (mp)->m_sb.sb_sectsize + \
- XFS_FSB_TO_B((mp), XFS_IALLOC_BLOCKS((mp))) + \
- XFS_FSB_TO_B((mp), (mp)->m_in_maxlevels) + \
- XFS_ALLOCFREE_LOG_RES(mp, 1) + \
- (128 * (2 + XFS_IALLOC_BLOCKS(mp) + (mp)->m_in_maxlevels + \
- XFS_ALLOCFREE_LOG_COUNT(mp, 1))))))
-
#define XFS_CREATE_LOG_RES(mp) ((mp)->m_reservations.tr_create)
-
-/*
- * Making a new directory is the same as creating a new file.
- */
-#define XFS_CALC_MKDIR_LOG_RES(mp) XFS_CALC_CREATE_LOG_RES(mp)
-
#define XFS_MKDIR_LOG_RES(mp) ((mp)->m_reservations.tr_mkdir)
-
-/*
- * In freeing an inode we can modify:
- * the inode being freed: inode size
- * the super block free inode counter: sector size
- * the agi hash list and counters: sector size
- * the inode btree entry: block size
- * the on disk inode before ours in the agi hash list: inode cluster size
- * the inode btree: max depth * blocksize
- * the allocation btrees: 2 trees * (max depth - 1) * block size
- */
-#define XFS_CALC_IFREE_LOG_RES(mp) \
- ((mp)->m_sb.sb_inodesize + \
- (mp)->m_sb.sb_sectsize + \
- (mp)->m_sb.sb_sectsize + \
- XFS_FSB_TO_B((mp), 1) + \
- MAX((__uint16_t)XFS_FSB_TO_B((mp), 1), XFS_INODE_CLUSTER_SIZE(mp)) + \
- (128 * 5) + \
- XFS_ALLOCFREE_LOG_RES(mp, 1) + \
- (128 * (2 + XFS_IALLOC_BLOCKS(mp) + (mp)->m_in_maxlevels + \
- XFS_ALLOCFREE_LOG_COUNT(mp, 1))))
-
-
#define XFS_IFREE_LOG_RES(mp) ((mp)->m_reservations.tr_ifree)
-
-/*
- * When only changing the inode we log the inode and possibly the superblock
- * We also add a bit of slop for the transaction stuff.
- */
-#define XFS_CALC_ICHANGE_LOG_RES(mp) ((mp)->m_sb.sb_inodesize + \
- (mp)->m_sb.sb_sectsize + 512)
-
#define XFS_ICHANGE_LOG_RES(mp) ((mp)->m_reservations.tr_ichange)
-
-/*
- * Growing the data section of the filesystem.
- * superblock
- * agi and agf
- * allocation btrees
- */
-#define XFS_CALC_GROWDATA_LOG_RES(mp) \
- ((mp)->m_sb.sb_sectsize * 3 + \
- XFS_ALLOCFREE_LOG_RES(mp, 1) + \
- (128 * (3 + XFS_ALLOCFREE_LOG_COUNT(mp, 1))))
-
#define XFS_GROWDATA_LOG_RES(mp) ((mp)->m_reservations.tr_growdata)
-
-/*
- * Growing the rt section of the filesystem.
- * In the first set of transactions (ALLOC) we allocate space to the
- * bitmap or summary files.
- * superblock: sector size
- * agf of the ag from which the extent is allocated: sector size
- * bmap btree for bitmap/summary inode: max depth * blocksize
- * bitmap/summary inode: inode size
- * allocation btrees for 1 block alloc: 2 * (2 * maxdepth - 1) * blocksize
- */
-#define XFS_CALC_GROWRTALLOC_LOG_RES(mp) \
- (2 * (mp)->m_sb.sb_sectsize + \
- XFS_FSB_TO_B((mp), XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)) + \
- (mp)->m_sb.sb_inodesize + \
- XFS_ALLOCFREE_LOG_RES(mp, 1) + \
- (128 * \
- (3 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + \
- XFS_ALLOCFREE_LOG_COUNT(mp, 1))))
-
#define XFS_GROWRTALLOC_LOG_RES(mp) ((mp)->m_reservations.tr_growrtalloc)
-
-/*
- * Growing the rt section of the filesystem.
- * In the second set of transactions (ZERO) we zero the new metadata blocks.
- * one bitmap/summary block: blocksize
- */
-#define XFS_CALC_GROWRTZERO_LOG_RES(mp) \
- ((mp)->m_sb.sb_blocksize + 128)
-
#define XFS_GROWRTZERO_LOG_RES(mp) ((mp)->m_reservations.tr_growrtzero)
-
-/*
- * Growing the rt section of the filesystem.
- * In the third set of transactions (FREE) we update metadata without
- * allocating any new blocks.
- * superblock: sector size
- * bitmap inode: inode size
- * summary inode: inode size
- * one bitmap block: blocksize
- * summary blocks: new summary size
- */
-#define XFS_CALC_GROWRTFREE_LOG_RES(mp) \
- ((mp)->m_sb.sb_sectsize + \
- 2 * (mp)->m_sb.sb_inodesize + \
- (mp)->m_sb.sb_blocksize + \
- (mp)->m_rsumsize + \
- (128 * 5))
-
#define XFS_GROWRTFREE_LOG_RES(mp) ((mp)->m_reservations.tr_growrtfree)
-
-/*
- * Logging the inode modification timestamp on a synchronous write.
- * inode
- */
-#define XFS_CALC_SWRITE_LOG_RES(mp) \
- ((mp)->m_sb.sb_inodesize + 128)
-
#define XFS_SWRITE_LOG_RES(mp) ((mp)->m_reservations.tr_swrite)
-
/*
* Logging the inode timestamps on an fsync -- same as SWRITE
* as long as SWRITE logs the entire inode core
*/
#define XFS_FSYNC_TS_LOG_RES(mp) ((mp)->m_reservations.tr_swrite)
-
-/*
- * Logging the inode mode bits when writing a setuid/setgid file
- * inode
- */
-#define XFS_CALC_WRITEID_LOG_RES(mp) \
- ((mp)->m_sb.sb_inodesize + 128)
-
#define XFS_WRITEID_LOG_RES(mp) ((mp)->m_reservations.tr_swrite)
-
-/*
- * Converting the inode from non-attributed to attributed.
- * the inode being converted: inode size
- * agf block and superblock (for block allocation)
- * the new block (directory sized)
- * bmap blocks for the new directory block
- * allocation btrees
- */
-#define XFS_CALC_ADDAFORK_LOG_RES(mp) \
- ((mp)->m_sb.sb_inodesize + \
- (mp)->m_sb.sb_sectsize * 2 + \
- (mp)->m_dirblksize + \
- XFS_FSB_TO_B(mp, (XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1)) + \
- XFS_ALLOCFREE_LOG_RES(mp, 1) + \
- (128 * (4 + (XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1) + \
- XFS_ALLOCFREE_LOG_COUNT(mp, 1))))
-
#define XFS_ADDAFORK_LOG_RES(mp) ((mp)->m_reservations.tr_addafork)
-
-/*
- * Removing the attribute fork of a file
- * the inode being truncated: inode size
- * the inode's bmap btree: max depth * block size
- * And the bmap_finish transaction can free the blocks and bmap blocks:
- * the agf for each of the ags: 4 * sector size
- * the agfl for each of the ags: 4 * sector size
- * the super block to reflect the freed blocks: sector size
- * worst case split in allocation btrees per extent assuming 4 extents:
- * 4 exts * 2 trees * (2 * max depth - 1) * block size
- */
-#define XFS_CALC_ATTRINVAL_LOG_RES(mp) \
- (MAX( \
- ((mp)->m_sb.sb_inodesize + \
- XFS_FSB_TO_B((mp), XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) + \
- (128 * (1 + XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)))), \
- ((4 * (mp)->m_sb.sb_sectsize) + \
- (4 * (mp)->m_sb.sb_sectsize) + \
- (mp)->m_sb.sb_sectsize + \
- XFS_ALLOCFREE_LOG_RES(mp, 4) + \
- (128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4))))))
-
#define XFS_ATTRINVAL_LOG_RES(mp) ((mp)->m_reservations.tr_attrinval)
-
-/*
- * Setting an attribute.
- * the inode getting the attribute
- * the superblock for allocations
- * the agfs extents are allocated from
- * the attribute btree * max depth
- * the inode allocation btree
- * Since attribute transaction space is dependent on the size of the attribute,
- * the calculation is done partially at mount time and partially at runtime.
- */
-#define XFS_CALC_ATTRSET_LOG_RES(mp) \
- ((mp)->m_sb.sb_inodesize + \
- (mp)->m_sb.sb_sectsize + \
- XFS_FSB_TO_B((mp), XFS_DA_NODE_MAXDEPTH) + \
- (128 * (2 + XFS_DA_NODE_MAXDEPTH)))
-
#define XFS_ATTRSET_LOG_RES(mp, ext) \
((mp)->m_reservations.tr_attrset + \
(ext * (mp)->m_sb.sb_sectsize) + \
(ext * XFS_FSB_TO_B((mp), XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK))) + \
(128 * (ext + (ext * XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)))))
-
-/*
- * Removing an attribute.
- * the inode: inode size
- * the attribute btree could join: max depth * block size
- * the inode bmap btree could join or split: max depth * block size
- * And the bmap_finish transaction can free the attr blocks freed giving:
- * the agf for the ag in which the blocks live: 2 * sector size
- * the agfl for the ag in which the blocks live: 2 * sector size
- * the superblock for the free block count: sector size
- * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
- */
-#define XFS_CALC_ATTRRM_LOG_RES(mp) \
- (MAX( \
- ((mp)->m_sb.sb_inodesize + \
- XFS_FSB_TO_B((mp), XFS_DA_NODE_MAXDEPTH) + \
- XFS_FSB_TO_B((mp), XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) + \
- (128 * (1 + XFS_DA_NODE_MAXDEPTH + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)))), \
- ((2 * (mp)->m_sb.sb_sectsize) + \
- (2 * (mp)->m_sb.sb_sectsize) + \
- (mp)->m_sb.sb_sectsize + \
- XFS_ALLOCFREE_LOG_RES(mp, 2) + \
- (128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))))))
-
#define XFS_ATTRRM_LOG_RES(mp) ((mp)->m_reservations.tr_attrrm)
-
-/*
- * Clearing a bad agino number in an agi hash bucket.
- */
-#define XFS_CALC_CLEAR_AGI_BUCKET_LOG_RES(mp) \
- ((mp)->m_sb.sb_sectsize + 128)
-
#define XFS_CLEAR_AGI_BUCKET_LOG_RES(mp) ((mp)->m_reservations.tr_clearagi)
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 9d376be..a06bd62 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -267,7 +267,7 @@
if (code) {
ASSERT(tp == NULL);
lock_flags &= ~XFS_ILOCK_EXCL;
- ASSERT(lock_flags == XFS_IOLOCK_EXCL);
+ ASSERT(lock_flags == XFS_IOLOCK_EXCL || !need_iolock);
goto error_return;
}
tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_SIZE);
diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h
index 5958d78..17714be 100644
--- a/include/acpi/acexcep.h
+++ b/include/acpi/acexcep.h
@@ -212,7 +212,7 @@
"AE_NO_GLOBAL_LOCK",
"AE_ABORT_METHOD",
"AE_SAME_HANDLER",
- "AE_WAKE_ONLY_GPE",
+ "AE_NO_HANDLER",
"AE_OWNER_ID_LIMIT"
};
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 0e4ab1f..1371cc9 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -69,6 +69,7 @@
extern u32 acpi_gbl_trace_flags;
extern u8 acpi_gbl_enable_aml_debug_object;
extern u8 acpi_gbl_copy_dsdt_locally;
+extern u8 acpi_gbl_truncate_io_addresses;
extern u32 acpi_current_gpe_count;
extern struct acpi_table_fadt acpi_gbl_FADT;
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index bade172..d55f4a7 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -663,10 +663,11 @@
#define ACPI_GPE_MAX 0xFF
#define ACPI_NUM_GPE 256
-/* Actions for acpi_set_gpe */
+/* Actions for acpi_set_gpe and acpi_hw_low_set_gpe */
#define ACPI_GPE_ENABLE 0
#define ACPI_GPE_DISABLE 1
+#define ACPI_GPE_COND_ENABLE 2
/* gpe_types for acpi_enable_gpe and acpi_disable_gpe */
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index dc5873c..1121f77 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -130,4 +130,7 @@
extern void drm_kms_helper_poll_init(struct drm_device *dev);
extern void drm_kms_helper_poll_fini(struct drm_device *dev);
extern void drm_helper_hpd_irq_event(struct drm_device *dev);
+
+extern void drm_kms_helper_poll_disable(struct drm_device *dev);
+extern void drm_kms_helper_poll_enable(struct drm_device *dev);
#endif
diff --git a/include/drm/nouveau_drm.h b/include/drm/nouveau_drm.h
index a6a9f4a..fe917de 100644
--- a/include/drm/nouveau_drm.h
+++ b/include/drm/nouveau_drm.h
@@ -79,6 +79,7 @@
#define NOUVEAU_GETPARAM_CHIPSET_ID 11
#define NOUVEAU_GETPARAM_VM_VRAM_BASE 12
#define NOUVEAU_GETPARAM_GRAPH_UNITS 13
+#define NOUVEAU_GETPARAM_PTIMER_TIME 14
struct drm_nouveau_getparam {
uint64_t param;
uint64_t value;
diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h
index 3ff9fc0..5347063 100644
--- a/include/drm/radeon_drm.h
+++ b/include/drm/radeon_drm.h
@@ -903,6 +903,7 @@
#define RADEON_INFO_NUM_Z_PIPES 0x02
#define RADEON_INFO_ACCEL_WORKING 0x03
#define RADEON_INFO_CRTC_FROM_ID 0x04
+#define RADEON_INFO_ACCEL_WORKING2 0x05
struct drm_radeon_info {
uint32_t request;
diff --git a/include/drm/vmwgfx_drm.h b/include/drm/vmwgfx_drm.h
index c7645f4..4d08423 100644
--- a/include/drm/vmwgfx_drm.h
+++ b/include/drm/vmwgfx_drm.h
@@ -50,6 +50,8 @@
#define DRM_VMW_EXECBUF 12
#define DRM_VMW_FIFO_DEBUG 13
#define DRM_VMW_FENCE_WAIT 14
+/* guarded by minor version >= 2 */
+#define DRM_VMW_UPDATE_LAYOUT 15
/*************************************************************************/
@@ -585,4 +587,28 @@
* sure that the stream has been stopped.
*/
+/*************************************************************************/
+/**
+ * DRM_VMW_UPDATE_LAYOUT - Update layout
+ *
+ * Updates the prefered modes and connection status for connectors. The
+ * command conisits of one drm_vmw_update_layout_arg pointing out a array
+ * of num_outputs drm_vmw_rect's.
+ */
+
+/**
+ * struct drm_vmw_update_layout_arg
+ *
+ * @num_outputs: number of active
+ * @rects: pointer to array of drm_vmw_rect
+ *
+ * Input argument to the DRM_VMW_UPDATE_LAYOUT Ioctl.
+ */
+
+struct drm_vmw_update_layout_arg {
+ uint32_t num_outputs;
+ uint32_t pad64;
+ uint64_t rects;
+};
+
#endif
diff --git a/include/linux/agp_backend.h b/include/linux/agp_backend.h
index 9101ed64..09ea4a1 100644
--- a/include/linux/agp_backend.h
+++ b/include/linux/agp_backend.h
@@ -79,7 +79,6 @@
u32 physical;
bool is_bound;
bool is_flushed;
- bool vmalloc_flag;
/* list of agp_memory mapped to the aperture */
struct list_head mapped_list;
/* DMA-mapped addresses */
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index e6e0cb5..9ae2889 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -105,8 +105,8 @@
int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev);
void bdi_unregister(struct backing_dev_info *bdi);
int bdi_setup_and_register(struct backing_dev_info *, char *, unsigned int);
-void bdi_start_writeback(struct backing_dev_info *bdi, struct super_block *sb,
- long nr_pages, int sb_locked);
+void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages);
+void bdi_start_background_writeback(struct backing_dev_info *bdi);
int bdi_writeback_task(struct bdi_writeback *wb);
int bdi_has_dirty_io(struct backing_dev_info *bdi);
void bdi_arm_supers_timer(void);
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 8b7f5e0..09a8402 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1211,14 +1211,23 @@
int kblockd_schedule_work(struct request_queue *q, struct work_struct *work);
#ifdef CONFIG_BLK_CGROUP
+/*
+ * This should not be using sched_clock(). A real patch is in progress
+ * to fix this up, until that is in place we need to disable preemption
+ * around sched_clock() in this function and set_io_start_time_ns().
+ */
static inline void set_start_time_ns(struct request *req)
{
+ preempt_disable();
req->start_time_ns = sched_clock();
+ preempt_enable();
}
static inline void set_io_start_time_ns(struct request *req)
{
+ preempt_disable();
req->io_start_time_ns = sched_clock();
+ preempt_enable();
}
static inline uint64_t rq_start_time_ns(struct request *req)
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 0c62160..e3d00fd 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -525,13 +525,21 @@
return cgrp->subsys[subsys_id];
}
-static inline struct cgroup_subsys_state *task_subsys_state(
- struct task_struct *task, int subsys_id)
+/*
+ * function to get the cgroup_subsys_state which allows for extra
+ * rcu_dereference_check() conditions, such as locks used during the
+ * cgroup_subsys::attach() methods.
+ */
+#define task_subsys_state_check(task, subsys_id, __c) \
+ rcu_dereference_check(task->cgroups->subsys[subsys_id], \
+ rcu_read_lock_held() || \
+ lockdep_is_held(&task->alloc_lock) || \
+ cgroup_lock_is_held() || (__c))
+
+static inline struct cgroup_subsys_state *
+task_subsys_state(struct task_struct *task, int subsys_id)
{
- return rcu_dereference_check(task->cgroups->subsys[subsys_id],
- rcu_read_lock_held() ||
- lockdep_is_held(&task->alloc_lock) ||
- cgroup_lock_is_held());
+ return task_subsys_state_check(task, subsys_id, false);
}
static inline struct cgroup* task_cgroup(struct task_struct *task,
diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
index 73dcf80..0da5b18 100644
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -58,8 +58,12 @@
* naked functions because then mcount is called without stack and frame pointer
* being set up and there is no chance to restore the lr register to the value
* before mcount was called.
+ *
+ * The asm() bodies of naked functions often depend on standard calling conventions,
+ * therefore they must be noinline and noclone. GCC 4.[56] currently fail to enforce
+ * this, so we must do so ourselves. See GCC PR44290.
*/
-#define __naked __attribute__((naked)) notrace
+#define __naked __attribute__((naked)) noinline __noclone notrace
#define __noreturn __attribute__((noreturn))
@@ -85,3 +89,7 @@
#define _gcc_header(x) __gcc_header(linux/compiler-gcc##x.h)
#define gcc_header(x) _gcc_header(x)
#include gcc_header(__GNUC__)
+
+#if !defined(__noclone)
+#define __noclone /* not needed */
+#endif
diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h
index 94dea3f..fcfa5b9 100644
--- a/include/linux/compiler-gcc4.h
+++ b/include/linux/compiler-gcc4.h
@@ -48,6 +48,10 @@
* unreleased. Really, we need to have autoconf for the kernel.
*/
#define unreachable() __builtin_unreachable()
+
+/* Mark a function definition as prohibited from being cloned. */
+#define __noclone __attribute__((__noclone__))
+
#endif
#endif
diff --git a/include/linux/drbd.h b/include/linux/drbd.h
index 6853052..b8d2516 100644
--- a/include/linux/drbd.h
+++ b/include/linux/drbd.h
@@ -53,7 +53,7 @@
extern const char *drbd_buildtag(void);
-#define REL_VERSION "8.3.8rc1"
+#define REL_VERSION "8.3.8"
#define API_VERSION 88
#define PRO_VERSION_MIN 86
#define PRO_VERSION_MAX 94
diff --git a/include/linux/edac_mce.h b/include/linux/edac_mce.h
new file mode 100644
index 0000000..f974fc0
--- /dev/null
+++ b/include/linux/edac_mce.h
@@ -0,0 +1,31 @@
+/* Provides edac interface to mcelog events
+ *
+ * This file may be distributed under the terms of the
+ * GNU General Public License version 2.
+ *
+ * Copyright (c) 2009 by:
+ * Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ * Red Hat Inc. http://www.redhat.com
+ */
+
+#if defined(CONFIG_EDAC_MCE) || \
+ (defined(CONFIG_EDAC_MCE_MODULE) && defined(MODULE))
+
+#include <asm/mce.h>
+#include <linux/list.h>
+
+struct edac_mce {
+ struct list_head list;
+
+ void *priv;
+ int (*check_error)(void *priv, struct mce *mce);
+};
+
+int edac_mce_register(struct edac_mce *edac_mce);
+void edac_mce_unregister(struct edac_mce *edac_mce);
+int edac_mce_parse(struct mce *mce);
+
+#else
+#define edac_mce_parse(mce) (0)
+#endif
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 907ace3..8e5a9df 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -786,8 +786,6 @@
#define FBINFO_MISC_USEREVENT 0x10000 /* event request
from userspace */
#define FBINFO_MISC_TILEBLITTING 0x20000 /* use tile blitting */
-#define FBINFO_MISC_FIRMWARE 0x40000 /* a replaceable firmware
- inited framebuffer */
/* A driver may set this flag to indicate that it does want a set_par to be
* called every time when fbcon_switch is executed. The advantage is that with
@@ -801,6 +799,8 @@
*/
#define FBINFO_MISC_ALWAYS_SETPAR 0x40000
+/* where the fb is a firmware driver, and can be replaced with a proper one */
+#define FBINFO_MISC_FIRMWARE 0x80000
/*
* Host and GPU endianness differ.
*/
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 3428393..471e1ff 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2388,7 +2388,7 @@
extern const struct inode_operations simple_dir_inode_operations;
struct tree_descr { char *name; const struct file_operations *ops; int mode; };
struct dentry *d_alloc_name(struct dentry *, const char *);
-extern int simple_fill_super(struct super_block *, int, struct tree_descr *);
+extern int simple_fill_super(struct super_block *, unsigned long, struct tree_descr *);
extern int simple_pin_fs(struct file_system_type *, struct vfsmount **mount, int *count);
extern void simple_release_fs(struct vfsmount **mount, int *count);
diff --git a/include/linux/iocontext.h b/include/linux/iocontext.h
index a0bb301..64d5291 100644
--- a/include/linux/iocontext.h
+++ b/include/linux/iocontext.h
@@ -7,7 +7,6 @@
struct cfq_queue;
struct cfq_io_context {
void *key;
- unsigned long dead_key;
struct cfq_queue *cfqq[2];
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 3bad270..b85f3ff 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -1023,6 +1023,7 @@
extern int ata_std_bios_param(struct scsi_device *sdev,
struct block_device *bdev,
sector_t capacity, int geom[]);
+extern void ata_scsi_unlock_native_capacity(struct scsi_device *sdev);
extern int ata_scsi_slave_config(struct scsi_device *sdev);
extern void ata_scsi_slave_destroy(struct scsi_device *sdev);
extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
@@ -1174,6 +1175,7 @@
.slave_configure = ata_scsi_slave_config, \
.slave_destroy = ata_scsi_slave_destroy, \
.bios_param = ata_std_bios_param, \
+ .unlock_native_capacity = ata_scsi_unlock_native_capacity, \
.sdev_attrs = ata_common_sdev_attrs
#define ATA_NCQ_SHT(drv_name) \
diff --git a/include/linux/list.h b/include/linux/list.h
index 8392884..5d57a3a 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -544,6 +544,21 @@
&pos->member != (head); \
pos = n, n = list_entry(n->member.prev, typeof(*n), member))
+/**
+ * list_safe_reset_next - reset a stale list_for_each_entry_safe loop
+ * @pos: the loop cursor used in the list_for_each_entry_safe loop
+ * @n: temporary storage used in list_for_each_entry_safe
+ * @member: the name of the list_struct within the struct.
+ *
+ * list_safe_reset_next is not safe to use in general if the list may be
+ * modified concurrently (eg. the lock is dropped in the loop body). An
+ * exception to this is if the cursor element (pos) is pinned in the list,
+ * and list_safe_reset_next is called after re-taking the lock and before
+ * completing the current iteration of the loop body.
+ */
+#define list_safe_reset_next(pos, n, member) \
+ n = list_entry(pos->member.next, typeof(*pos), member)
+
/*
* Double linked lists with a single pointer list head.
* Mostly useful for hash tables where the two pointer list head is
diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h
index b631c46..f6c9b7d 100644
--- a/include/linux/miscdevice.h
+++ b/include/linux/miscdevice.h
@@ -3,6 +3,12 @@
#include <linux/module.h>
#include <linux/major.h>
+/*
+ * These allocations are managed by device@lanana.org. If you use an
+ * entry that is not in assigned your entry may well be moved and
+ * reassigned, or set dynamic if a fixed value is not justified.
+ */
+
#define PSMOUSE_MINOR 1
#define MS_BUSMOUSE_MINOR 2
#define ATIXL_BUSMOUSE_MINOR 3
@@ -30,7 +36,6 @@
#define HPET_MINOR 228
#define FUSE_MINOR 229
#define KVM_MINOR 232
-#define VHOST_NET_MINOR 233
#define BTRFS_MINOR 234
#define AUTOFS_MINOR 235
#define MISC_DYNAMIC_MINOR 255
diff --git a/include/linux/mmc/sh_mmcif.h b/include/linux/mmc/sh_mmcif.h
index aafe832..d4a2ebb 100644
--- a/include/linux/mmc/sh_mmcif.h
+++ b/include/linux/mmc/sh_mmcif.h
@@ -14,6 +14,9 @@
#ifndef __SH_MMCIF_H__
#define __SH_MMCIF_H__
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
/*
* MMCIF : CE_CLK_CTRL [19:16]
* 1000 : Peripheral clock / 512
@@ -36,4 +39,162 @@
u32 ocr;
};
+#define MMCIF_CE_CMD_SET 0x00000000
+#define MMCIF_CE_ARG 0x00000008
+#define MMCIF_CE_ARG_CMD12 0x0000000C
+#define MMCIF_CE_CMD_CTRL 0x00000010
+#define MMCIF_CE_BLOCK_SET 0x00000014
+#define MMCIF_CE_CLK_CTRL 0x00000018
+#define MMCIF_CE_BUF_ACC 0x0000001C
+#define MMCIF_CE_RESP3 0x00000020
+#define MMCIF_CE_RESP2 0x00000024
+#define MMCIF_CE_RESP1 0x00000028
+#define MMCIF_CE_RESP0 0x0000002C
+#define MMCIF_CE_RESP_CMD12 0x00000030
+#define MMCIF_CE_DATA 0x00000034
+#define MMCIF_CE_INT 0x00000040
+#define MMCIF_CE_INT_MASK 0x00000044
+#define MMCIF_CE_HOST_STS1 0x00000048
+#define MMCIF_CE_HOST_STS2 0x0000004C
+#define MMCIF_CE_VERSION 0x0000007C
+
+extern inline u32 sh_mmcif_readl(void __iomem *addr, int reg)
+{
+ return readl(addr + reg);
+}
+
+extern inline void sh_mmcif_writel(void __iomem *addr, int reg, u32 val)
+{
+ writel(val, addr + reg);
+}
+
+#define SH_MMCIF_BBS 512 /* boot block size */
+
+extern inline void sh_mmcif_boot_cmd_send(void __iomem *base,
+ unsigned long cmd, unsigned long arg)
+{
+ sh_mmcif_writel(base, MMCIF_CE_INT, 0);
+ sh_mmcif_writel(base, MMCIF_CE_ARG, arg);
+ sh_mmcif_writel(base, MMCIF_CE_CMD_SET, cmd);
+}
+
+extern inline int sh_mmcif_boot_cmd_poll(void __iomem *base, unsigned long mask)
+{
+ unsigned long tmp;
+ int cnt;
+
+ for (cnt = 0; cnt < 1000000; cnt++) {
+ tmp = sh_mmcif_readl(base, MMCIF_CE_INT);
+ if (tmp & mask) {
+ sh_mmcif_writel(base, MMCIF_CE_INT, tmp & ~mask);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+extern inline int sh_mmcif_boot_cmd(void __iomem *base,
+ unsigned long cmd, unsigned long arg)
+{
+ sh_mmcif_boot_cmd_send(base, cmd, arg);
+ return sh_mmcif_boot_cmd_poll(base, 0x00010000);
+}
+
+extern inline int sh_mmcif_boot_do_read_single(void __iomem *base,
+ unsigned int block_nr,
+ unsigned long *buf)
+{
+ int k;
+
+ /* CMD13 - Status */
+ sh_mmcif_boot_cmd(base, 0x0d400000, 0x00010000);
+
+ if (sh_mmcif_readl(base, MMCIF_CE_RESP0) != 0x0900)
+ return -1;
+
+ /* CMD17 - Read */
+ sh_mmcif_boot_cmd(base, 0x11480000, block_nr * SH_MMCIF_BBS);
+ if (sh_mmcif_boot_cmd_poll(base, 0x00100000) < 0)
+ return -1;
+
+ for (k = 0; k < (SH_MMCIF_BBS / 4); k++)
+ buf[k] = sh_mmcif_readl(base, MMCIF_CE_DATA);
+
+ return 0;
+}
+
+extern inline int sh_mmcif_boot_do_read(void __iomem *base,
+ unsigned long first_block,
+ unsigned long nr_blocks,
+ void *buf)
+{
+ unsigned long k;
+ int ret = 0;
+
+ /* CMD16 - Set the block size */
+ sh_mmcif_boot_cmd(base, 0x10400000, SH_MMCIF_BBS);
+
+ for (k = 0; !ret && k < nr_blocks; k++)
+ ret = sh_mmcif_boot_do_read_single(base, first_block + k,
+ buf + (k * SH_MMCIF_BBS));
+
+ return ret;
+}
+
+extern inline void sh_mmcif_boot_init(void __iomem *base)
+{
+ unsigned long tmp;
+
+ /* reset */
+ tmp = sh_mmcif_readl(base, MMCIF_CE_VERSION);
+ sh_mmcif_writel(base, MMCIF_CE_VERSION, tmp | 0x80000000);
+ sh_mmcif_writel(base, MMCIF_CE_VERSION, tmp & ~0x80000000);
+
+ /* byte swap */
+ sh_mmcif_writel(base, MMCIF_CE_BUF_ACC, 0x00010000);
+
+ /* Set block size in MMCIF hardware */
+ sh_mmcif_writel(base, MMCIF_CE_BLOCK_SET, SH_MMCIF_BBS);
+
+ /* Enable the clock, set it to Bus clock/256 (about 325Khz)*/
+ sh_mmcif_writel(base, MMCIF_CE_CLK_CTRL, 0x01072fff);
+
+ /* CMD0 */
+ sh_mmcif_boot_cmd(base, 0x00000040, 0);
+
+ /* CMD1 - Get OCR */
+ do {
+ sh_mmcif_boot_cmd(base, 0x01405040, 0x40300000); /* CMD1 */
+ } while ((sh_mmcif_readl(base, MMCIF_CE_RESP0) & 0x80000000)
+ != 0x80000000);
+
+ /* CMD2 - Get CID */
+ sh_mmcif_boot_cmd(base, 0x02806040, 0);
+
+ /* CMD3 - Set card relative address */
+ sh_mmcif_boot_cmd(base, 0x03400040, 0x00010000);
+}
+
+extern inline void sh_mmcif_boot_slurp(void __iomem *base,
+ unsigned char *buf,
+ unsigned long no_bytes)
+{
+ unsigned long tmp;
+
+ /* In data transfer mode: Set clock to Bus clock/4 (about 20Mhz) */
+ sh_mmcif_writel(base, MMCIF_CE_CLK_CTRL, 0x01012fff);
+
+ /* CMD9 - Get CSD */
+ sh_mmcif_boot_cmd(base, 0x09806000, 0x00010000);
+
+ /* CMD7 - Select the card */
+ sh_mmcif_boot_cmd(base, 0x07400000, 0x00010000);
+
+ tmp = no_bytes / SH_MMCIF_BBS;
+ tmp += (no_bytes % SH_MMCIF_BBS) ? 1 : 0;
+
+ sh_mmcif_boot_do_read(base, 512, tmp, buf);
+}
+
#endif /* __SH_MMCIF_H__ */
diff --git a/include/linux/module.h b/include/linux/module.h
index 6914fca..8a6b9fd 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -181,6 +181,13 @@
void *__symbol_get_gpl(const char *symbol);
#define symbol_get(x) ((typeof(&x))(__symbol_get(MODULE_SYMBOL_PREFIX #x)))
+/* modules using other modules: kdb wants to see this. */
+struct module_use {
+ struct list_head source_list;
+ struct list_head target_list;
+ struct module *source, *target;
+};
+
#ifndef __GENKSYMS__
#ifdef CONFIG_MODVERSIONS
/* Mark the CRC weak since genksyms apparently decides not to
@@ -359,7 +366,9 @@
#ifdef CONFIG_MODULE_UNLOAD
/* What modules depend on me? */
- struct list_head modules_which_use_me;
+ struct list_head source_list;
+ /* What modules do I depend on? */
+ struct list_head target_list;
/* Who is waiting for us to be unloaded */
struct task_struct *waiter;
@@ -663,43 +672,10 @@
#endif /* CONFIG_MODULES */
-struct device_driver;
#ifdef CONFIG_SYSFS
-struct module;
-
extern struct kset *module_kset;
extern struct kobj_type module_ktype;
extern int module_sysfs_initialized;
-
-int mod_sysfs_init(struct module *mod);
-int mod_sysfs_setup(struct module *mod,
- struct kernel_param *kparam,
- unsigned int num_params);
-int module_add_modinfo_attrs(struct module *mod);
-void module_remove_modinfo_attrs(struct module *mod);
-
-#else /* !CONFIG_SYSFS */
-
-static inline int mod_sysfs_init(struct module *mod)
-{
- return 0;
-}
-
-static inline int mod_sysfs_setup(struct module *mod,
- struct kernel_param *kparam,
- unsigned int num_params)
-{
- return 0;
-}
-
-static inline int module_add_modinfo_attrs(struct module *mod)
-{
- return 0;
-}
-
-static inline void module_remove_modinfo_attrs(struct module *mod)
-{ }
-
#endif /* CONFIG_SYSFS */
#define symbol_request(x) try_then_request_module(symbol_get(x), "symbol:" #x)
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 6a471ab..7cb0084 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -632,6 +632,7 @@
/* Generic PCI functions used internally */
+void pcibios_scan_specific_bus(int busn);
extern struct pci_bus *pci_find_bus(int domain, int busnr);
void pci_bus_add_devices(const struct pci_bus *bus);
struct pci_bus *pci_scan_bus_parented(struct device *parent, int bus,
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index ae66851..3bedcc1 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1261,6 +1261,7 @@
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE 0x0759
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_SMBUS 0x07D8
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP79_SMBUS 0x0AA2
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA 0x0D85
#define PCI_VENDOR_ID_IMS 0x10e0
#define PCI_DEVICE_ID_IMS_TT128 0x9128
@@ -2321,6 +2322,7 @@
#define PCI_VENDOR_ID_JMICRON 0x197B
#define PCI_DEVICE_ID_JMICRON_JMB360 0x2360
#define PCI_DEVICE_ID_JMICRON_JMB361 0x2361
+#define PCI_DEVICE_ID_JMICRON_JMB362 0x2362
#define PCI_DEVICE_ID_JMICRON_JMB363 0x2363
#define PCI_DEVICE_ID_JMICRON_JMB365 0x2365
#define PCI_DEVICE_ID_JMICRON_JMB366 0x2366
@@ -2532,11 +2534,63 @@
#define PCI_DEVICE_ID_INTEL_ICH9_6 0x2930
#define PCI_DEVICE_ID_INTEL_ICH9_7 0x2916
#define PCI_DEVICE_ID_INTEL_ICH9_8 0x2918
+#define PCI_DEVICE_ID_INTEL_I7_MCR 0x2c18
+#define PCI_DEVICE_ID_INTEL_I7_MC_TAD 0x2c19
+#define PCI_DEVICE_ID_INTEL_I7_MC_RAS 0x2c1a
+#define PCI_DEVICE_ID_INTEL_I7_MC_TEST 0x2c1c
+#define PCI_DEVICE_ID_INTEL_I7_MC_CH0_CTRL 0x2c20
+#define PCI_DEVICE_ID_INTEL_I7_MC_CH0_ADDR 0x2c21
+#define PCI_DEVICE_ID_INTEL_I7_MC_CH0_RANK 0x2c22
+#define PCI_DEVICE_ID_INTEL_I7_MC_CH0_TC 0x2c23
+#define PCI_DEVICE_ID_INTEL_I7_MC_CH1_CTRL 0x2c28
+#define PCI_DEVICE_ID_INTEL_I7_MC_CH1_ADDR 0x2c29
+#define PCI_DEVICE_ID_INTEL_I7_MC_CH1_RANK 0x2c2a
+#define PCI_DEVICE_ID_INTEL_I7_MC_CH1_TC 0x2c2b
+#define PCI_DEVICE_ID_INTEL_I7_MC_CH2_CTRL 0x2c30
+#define PCI_DEVICE_ID_INTEL_I7_MC_CH2_ADDR 0x2c31
+#define PCI_DEVICE_ID_INTEL_I7_MC_CH2_RANK 0x2c32
+#define PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC 0x2c33
+#define PCI_DEVICE_ID_INTEL_I7_NONCORE 0x2c41
+#define PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT 0x2c40
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE 0x2c50
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT 0x2c51
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_REV2 0x2c70
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_SAD 0x2c81
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_QPI_LINK0 0x2c90
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_QPI_PHY0 0x2c91
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MCR 0x2c98
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TAD 0x2c99
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TEST 0x2c9C
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_CTRL 0x2ca0
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_ADDR 0x2ca1
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_RANK 0x2ca2
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_TC 0x2ca3
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_CTRL 0x2ca8
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_ADDR 0x2ca9
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_RANK 0x2caa
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_TC 0x2cab
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MCR_REV2 0x2d98
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TAD_REV2 0x2d99
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_RAS_REV2 0x2d9a
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TEST_REV2 0x2d9c
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_CTRL_REV2 0x2da0
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_ADDR_REV2 0x2da1
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_RANK_REV2 0x2da2
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_TC_REV2 0x2da3
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_CTRL_REV2 0x2da8
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_ADDR_REV2 0x2da9
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_RANK_REV2 0x2daa
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_TC_REV2 0x2dab
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_CTRL_REV2 0x2db0
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_ADDR_REV2 0x2db1
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_RANK_REV2 0x2db2
+#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_TC_REV2 0x2db3
#define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340
#define PCI_DEVICE_ID_INTEL_IOAT_TBG4 0x3429
#define PCI_DEVICE_ID_INTEL_IOAT_TBG5 0x342a
#define PCI_DEVICE_ID_INTEL_IOAT_TBG6 0x342b
#define PCI_DEVICE_ID_INTEL_IOAT_TBG7 0x342c
+#define PCI_DEVICE_ID_INTEL_X58_HUB_MGMT 0x342e
#define PCI_DEVICE_ID_INTEL_IOAT_TBG0 0x3430
#define PCI_DEVICE_ID_INTEL_IOAT_TBG1 0x3431
#define PCI_DEVICE_ID_INTEL_IOAT_TBG2 0x3432
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index fb6c91e..5d0266d 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -585,6 +585,7 @@
struct file;
struct perf_mmap_data {
+ atomic_t refcount;
struct rcu_head rcu_head;
#ifdef CONFIG_PERF_USE_VMALLOC
struct work_struct work;
@@ -592,7 +593,6 @@
#endif
int nr_pages; /* nr of data pages */
int writable; /* are we writable */
- int nr_locked; /* nr pages mlocked */
atomic_t poll; /* POLL_ for wakeups */
@@ -631,6 +631,9 @@
struct rcu_head rcu_head;
};
+#define PERF_ATTACH_CONTEXT 0x01
+#define PERF_ATTACH_GROUP 0x02
+
/**
* struct perf_event - performance event kernel representation:
*/
@@ -643,10 +646,10 @@
int nr_siblings;
int group_flags;
struct perf_event *group_leader;
- struct perf_event *output;
const struct pmu *pmu;
enum perf_event_active_state state;
+ unsigned int attach_state;
atomic64_t count;
/*
@@ -704,6 +707,8 @@
/* mmap bits */
struct mutex mmap_mutex;
atomic_t mmap_count;
+ int mmap_locked;
+ struct user_struct *mmap_user;
struct perf_mmap_data *data;
/* poll related */
diff --git a/include/linux/personality.h b/include/linux/personality.h
index 12612081..eec3bae 100644
--- a/include/linux/personality.h
+++ b/include/linux/personality.h
@@ -12,7 +12,7 @@
extern int register_exec_domain(struct exec_domain *);
extern int unregister_exec_domain(struct exec_domain *);
-extern int __set_personality(unsigned long);
+extern int __set_personality(unsigned int);
#endif /* __KERNEL__ */
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index 16de393..4457969 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -139,7 +139,9 @@
void pipe_unlock(struct pipe_inode_info *);
void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *);
-extern unsigned int pipe_max_pages;
+extern unsigned int pipe_max_size, pipe_min_size;
+int pipe_proc_fn(struct ctl_table *, int, void __user *, size_t *, loff_t *);
+
/* Drop the inode semaphore and wait for a pipe event, atomically */
void pipe_wait(struct pipe_inode_info *pipe);
diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h
index f5364a1..baed212 100644
--- a/include/linux/serial_sci.h
+++ b/include/linux/serial_sci.h
@@ -2,9 +2,7 @@
#define __LINUX_SERIAL_SCI_H
#include <linux/serial_core.h>
-#ifdef CONFIG_SERIAL_SH_SCI_DMA
-#include <asm/dmaengine.h>
-#endif
+#include <linux/sh_dma.h>
/*
* Generic header for SuperH SCI(F) (used by sh/sh64/h8300 and related parts)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index bf243fc..f89e7fd 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -380,7 +380,10 @@
kmemcheck_bitfield_begin(flags2);
__u16 queue_mapping:16;
#ifdef CONFIG_IPV6_NDISC_NODETYPE
- __u8 ndisc_nodetype:2;
+ __u8 ndisc_nodetype:2,
+ deliver_no_wcard:1;
+#else
+ __u8 deliver_no_wcard:1;
#endif
kmemcheck_bitfield_end(flags2);
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index 5e781d8..bc7d6bb 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -256,22 +256,22 @@
static inline bool system_entering_hibernation(void) { return false; }
#endif /* CONFIG_HIBERNATION */
-#ifdef CONFIG_HIBERNATION_NVS
-extern int hibernate_nvs_register(unsigned long start, unsigned long size);
-extern int hibernate_nvs_alloc(void);
-extern void hibernate_nvs_free(void);
-extern void hibernate_nvs_save(void);
-extern void hibernate_nvs_restore(void);
-#else /* CONFIG_HIBERNATION_NVS */
-static inline int hibernate_nvs_register(unsigned long a, unsigned long b)
+#ifdef CONFIG_SUSPEND_NVS
+extern int suspend_nvs_register(unsigned long start, unsigned long size);
+extern int suspend_nvs_alloc(void);
+extern void suspend_nvs_free(void);
+extern void suspend_nvs_save(void);
+extern void suspend_nvs_restore(void);
+#else /* CONFIG_SUSPEND_NVS */
+static inline int suspend_nvs_register(unsigned long a, unsigned long b)
{
return 0;
}
-static inline int hibernate_nvs_alloc(void) { return 0; }
-static inline void hibernate_nvs_free(void) {}
-static inline void hibernate_nvs_save(void) {}
-static inline void hibernate_nvs_restore(void) {}
-#endif /* CONFIG_HIBERNATION_NVS */
+static inline int suspend_nvs_alloc(void) { return 0; }
+static inline void suspend_nvs_free(void) {}
+static inline void suspend_nvs_save(void) {}
+static inline void suspend_nvs_restore(void) {}
+#endif /* CONFIG_SUSPEND_NVS */
#ifdef CONFIG_PM_SLEEP
void save_processor_state(void);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index a1a86a5..7f614ce 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -289,7 +289,7 @@
cap_user_data_t dataptr);
asmlinkage long sys_capset(cap_user_header_t header,
const cap_user_data_t data);
-asmlinkage long sys_personality(u_long personality);
+asmlinkage long sys_personality(unsigned int personality);
asmlinkage long sys_sigpending(old_sigset_t __user *set);
asmlinkage long sys_sigprocmask(int how, old_sigset_t __user *set,
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index 9a59d1f..103d1b6 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -14,6 +14,7 @@
* See the file COPYING for more details.
*/
+#include <linux/errno.h>
#include <linux/types.h>
#include <linux/rcupdate.h>
diff --git a/include/linux/usb/audio-v2.h b/include/linux/usb/audio-v2.h
index 92f1d99..383b94b 100644
--- a/include/linux/usb/audio-v2.h
+++ b/include/linux/usb/audio-v2.h
@@ -18,6 +18,16 @@
/* v1.0 and v2.0 of this standard have many things in common. For the rest
* of the definitions, please refer to audio.h */
+static inline bool uac2_control_is_readable(u32 bmControls, u8 control)
+{
+ return (bmControls >> (control * 2)) & 0x1;
+}
+
+static inline bool uac2_control_is_writeable(u32 bmControls, u8 control)
+{
+ return (bmControls >> (control * 2)) & 0x2;
+}
+
/* 4.7.2.1 Clock Source Descriptor */
struct uac_clock_source_descriptor {
@@ -31,6 +41,13 @@
__u8 iClockSource;
} __attribute__((packed));
+/* bmAttribute fields */
+#define UAC_CLOCK_SOURCE_TYPE_EXT 0x0
+#define UAC_CLOCK_SOURCE_TYPE_INT_FIXED 0x1
+#define UAC_CLOCK_SOURCE_TYPE_INT_VAR 0x2
+#define UAC_CLOCK_SOURCE_TYPE_INT_PROG 0x3
+#define UAC_CLOCK_SOURCE_SYNCED_TO_SOF (1 << 2)
+
/* 4.7.2.2 Clock Source Descriptor */
struct uac_clock_selector_descriptor {
@@ -39,8 +56,20 @@
__u8 bDescriptorSubtype;
__u8 bClockID;
__u8 bNrInPins;
- __u8 bmControls;
__u8 baCSourceID[];
+ /* bmControls, bAssocTerminal and iClockSource omitted */
+} __attribute__((packed));
+
+/* 4.7.2.3 Clock Multiplier Descriptor */
+
+struct uac_clock_multiplier_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDescriptorSubtype;
+ __u8 bClockID;
+ __u8 bCSourceID;
+ __u8 bmControls;
+ __u8 iClockMultiplier;
} __attribute__((packed));
/* 4.7.2.4 Input terminal descriptor */
diff --git a/include/linux/usb/audio.h b/include/linux/usb/audio.h
index 5d646c3..c51200c 100644
--- a/include/linux/usb/audio.h
+++ b/include/linux/usb/audio.h
@@ -47,6 +47,15 @@
#define UAC_FORMAT_TYPE 0x02
#define UAC_FORMAT_SPECIFIC 0x03
+/* A.7 Processing Unit Process Types */
+#define UAC_PROCESS_UNDEFINED 0x00
+#define UAC_PROCESS_UP_DOWNMIX 0x01
+#define UAC_PROCESS_DOLBY_PROLOGIC 0x02
+#define UAC_PROCESS_STEREO_EXTENDER 0x03
+#define UAC_PROCESS_REVERB 0x04
+#define UAC_PROCESS_CHORUS 0x05
+#define UAC_PROCESS_DYN_RANGE_COMP 0x06
+
/* A.8 Audio Class-Specific Endpoint Descriptor Subtypes */
#define UAC_EP_GENERAL 0x01
@@ -73,6 +82,60 @@
#define UAC_GET_STAT 0xff
+/* A.10 Control Selector Codes */
+
+/* A.10.1 Terminal Control Selectors */
+#define UAC_TERM_COPY_PROTECT 0x01
+
+/* A.10.2 Feature Unit Control Selectors */
+#define UAC_FU_MUTE 0x01
+#define UAC_FU_VOLUME 0x02
+#define UAC_FU_BASS 0x03
+#define UAC_FU_MID 0x04
+#define UAC_FU_TREBLE 0x05
+#define UAC_FU_GRAPHIC_EQUALIZER 0x06
+#define UAC_FU_AUTOMATIC_GAIN 0x07
+#define UAC_FU_DELAY 0x08
+#define UAC_FU_BASS_BOOST 0x09
+#define UAC_FU_LOUDNESS 0x0a
+
+#define UAC_CONTROL_BIT(CS) (1 << ((CS) - 1))
+
+/* A.10.3.1 Up/Down-mix Processing Unit Controls Selectors */
+#define UAC_UD_ENABLE 0x01
+#define UAC_UD_MODE_SELECT 0x02
+
+/* A.10.3.2 Dolby Prologic (tm) Processing Unit Controls Selectors */
+#define UAC_DP_ENABLE 0x01
+#define UAC_DP_MODE_SELECT 0x02
+
+/* A.10.3.3 3D Stereo Extender Processing Unit Control Selectors */
+#define UAC_3D_ENABLE 0x01
+#define UAC_3D_SPACE 0x02
+
+/* A.10.3.4 Reverberation Processing Unit Control Selectors */
+#define UAC_REVERB_ENABLE 0x01
+#define UAC_REVERB_LEVEL 0x02
+#define UAC_REVERB_TIME 0x03
+#define UAC_REVERB_FEEDBACK 0x04
+
+/* A.10.3.5 Chorus Processing Unit Control Selectors */
+#define UAC_CHORUS_ENABLE 0x01
+#define UAC_CHORUS_LEVEL 0x02
+#define UAC_CHORUS_RATE 0x03
+#define UAC_CHORUS_DEPTH 0x04
+
+/* A.10.3.6 Dynamic Range Compressor Unit Control Selectors */
+#define UAC_DCR_ENABLE 0x01
+#define UAC_DCR_RATE 0x02
+#define UAC_DCR_MAXAMPL 0x03
+#define UAC_DCR_THRESHOLD 0x04
+#define UAC_DCR_ATTACK_TIME 0x05
+#define UAC_DCR_RELEASE_TIME 0x06
+
+/* A.10.4 Extension Unit Control Selectors */
+#define UAC_XU_ENABLE 0x01
+
/* MIDI - A.1 MS Class-Specific Interface Descriptor Subtypes */
#define UAC_MS_HEADER 0x01
#define UAC_MIDI_IN_JACK 0x02
@@ -244,7 +307,7 @@
static inline __u8 uac_selector_unit_iSelector(struct uac_selector_unit_descriptor *desc)
{
__u8 *raw = (__u8 *) desc;
- return raw[9 + desc->bLength - 1];
+ return raw[desc->bLength - 1];
}
/* 4.3.2.5 Feature Unit Descriptor */
@@ -463,31 +526,6 @@
#define UAC_EP_CS_ATTR_PITCH_CONTROL 0x02
#define UAC_EP_CS_ATTR_FILL_MAX 0x80
-/* A.10.2 Feature Unit Control Selectors */
-
-#define UAC_FU_CONTROL_UNDEFINED 0x00
-#define UAC_MUTE_CONTROL 0x01
-#define UAC_VOLUME_CONTROL 0x02
-#define UAC_BASS_CONTROL 0x03
-#define UAC_MID_CONTROL 0x04
-#define UAC_TREBLE_CONTROL 0x05
-#define UAC_GRAPHIC_EQUALIZER_CONTROL 0x06
-#define UAC_AUTOMATIC_GAIN_CONTROL 0x07
-#define UAC_DELAY_CONTROL 0x08
-#define UAC_BASS_BOOST_CONTROL 0x09
-#define UAC_LOUDNESS_CONTROL 0x0a
-
-#define UAC_FU_MUTE (1 << (UAC_MUTE_CONTROL - 1))
-#define UAC_FU_VOLUME (1 << (UAC_VOLUME_CONTROL - 1))
-#define UAC_FU_BASS (1 << (UAC_BASS_CONTROL - 1))
-#define UAC_FU_MID (1 << (UAC_MID_CONTROL - 1))
-#define UAC_FU_TREBLE (1 << (UAC_TREBLE_CONTROL - 1))
-#define UAC_FU_GRAPHIC_EQ (1 << (UAC_GRAPHIC_EQUALIZER_CONTROL - 1))
-#define UAC_FU_AUTO_GAIN (1 << (UAC_AUTOMATIC_GAIN_CONTROL - 1))
-#define UAC_FU_DELAY (1 << (UAC_DELAY_CONTROL - 1))
-#define UAC_FU_BASS_BOOST (1 << (UAC_BASS_BOOST_CONTROL - 1))
-#define UAC_FU_LOUDNESS (1 << (UAC_LOUDNESS_CONTROL - 1))
-
/* status word format (3.7.1.1) */
#define UAC1_STATUS_TYPE_ORIG_MASK 0x0f
diff --git a/include/linux/vgaarb.h b/include/linux/vgaarb.h
index 2dfaa29..c9a9759 100644
--- a/include/linux/vgaarb.h
+++ b/include/linux/vgaarb.h
@@ -5,6 +5,27 @@
* (C) Copyright 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org>
* (C) Copyright 2007 Paulo R. Zanoni <przanoni@gmail.com>
* (C) Copyright 2007, 2009 Tiago Vignatti <vignatti@freedesktop.org>
+ *
+ * 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 (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS
+ * IN THE SOFTWARE.
+ *
*/
#ifndef LINUX_VGA_H
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index cc97d6c..d63ef8f 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -56,24 +56,6 @@
unsigned for_reclaim:1; /* Invoked from the page allocator */
unsigned range_cyclic:1; /* range_start is cyclic */
unsigned more_io:1; /* more io to be dispatched */
- /*
- * write_cache_pages() won't update wbc->nr_to_write and
- * mapping->writeback_index if no_nrwrite_index_update
- * is set. write_cache_pages() may write more than we
- * requested and we want to make sure nr_to_write and
- * writeback_index are updated in a consistent manner
- * so we use a single control to update them
- */
- unsigned no_nrwrite_index_update:1;
-
- /*
- * For WB_SYNC_ALL, the sb must always be pinned. For WB_SYNC_NONE,
- * the writeback code will pin the sb for the caller. However,
- * for eg umount, the caller does WB_SYNC_NONE but already has
- * the sb pinned. If the below is set, caller already has the
- * sb pinned.
- */
- unsigned sb_pinned:1;
};
/*
@@ -82,7 +64,6 @@
struct bdi_writeback;
int inode_wait(void *);
void writeback_inodes_sb(struct super_block *);
-void writeback_inodes_sb_locked(struct super_block *);
int writeback_inodes_sb_if_idle(struct super_block *);
void sync_inodes_sb(struct super_block *);
void writeback_inodes_wbc(struct writeback_control *wbc);
diff --git a/include/media/rc-map.h b/include/media/rc-map.h
index 5833966..c78e99a 100644
--- a/include/media/rc-map.h
+++ b/include/media/rc-map.h
@@ -55,7 +55,8 @@
#define RC_MAP_AVERMEDIA_A16D "rc-avermedia-a16d"
#define RC_MAP_AVERMEDIA_CARDBUS "rc-avermedia-cardbus"
#define RC_MAP_AVERMEDIA_DVBT "rc-avermedia-dvbt"
-#define RC_MAP_AVERMEDIA_M135A_RM_JX "rc-avermedia-m135a-rm-jx"
+#define RC_MAP_AVERMEDIA_M135A "rc-avermedia-m135a"
+#define RC_MAP_AVERMEDIA_M733A_RM_K6 "rc-avermedia-m733a-rm-k6"
#define RC_MAP_AVERMEDIA "rc-avermedia"
#define RC_MAP_AVERTV_303 "rc-avertv-303"
#define RC_MAP_BEHOLD_COLUMBUS "rc-behold-columbus"
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index c9a5bbf..b8289c2 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -66,7 +66,7 @@
* .get_formats() fail, .put_formats() will not be called at all, the
* failing .get_formats() must then clean up internally.
*/
- int (*get_formats)(struct soc_camera_device *, int,
+ int (*get_formats)(struct soc_camera_device *, unsigned int,
struct soc_camera_format_xlate *);
void (*put_formats)(struct soc_camera_device *);
int (*cropcap)(struct soc_camera_device *, struct v4l2_cropcap *);
diff --git a/include/media/v4l2-mediabus.h b/include/media/v4l2-mediabus.h
index 0dbe02a..865cda7 100644
--- a/include/media/v4l2-mediabus.h
+++ b/include/media/v4l2-mediabus.h
@@ -40,6 +40,7 @@
V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE,
V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE,
V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE,
+ V4L2_MBUS_FMT_SGRBG8_1X8,
};
/**
@@ -58,4 +59,24 @@
enum v4l2_colorspace colorspace;
};
+static inline void v4l2_fill_pix_format(struct v4l2_pix_format *pix_fmt,
+ const struct v4l2_mbus_framefmt *mbus_fmt)
+{
+ pix_fmt->width = mbus_fmt->width;
+ pix_fmt->height = mbus_fmt->height;
+ pix_fmt->field = mbus_fmt->field;
+ pix_fmt->colorspace = mbus_fmt->colorspace;
+}
+
+static inline void v4l2_fill_mbus_format(struct v4l2_mbus_framefmt *mbus_fmt,
+ const struct v4l2_pix_format *pix_fmt,
+ enum v4l2_mbus_pixelcode code)
+{
+ mbus_fmt->width = pix_fmt->width;
+ mbus_fmt->height = pix_fmt->height;
+ mbus_fmt->field = pix_fmt->field;
+ mbus_fmt->colorspace = pix_fmt->colorspace;
+ mbus_fmt->code = code;
+}
+
#endif
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index a888893..02c6f4d 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -246,7 +246,7 @@
struct v4l2_dv_timings *timings);
int (*g_dv_timings)(struct v4l2_subdev *sd,
struct v4l2_dv_timings *timings);
- int (*enum_mbus_fmt)(struct v4l2_subdev *sd, int index,
+ int (*enum_mbus_fmt)(struct v4l2_subdev *sd, unsigned int index,
enum v4l2_mbus_pixelcode *code);
int (*g_mbus_fmt)(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *fmt);
diff --git a/include/net/dst.h b/include/net/dst.h
index 612069b..81d1413 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -250,11 +250,11 @@
* Linux networking. Thus, destinations are stackable.
*/
-static inline struct dst_entry *dst_pop(struct dst_entry *dst)
+static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb)
{
- struct dst_entry *child = dst_clone(dst->child);
+ struct dst_entry *child = skb_dst(skb)->child;
- dst_release(dst);
+ skb_dst_drop(skb);
return child;
}
diff --git a/include/net/snmp.h b/include/net/snmp.h
index 92456f1..899003d 100644
--- a/include/net/snmp.h
+++ b/include/net/snmp.h
@@ -134,7 +134,7 @@
#define SNMP_ADD_STATS_USER(mib, field, addend) \
this_cpu_add(mib[1]->mibs[field], addend)
#define SNMP_ADD_STATS(mib, field, addend) \
- this_cpu_add(mib[0]->mibs[field], addend)
+ this_cpu_add(mib[!in_softirq()]->mibs[field], addend)
/*
* Use "__typeof__(*mib[0]) *ptr" instead of "__typeof__(mib[0]) ptr"
* to make @ptr a non-percpu pointer.
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index c50a97f..b7bdecb 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -327,6 +327,14 @@
sector_t, int []);
/*
+ * This function is called when one or more partitions on the
+ * device reach beyond the end of the device.
+ *
+ * Status: OPTIONAL
+ */
+ void (*unlock_native_capacity)(struct scsi_device *);
+
+ /*
* Can be used to export driver statistics and other infos to the
* world outside the kernel ie. userspace and it also provides an
* interface to feed the driver with information.
diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
index f5b1ba9..f3865c7 100644
--- a/include/trace/events/ext4.h
+++ b/include/trace/events/ext4.h
@@ -306,7 +306,6 @@
__field( int, pages_written )
__field( long, pages_skipped )
__field( char, more_io )
- __field( char, no_nrwrite_index_update )
__field( pgoff_t, writeback_index )
),
@@ -317,16 +316,14 @@
__entry->pages_written = pages_written;
__entry->pages_skipped = wbc->pages_skipped;
__entry->more_io = wbc->more_io;
- __entry->no_nrwrite_index_update = wbc->no_nrwrite_index_update;
__entry->writeback_index = inode->i_mapping->writeback_index;
),
- TP_printk("dev %s ino %lu ret %d pages_written %d pages_skipped %ld more_io %d no_nrwrite_index_update %d writeback_index %lu",
+ TP_printk("dev %s ino %lu ret %d pages_written %d pages_skipped %ld more_io %d writeback_index %lu",
jbd2_dev_to_name(__entry->dev),
(unsigned long) __entry->ino, __entry->ret,
__entry->pages_written, __entry->pages_skipped,
__entry->more_io,
- __entry->no_nrwrite_index_update,
(unsigned long) __entry->writeback_index)
);
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index 4f733ec..b9e1dd6 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -115,6 +115,23 @@
TP_PROTO(struct task_struct *p, int success),
TP_ARGS(p, success));
+#ifdef CREATE_TRACE_POINTS
+static inline long __trace_sched_switch_state(struct task_struct *p)
+{
+ long state = p->state;
+
+#ifdef CONFIG_PREEMPT
+ /*
+ * For all intents and purposes a preempted task is a running task.
+ */
+ if (task_thread_info(p)->preempt_count & PREEMPT_ACTIVE)
+ state = TASK_RUNNING;
+#endif
+
+ return state;
+}
+#endif
+
/*
* Tracepoint for task switches, performed by the scheduler:
*/
@@ -139,7 +156,7 @@
memcpy(__entry->next_comm, next->comm, TASK_COMM_LEN);
__entry->prev_pid = prev->pid;
__entry->prev_prio = prev->prio;
- __entry->prev_state = prev->state;
+ __entry->prev_state = __trace_sched_switch_state(prev);
memcpy(__entry->prev_comm, prev->comm, TASK_COMM_LEN);
__entry->next_pid = next->pid;
__entry->next_prio = next->prio;
diff --git a/include/trace/events/signal.h b/include/trace/events/signal.h
index 814566c..17df434 100644
--- a/include/trace/events/signal.h
+++ b/include/trace/events/signal.h
@@ -10,7 +10,8 @@
#define TP_STORE_SIGINFO(__entry, info) \
do { \
- if (info == SEND_SIG_NOINFO) { \
+ if (info == SEND_SIG_NOINFO || \
+ info == SEND_SIG_FORCED) { \
__entry->errno = 0; \
__entry->code = SI_USER; \
} else if (info == SEND_SIG_PRIV) { \
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h
index 3d685d1..5a64905 100644
--- a/include/trace/ftrace.h
+++ b/include/trace/ftrace.h
@@ -725,7 +725,7 @@
\
{ assign; } \
\
- head = per_cpu_ptr(event_call->perf_events, smp_processor_id());\
+ head = this_cpu_ptr(event_call->perf_events); \
perf_trace_buf_submit(entry, __entry_size, rctx, __addr, \
__count, &__regs, head); \
}
diff --git a/init/main.c b/init/main.c
index 3bdb152..ac2e4a5 100644
--- a/init/main.c
+++ b/init/main.c
@@ -125,7 +125,9 @@
#ifdef CONFIG_SMP
/* Setup configured maximum number of CPUs to activate */
-unsigned int __initdata setup_max_cpus = NR_CPUS;
+unsigned int setup_max_cpus = NR_CPUS;
+EXPORT_SYMBOL(setup_max_cpus);
+
/*
* Setup routine for controlling SMP activation
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 5108232..c93fd3f 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -176,7 +176,6 @@
}
return inode;
out_inode:
- make_bad_inode(inode);
iput(inode);
return NULL;
}
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 422cb19..3ac6f5b 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -4598,7 +4598,7 @@
parent_css = parent->subsys[subsys_id];
child_css = child->subsys[subsys_id];
parent_id = parent_css->id;
- depth = parent_id->depth;
+ depth = parent_id->depth + 1;
child_id = get_new_cssid(ss, depth);
if (IS_ERR(child_id))
diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c
index b724c79..184cd82 100644
--- a/kernel/debug/kdb/kdb_main.c
+++ b/kernel/debug/kdb/kdb_main.c
@@ -1857,12 +1857,6 @@
}
#if defined(CONFIG_MODULES)
-/* modules using other modules */
-struct module_use {
- struct list_head list;
- struct module *module_which_uses;
-};
-
/*
* kdb_lsmod - This function implements the 'lsmod' command. Lists
* currently loaded kernel modules.
@@ -1894,9 +1888,9 @@
{
struct module_use *use;
kdb_printf(" [ ");
- list_for_each_entry(use, &mod->modules_which_use_me,
- list)
- kdb_printf("%s ", use->module_which_uses->name);
+ list_for_each_entry(use, &mod->source_list,
+ source_list)
+ kdb_printf("%s ", use->target->name);
kdb_printf("]\n");
}
#endif
diff --git a/kernel/exec_domain.c b/kernel/exec_domain.c
index c35452c..dd62f8e 100644
--- a/kernel/exec_domain.c
+++ b/kernel/exec_domain.c
@@ -27,7 +27,7 @@
static DEFINE_RWLOCK(exec_domains_lock);
-static u_long ident_map[32] = {
+static unsigned long ident_map[32] = {
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23,
@@ -56,10 +56,10 @@
}
static struct exec_domain *
-lookup_exec_domain(u_long personality)
+lookup_exec_domain(unsigned int personality)
{
- struct exec_domain * ep;
- u_long pers = personality(personality);
+ unsigned int pers = personality(personality);
+ struct exec_domain *ep;
read_lock(&exec_domains_lock);
for (ep = exec_domains; ep; ep = ep->next) {
@@ -70,7 +70,7 @@
#ifdef CONFIG_MODULES
read_unlock(&exec_domains_lock);
- request_module("personality-%ld", pers);
+ request_module("personality-%d", pers);
read_lock(&exec_domains_lock);
for (ep = exec_domains; ep; ep = ep->next) {
@@ -135,7 +135,7 @@
}
int
-__set_personality(u_long personality)
+__set_personality(unsigned int personality)
{
struct exec_domain *ep, *oep;
@@ -188,9 +188,9 @@
module_init(proc_execdomains_init);
#endif
-SYSCALL_DEFINE1(personality, u_long, personality)
+SYSCALL_DEFINE1(personality, unsigned int, personality)
{
- u_long old = current->personality;
+ unsigned int old = current->personality;
if (personality != 0xffffffff) {
set_personality(personality);
@@ -198,7 +198,7 @@
return -EINVAL;
}
- return (long)old;
+ return old;
}
diff --git a/kernel/futex.c b/kernel/futex.c
index e7a35f1..6a3a5fa 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -429,20 +429,11 @@
static struct task_struct * futex_find_get_task(pid_t pid)
{
struct task_struct *p;
- const struct cred *cred = current_cred(), *pcred;
rcu_read_lock();
p = find_task_by_vpid(pid);
- if (!p) {
- p = ERR_PTR(-ESRCH);
- } else {
- pcred = __task_cred(p);
- if (cred->euid != pcred->euid &&
- cred->euid != pcred->uid)
- p = ERR_PTR(-ESRCH);
- else
- get_task_struct(p);
- }
+ if (p)
+ get_task_struct(p);
rcu_read_unlock();
@@ -564,8 +555,8 @@
if (!pid)
return -ESRCH;
p = futex_find_get_task(pid);
- if (IS_ERR(p))
- return PTR_ERR(p);
+ if (!p)
+ return -ESRCH;
/*
* We need to look at the task state flags to figure out,
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 3164ba7..e149748 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -456,6 +456,9 @@
/* note that IRQF_TRIGGER_MASK == IRQ_TYPE_SENSE_MASK */
desc->status &= ~(IRQ_LEVEL | IRQ_TYPE_SENSE_MASK);
desc->status |= flags;
+
+ if (chip != desc->chip)
+ irq_chip_set_defaults(desc->chip);
}
return ret;
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 474a847..131b170 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -1089,9 +1089,10 @@
size_t crash_get_memory_size(void)
{
- size_t size;
+ size_t size = 0;
mutex_lock(&kexec_mutex);
- size = crashk_res.end - crashk_res.start + 1;
+ if (crashk_res.end != crashk_res.start)
+ size = crashk_res.end - crashk_res.start + 1;
mutex_unlock(&kexec_mutex);
return size;
}
@@ -1134,7 +1135,7 @@
free_reserved_phys_range(end, crashk_res.end);
- if (start == end)
+ if ((start == end) && (crashk_res.parent != NULL))
release_resource(&crashk_res);
crashk_res.end = end - 1;
diff --git a/kernel/module.c b/kernel/module.c
index 0129769..8c6b428 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -72,7 +72,11 @@
/* If this is set, the section belongs in the init part of the module */
#define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1))
-/* List of modules, protected by module_mutex or preempt_disable
+/*
+ * Mutex protects:
+ * 1) List of modules (also safely readable with preempt_disable),
+ * 2) module_use links,
+ * 3) module_addr_min/module_addr_max.
* (delete uses stop_machine/add uses RCU list operations). */
DEFINE_MUTEX(module_mutex);
EXPORT_SYMBOL_GPL(module_mutex);
@@ -90,7 +94,8 @@
static BLOCKING_NOTIFIER_HEAD(module_notify_list);
-/* Bounds of module allocation, for speeding __module_address */
+/* Bounds of module allocation, for speeding __module_address.
+ * Protected by module_mutex. */
static unsigned long module_addr_min = -1UL, module_addr_max = 0;
int register_module_notifier(struct notifier_block * nb)
@@ -329,7 +334,7 @@
}
/* Find a symbol and return it, along with, (optional) crc and
- * (optional) module which owns it */
+ * (optional) module which owns it. Needs preempt disabled or module_mutex. */
const struct kernel_symbol *find_symbol(const char *name,
struct module **owner,
const unsigned long **crc,
@@ -523,7 +528,8 @@
{
int cpu;
- INIT_LIST_HEAD(&mod->modules_which_use_me);
+ INIT_LIST_HEAD(&mod->source_list);
+ INIT_LIST_HEAD(&mod->target_list);
for_each_possible_cpu(cpu) {
per_cpu_ptr(mod->refptr, cpu)->incs = 0;
per_cpu_ptr(mod->refptr, cpu)->decs = 0;
@@ -535,20 +541,13 @@
mod->waiter = current;
}
-/* modules using other modules */
-struct module_use
-{
- struct list_head list;
- struct module *module_which_uses;
-};
-
/* Does a already use b? */
static int already_uses(struct module *a, struct module *b)
{
struct module_use *use;
- list_for_each_entry(use, &b->modules_which_use_me, list) {
- if (use->module_which_uses == a) {
+ list_for_each_entry(use, &b->source_list, source_list) {
+ if (use->source == a) {
DEBUGP("%s uses %s!\n", a->name, b->name);
return 1;
}
@@ -557,62 +556,68 @@
return 0;
}
-/* Module a uses b */
-int use_module(struct module *a, struct module *b)
+/*
+ * Module a uses b
+ * - we add 'a' as a "source", 'b' as a "target" of module use
+ * - the module_use is added to the list of 'b' sources (so
+ * 'b' can walk the list to see who sourced them), and of 'a'
+ * targets (so 'a' can see what modules it targets).
+ */
+static int add_module_usage(struct module *a, struct module *b)
{
struct module_use *use;
- int no_warn, err;
-
- if (b == NULL || already_uses(a, b)) return 1;
-
- /* If we're interrupted or time out, we fail. */
- if (wait_event_interruptible_timeout(
- module_wq, (err = strong_try_module_get(b)) != -EBUSY,
- 30 * HZ) <= 0) {
- printk("%s: gave up waiting for init of module %s.\n",
- a->name, b->name);
- return 0;
- }
-
- /* If strong_try_module_get() returned a different error, we fail. */
- if (err)
- return 0;
DEBUGP("Allocating new usage for %s.\n", a->name);
use = kmalloc(sizeof(*use), GFP_ATOMIC);
if (!use) {
- printk("%s: out of memory loading\n", a->name);
- module_put(b);
- return 0;
+ printk(KERN_WARNING "%s: out of memory loading\n", a->name);
+ return -ENOMEM;
}
- use->module_which_uses = a;
- list_add(&use->list, &b->modules_which_use_me);
- no_warn = sysfs_create_link(b->holders_dir, &a->mkobj.kobj, a->name);
- return 1;
+ use->source = a;
+ use->target = b;
+ list_add(&use->source_list, &b->source_list);
+ list_add(&use->target_list, &a->target_list);
+ return 0;
}
-EXPORT_SYMBOL_GPL(use_module);
+
+/* Module a uses b: caller needs module_mutex() */
+int ref_module(struct module *a, struct module *b)
+{
+ int err;
+
+ if (b == NULL || already_uses(a, b))
+ return 0;
+
+ /* If module isn't available, we fail. */
+ err = strong_try_module_get(b);
+ if (err)
+ return err;
+
+ err = add_module_usage(a, b);
+ if (err) {
+ module_put(b);
+ return err;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ref_module);
/* Clear the unload stuff of the module. */
static void module_unload_free(struct module *mod)
{
- struct module *i;
+ struct module_use *use, *tmp;
- list_for_each_entry(i, &modules, list) {
- struct module_use *use;
-
- list_for_each_entry(use, &i->modules_which_use_me, list) {
- if (use->module_which_uses == mod) {
- DEBUGP("%s unusing %s\n", mod->name, i->name);
- module_put(i);
- list_del(&use->list);
- kfree(use);
- sysfs_remove_link(i->holders_dir, mod->name);
- /* There can be at most one match. */
- break;
- }
- }
+ mutex_lock(&module_mutex);
+ list_for_each_entry_safe(use, tmp, &mod->target_list, target_list) {
+ struct module *i = use->target;
+ DEBUGP("%s unusing %s\n", mod->name, i->name);
+ module_put(i);
+ list_del(&use->source_list);
+ list_del(&use->target_list);
+ kfree(use);
}
+ mutex_unlock(&module_mutex);
}
#ifdef CONFIG_MODULE_FORCE_UNLOAD
@@ -735,7 +740,7 @@
goto out;
}
- if (!list_empty(&mod->modules_which_use_me)) {
+ if (!list_empty(&mod->source_list)) {
/* Other modules depend on us: get rid of them first. */
ret = -EWOULDBLOCK;
goto out;
@@ -779,13 +784,14 @@
blocking_notifier_call_chain(&module_notify_list,
MODULE_STATE_GOING, mod);
async_synchronize_full();
- mutex_lock(&module_mutex);
+
/* Store the name of the last unloaded module for diagnostic purposes */
strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module));
ddebug_remove_module(mod->name);
- free_module(mod);
- out:
+ free_module(mod);
+ return 0;
+out:
mutex_unlock(&module_mutex);
return ret;
}
@@ -799,9 +805,9 @@
/* Always include a trailing , so userspace can differentiate
between this and the old multi-field proc format. */
- list_for_each_entry(use, &mod->modules_which_use_me, list) {
+ list_for_each_entry(use, &mod->source_list, source_list) {
printed_something = 1;
- seq_printf(m, "%s,", use->module_which_uses->name);
+ seq_printf(m, "%s,", use->source->name);
}
if (mod->init != NULL && mod->exit == NULL) {
@@ -880,11 +886,11 @@
{
}
-int use_module(struct module *a, struct module *b)
+int ref_module(struct module *a, struct module *b)
{
- return strong_try_module_get(b) == 0;
+ return strong_try_module_get(b);
}
-EXPORT_SYMBOL_GPL(use_module);
+EXPORT_SYMBOL_GPL(ref_module);
static inline void module_unload_init(struct module *mod)
{
@@ -1001,6 +1007,8 @@
{
const unsigned long *crc;
+ /* Since this should be found in kernel (which can't be removed),
+ * no locking is necessary. */
if (!find_symbol(MODULE_SYMBOL_PREFIX "module_layout", NULL,
&crc, true, false))
BUG();
@@ -1043,29 +1051,62 @@
}
#endif /* CONFIG_MODVERSIONS */
-/* Resolve a symbol for this module. I.e. if we find one, record usage.
- Must be holding module_mutex. */
+/* Resolve a symbol for this module. I.e. if we find one, record usage. */
static const struct kernel_symbol *resolve_symbol(Elf_Shdr *sechdrs,
unsigned int versindex,
const char *name,
- struct module *mod)
+ struct module *mod,
+ char ownername[])
{
struct module *owner;
const struct kernel_symbol *sym;
const unsigned long *crc;
+ int err;
+ mutex_lock(&module_mutex);
sym = find_symbol(name, &owner, &crc,
!(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true);
- /* use_module can fail due to OOM,
- or module initialization or unloading */
- if (sym) {
- if (!check_version(sechdrs, versindex, name, mod, crc, owner)
- || !use_module(mod, owner))
- sym = NULL;
+ if (!sym)
+ goto unlock;
+
+ if (!check_version(sechdrs, versindex, name, mod, crc, owner)) {
+ sym = ERR_PTR(-EINVAL);
+ goto getname;
}
+
+ err = ref_module(mod, owner);
+ if (err) {
+ sym = ERR_PTR(err);
+ goto getname;
+ }
+
+getname:
+ /* We must make copy under the lock if we failed to get ref. */
+ strncpy(ownername, module_name(owner), MODULE_NAME_LEN);
+unlock:
+ mutex_unlock(&module_mutex);
return sym;
}
+static const struct kernel_symbol *resolve_symbol_wait(Elf_Shdr *sechdrs,
+ unsigned int versindex,
+ const char *name,
+ struct module *mod)
+{
+ const struct kernel_symbol *ksym;
+ char ownername[MODULE_NAME_LEN];
+
+ if (wait_event_interruptible_timeout(module_wq,
+ !IS_ERR(ksym = resolve_symbol(sechdrs, versindex, name,
+ mod, ownername)) ||
+ PTR_ERR(ksym) != -EBUSY,
+ 30 * HZ) <= 0) {
+ printk(KERN_WARNING "%s: gave up waiting for init of module %s.\n",
+ mod->name, ownername);
+ }
+ return ksym;
+}
+
/*
* /sys/module/foo/sections stuff
* J. Corbet <corbet@lwn.net>
@@ -1295,7 +1336,34 @@
#endif
#ifdef CONFIG_SYSFS
-int module_add_modinfo_attrs(struct module *mod)
+static void add_usage_links(struct module *mod)
+{
+#ifdef CONFIG_MODULE_UNLOAD
+ struct module_use *use;
+ int nowarn;
+
+ mutex_lock(&module_mutex);
+ list_for_each_entry(use, &mod->target_list, target_list) {
+ nowarn = sysfs_create_link(use->target->holders_dir,
+ &mod->mkobj.kobj, mod->name);
+ }
+ mutex_unlock(&module_mutex);
+#endif
+}
+
+static void del_usage_links(struct module *mod)
+{
+#ifdef CONFIG_MODULE_UNLOAD
+ struct module_use *use;
+
+ mutex_lock(&module_mutex);
+ list_for_each_entry(use, &mod->target_list, target_list)
+ sysfs_remove_link(use->target->holders_dir, mod->name);
+ mutex_unlock(&module_mutex);
+#endif
+}
+
+static int module_add_modinfo_attrs(struct module *mod)
{
struct module_attribute *attr;
struct module_attribute *temp_attr;
@@ -1321,7 +1389,7 @@
return error;
}
-void module_remove_modinfo_attrs(struct module *mod)
+static void module_remove_modinfo_attrs(struct module *mod)
{
struct module_attribute *attr;
int i;
@@ -1337,7 +1405,7 @@
kfree(mod->modinfo_attrs);
}
-int mod_sysfs_init(struct module *mod)
+static int mod_sysfs_init(struct module *mod)
{
int err;
struct kobject *kobj;
@@ -1371,12 +1439,16 @@
return err;
}
-int mod_sysfs_setup(struct module *mod,
+static int mod_sysfs_setup(struct module *mod,
struct kernel_param *kparam,
unsigned int num_params)
{
int err;
+ err = mod_sysfs_init(mod);
+ if (err)
+ goto out;
+
mod->holders_dir = kobject_create_and_add("holders", &mod->mkobj.kobj);
if (!mod->holders_dir) {
err = -ENOMEM;
@@ -1391,6 +1463,8 @@
if (err)
goto out_unreg_param;
+ add_usage_links(mod);
+
kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD);
return 0;
@@ -1400,6 +1474,7 @@
kobject_put(mod->holders_dir);
out_unreg:
kobject_put(&mod->mkobj.kobj);
+out:
return err;
}
@@ -1410,14 +1485,40 @@
#else /* CONFIG_SYSFS */
+static inline int mod_sysfs_init(struct module *mod)
+{
+ return 0;
+}
+
+static inline int mod_sysfs_setup(struct module *mod,
+ struct kernel_param *kparam,
+ unsigned int num_params)
+{
+ return 0;
+}
+
+static inline int module_add_modinfo_attrs(struct module *mod)
+{
+ return 0;
+}
+
+static inline void module_remove_modinfo_attrs(struct module *mod)
+{
+}
+
static void mod_sysfs_fini(struct module *mod)
{
}
+static void del_usage_links(struct module *mod)
+{
+}
+
#endif /* CONFIG_SYSFS */
static void mod_kobject_remove(struct module *mod)
{
+ del_usage_links(mod);
module_remove_modinfo_attrs(mod);
module_param_sysfs_remove(mod);
kobject_put(mod->mkobj.drivers_dir);
@@ -1436,13 +1537,15 @@
return 0;
}
-/* Free a module, remove from lists, etc (must hold module_mutex). */
+/* Free a module, remove from lists, etc. */
static void free_module(struct module *mod)
{
trace_module_free(mod);
/* Delete from various lists */
+ mutex_lock(&module_mutex);
stop_machine(__unlink_module, mod, NULL);
+ mutex_unlock(&module_mutex);
remove_notes_attrs(mod);
remove_sect_attrs(mod);
mod_kobject_remove(mod);
@@ -1493,6 +1596,8 @@
/*
* Ensure that an exported symbol [global namespace] does not already exist
* in the kernel or in some other module's exported symbol table.
+ *
+ * You must hold the module_mutex.
*/
static int verify_export_symbols(struct module *mod)
{
@@ -1558,21 +1663,23 @@
break;
case SHN_UNDEF:
- ksym = resolve_symbol(sechdrs, versindex,
- strtab + sym[i].st_name, mod);
+ ksym = resolve_symbol_wait(sechdrs, versindex,
+ strtab + sym[i].st_name,
+ mod);
/* Ok if resolved. */
- if (ksym) {
+ if (ksym && !IS_ERR(ksym)) {
sym[i].st_value = ksym->value;
break;
}
/* Ok if weak. */
- if (ELF_ST_BIND(sym[i].st_info) == STB_WEAK)
+ if (!ksym && ELF_ST_BIND(sym[i].st_info) == STB_WEAK)
break;
- printk(KERN_WARNING "%s: Unknown symbol %s\n",
- mod->name, strtab + sym[i].st_name);
- ret = -ENOENT;
+ printk(KERN_WARNING "%s: Unknown symbol %s (err %li)\n",
+ mod->name, strtab + sym[i].st_name,
+ PTR_ERR(ksym));
+ ret = PTR_ERR(ksym) ?: -ENOENT;
break;
default:
@@ -1960,11 +2067,13 @@
void *ret = module_alloc(size);
if (ret) {
+ mutex_lock(&module_mutex);
/* Update module bounds. */
if ((unsigned long)ret < module_addr_min)
module_addr_min = (unsigned long)ret;
if ((unsigned long)ret + size > module_addr_max)
module_addr_max = (unsigned long)ret + size;
+ mutex_unlock(&module_mutex);
}
return ret;
}
@@ -2139,11 +2248,6 @@
goto free_mod;
}
- if (find_module(mod->name)) {
- err = -EEXIST;
- goto free_mod;
- }
-
mod->state = MODULE_STATE_COMING;
/* Allow arches to frob section contents and sizes. */
@@ -2234,11 +2338,6 @@
/* Now we've moved module, initialize linked lists, etc. */
module_unload_init(mod);
- /* add kobject, so we can reference it. */
- err = mod_sysfs_init(mod);
- if (err)
- goto free_unload;
-
/* Set up license info based on the info section */
set_license(mod, get_modinfo(sechdrs, infoindex, "license"));
@@ -2363,11 +2462,6 @@
goto cleanup;
}
- /* Find duplicate symbols */
- err = verify_export_symbols(mod);
- if (err < 0)
- goto cleanup;
-
/* Set up and sort exception table */
mod->extable = section_objs(hdr, sechdrs, secstrings, "__ex_table",
sizeof(*mod->extable), &mod->num_exentries);
@@ -2426,7 +2520,19 @@
* function to insert in a way safe to concurrent readers.
* The mutex protects against concurrent writers.
*/
+ mutex_lock(&module_mutex);
+ if (find_module(mod->name)) {
+ err = -EEXIST;
+ goto unlock;
+ }
+
+ /* Find duplicate symbols */
+ err = verify_export_symbols(mod);
+ if (err < 0)
+ goto unlock;
+
list_add_rcu(&mod->list, &modules);
+ mutex_unlock(&module_mutex);
err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, NULL);
if (err < 0)
@@ -2435,6 +2541,7 @@
err = mod_sysfs_setup(mod, mod->kp, mod->num_kp);
if (err < 0)
goto unlink;
+
add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs);
add_notes_attrs(mod, hdr->e_shnum, secstrings, sechdrs);
@@ -2447,15 +2554,15 @@
return mod;
unlink:
+ mutex_lock(&module_mutex);
/* Unlink carefully: kallsyms could be walking list. */
list_del_rcu(&mod->list);
+ unlock:
+ mutex_unlock(&module_mutex);
synchronize_sched();
module_arch_cleanup(mod);
cleanup:
free_modinfo(mod);
- kobject_del(&mod->mkobj.kobj);
- kobject_put(&mod->mkobj.kobj);
- free_unload:
module_unload_free(mod);
#if defined(CONFIG_MODULE_UNLOAD)
free_percpu(mod->refptr);
@@ -2502,19 +2609,10 @@
if (!capable(CAP_SYS_MODULE) || modules_disabled)
return -EPERM;
- /* Only one module load at a time, please */
- if (mutex_lock_interruptible(&module_mutex) != 0)
- return -EINTR;
-
/* Do all the hard work */
mod = load_module(umod, len, uargs);
- if (IS_ERR(mod)) {
- mutex_unlock(&module_mutex);
+ if (IS_ERR(mod))
return PTR_ERR(mod);
- }
-
- /* Drop lock so they can recurse */
- mutex_unlock(&module_mutex);
blocking_notifier_call_chain(&module_notify_list,
MODULE_STATE_COMING, mod);
@@ -2531,9 +2629,7 @@
module_put(mod);
blocking_notifier_call_chain(&module_notify_list,
MODULE_STATE_GOING, mod);
- mutex_lock(&module_mutex);
free_module(mod);
- mutex_unlock(&module_mutex);
wake_up(&module_wq);
return ret;
}
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index bd7ce8c..ff86c55 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -283,14 +283,15 @@
static void
list_add_event(struct perf_event *event, struct perf_event_context *ctx)
{
- struct perf_event *group_leader = event->group_leader;
+ WARN_ON_ONCE(event->attach_state & PERF_ATTACH_CONTEXT);
+ event->attach_state |= PERF_ATTACH_CONTEXT;
/*
- * Depending on whether it is a standalone or sibling event,
- * add it straight to the context's event list, or to the group
- * leader's sibling list:
+ * If we're a stand alone event or group leader, we go to the context
+ * list, group events are kept attached to the group so that
+ * perf_group_detach can, at all times, locate all siblings.
*/
- if (group_leader == event) {
+ if (event->group_leader == event) {
struct list_head *list;
if (is_software_event(event))
@@ -298,13 +299,6 @@
list = ctx_group_list(event, ctx);
list_add_tail(&event->group_entry, list);
- } else {
- if (group_leader->group_flags & PERF_GROUP_SOFTWARE &&
- !is_software_event(event))
- group_leader->group_flags &= ~PERF_GROUP_SOFTWARE;
-
- list_add_tail(&event->group_entry, &group_leader->sibling_list);
- group_leader->nr_siblings++;
}
list_add_rcu(&event->event_entry, &ctx->event_list);
@@ -313,6 +307,24 @@
ctx->nr_stat++;
}
+static void perf_group_attach(struct perf_event *event)
+{
+ struct perf_event *group_leader = event->group_leader;
+
+ WARN_ON_ONCE(event->attach_state & PERF_ATTACH_GROUP);
+ event->attach_state |= PERF_ATTACH_GROUP;
+
+ if (group_leader == event)
+ return;
+
+ if (group_leader->group_flags & PERF_GROUP_SOFTWARE &&
+ !is_software_event(event))
+ group_leader->group_flags &= ~PERF_GROUP_SOFTWARE;
+
+ list_add_tail(&event->group_entry, &group_leader->sibling_list);
+ group_leader->nr_siblings++;
+}
+
/*
* Remove a event from the lists for its context.
* Must be called with ctx->mutex and ctx->lock held.
@@ -320,17 +332,22 @@
static void
list_del_event(struct perf_event *event, struct perf_event_context *ctx)
{
- if (list_empty(&event->group_entry))
+ /*
+ * We can have double detach due to exit/hot-unplug + close.
+ */
+ if (!(event->attach_state & PERF_ATTACH_CONTEXT))
return;
+
+ event->attach_state &= ~PERF_ATTACH_CONTEXT;
+
ctx->nr_events--;
if (event->attr.inherit_stat)
ctx->nr_stat--;
- list_del_init(&event->group_entry);
list_del_rcu(&event->event_entry);
- if (event->group_leader != event)
- event->group_leader->nr_siblings--;
+ if (event->group_leader == event)
+ list_del_init(&event->group_entry);
update_group_times(event);
@@ -345,21 +362,39 @@
event->state = PERF_EVENT_STATE_OFF;
}
-static void
-perf_destroy_group(struct perf_event *event, struct perf_event_context *ctx)
+static void perf_group_detach(struct perf_event *event)
{
struct perf_event *sibling, *tmp;
+ struct list_head *list = NULL;
+
+ /*
+ * We can have double detach due to exit/hot-unplug + close.
+ */
+ if (!(event->attach_state & PERF_ATTACH_GROUP))
+ return;
+
+ event->attach_state &= ~PERF_ATTACH_GROUP;
+
+ /*
+ * If this is a sibling, remove it from its group.
+ */
+ if (event->group_leader != event) {
+ list_del_init(&event->group_entry);
+ event->group_leader->nr_siblings--;
+ return;
+ }
+
+ if (!list_empty(&event->group_entry))
+ list = &event->group_entry;
/*
* If this was a group event with sibling events then
* upgrade the siblings to singleton events by adding them
- * to the context list directly:
+ * to whatever list we are on.
*/
list_for_each_entry_safe(sibling, tmp, &event->sibling_list, group_entry) {
- struct list_head *list;
-
- list = ctx_group_list(event, ctx);
- list_move_tail(&sibling->group_entry, list);
+ if (list)
+ list_move_tail(&sibling->group_entry, list);
sibling->group_leader = sibling;
/* Inherit group flags from the previous leader */
@@ -652,8 +687,11 @@
if (txn)
pmu->start_txn(pmu);
- if (event_sched_in(group_event, cpuctx, ctx))
+ if (event_sched_in(group_event, cpuctx, ctx)) {
+ if (txn)
+ pmu->cancel_txn(pmu);
return -EAGAIN;
+ }
/*
* Schedule in siblings as one group (if any):
@@ -675,9 +713,6 @@
}
group_error:
- if (txn)
- pmu->cancel_txn(pmu);
-
/*
* Groups can be scheduled in as one unit only, so undo any
* partial group before returning:
@@ -689,6 +724,9 @@
}
event_sched_out(group_event, cpuctx, ctx);
+ if (txn)
+ pmu->cancel_txn(pmu);
+
return -EAGAIN;
}
@@ -727,6 +765,7 @@
struct perf_event_context *ctx)
{
list_add_event(event, ctx);
+ perf_group_attach(event);
event->tstamp_enabled = ctx->time;
event->tstamp_running = ctx->time;
event->tstamp_stopped = ctx->time;
@@ -1468,6 +1507,9 @@
divisor = nsec * frequency;
}
+ if (!divisor)
+ return dividend;
+
return div64_u64(dividend, divisor);
}
@@ -1490,7 +1532,7 @@
static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count)
{
struct hw_perf_event *hwc = &event->hw;
- u64 period, sample_period;
+ s64 period, sample_period;
s64 delta;
period = perf_calculate_period(event, nsec, count);
@@ -1841,6 +1883,7 @@
}
static void perf_pending_sync(struct perf_event *event);
+static void perf_mmap_data_put(struct perf_mmap_data *data);
static void free_event(struct perf_event *event)
{
@@ -1856,9 +1899,9 @@
atomic_dec(&nr_task_events);
}
- if (event->output) {
- fput(event->output->filp);
- event->output = NULL;
+ if (event->data) {
+ perf_mmap_data_put(event->data);
+ event->data = NULL;
}
if (event->destroy)
@@ -1893,8 +1936,8 @@
*/
mutex_lock_nested(&ctx->mutex, SINGLE_DEPTH_NESTING);
raw_spin_lock_irq(&ctx->lock);
+ perf_group_detach(event);
list_del_event(event, ctx);
- perf_destroy_group(event, ctx);
raw_spin_unlock_irq(&ctx->lock);
mutex_unlock(&ctx->mutex);
@@ -2175,7 +2218,27 @@
return ret;
}
-static int perf_event_set_output(struct perf_event *event, int output_fd);
+static const struct file_operations perf_fops;
+
+static struct perf_event *perf_fget_light(int fd, int *fput_needed)
+{
+ struct file *file;
+
+ file = fget_light(fd, fput_needed);
+ if (!file)
+ return ERR_PTR(-EBADF);
+
+ if (file->f_op != &perf_fops) {
+ fput_light(file, *fput_needed);
+ *fput_needed = 0;
+ return ERR_PTR(-EBADF);
+ }
+
+ return file->private_data;
+}
+
+static int perf_event_set_output(struct perf_event *event,
+ struct perf_event *output_event);
static int perf_event_set_filter(struct perf_event *event, void __user *arg);
static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
@@ -2202,7 +2265,23 @@
return perf_event_period(event, (u64 __user *)arg);
case PERF_EVENT_IOC_SET_OUTPUT:
- return perf_event_set_output(event, arg);
+ {
+ struct perf_event *output_event = NULL;
+ int fput_needed = 0;
+ int ret;
+
+ if (arg != -1) {
+ output_event = perf_fget_light(arg, &fput_needed);
+ if (IS_ERR(output_event))
+ return PTR_ERR(output_event);
+ }
+
+ ret = perf_event_set_output(event, output_event);
+ if (output_event)
+ fput_light(output_event->filp, fput_needed);
+
+ return ret;
+ }
case PERF_EVENT_IOC_SET_FILTER:
return perf_event_set_filter(event, (void __user *)arg);
@@ -2335,8 +2414,6 @@
unsigned long size;
int i;
- WARN_ON(atomic_read(&event->mmap_count));
-
size = sizeof(struct perf_mmap_data);
size += nr_pages * sizeof(void *);
@@ -2452,8 +2529,6 @@
unsigned long size;
void *all_buf;
- WARN_ON(atomic_read(&event->mmap_count));
-
size = sizeof(struct perf_mmap_data);
size += sizeof(void *);
@@ -2536,7 +2611,7 @@
if (!data->watermark)
data->watermark = max_size / 2;
-
+ atomic_set(&data->refcount, 1);
rcu_assign_pointer(event->data, data);
}
@@ -2548,13 +2623,26 @@
perf_mmap_data_free(data);
}
-static void perf_mmap_data_release(struct perf_event *event)
+static struct perf_mmap_data *perf_mmap_data_get(struct perf_event *event)
{
- struct perf_mmap_data *data = event->data;
+ struct perf_mmap_data *data;
- WARN_ON(atomic_read(&event->mmap_count));
+ rcu_read_lock();
+ data = rcu_dereference(event->data);
+ if (data) {
+ if (!atomic_inc_not_zero(&data->refcount))
+ data = NULL;
+ }
+ rcu_read_unlock();
- rcu_assign_pointer(event->data, NULL);
+ return data;
+}
+
+static void perf_mmap_data_put(struct perf_mmap_data *data)
+{
+ if (!atomic_dec_and_test(&data->refcount))
+ return;
+
call_rcu(&data->rcu_head, perf_mmap_data_free_rcu);
}
@@ -2569,15 +2657,18 @@
{
struct perf_event *event = vma->vm_file->private_data;
- WARN_ON_ONCE(event->ctx->parent_ctx);
if (atomic_dec_and_mutex_lock(&event->mmap_count, &event->mmap_mutex)) {
unsigned long size = perf_data_size(event->data);
- struct user_struct *user = current_user();
+ struct user_struct *user = event->mmap_user;
+ struct perf_mmap_data *data = event->data;
atomic_long_sub((size >> PAGE_SHIFT) + 1, &user->locked_vm);
- vma->vm_mm->locked_vm -= event->data->nr_locked;
- perf_mmap_data_release(event);
+ vma->vm_mm->locked_vm -= event->mmap_locked;
+ rcu_assign_pointer(event->data, NULL);
mutex_unlock(&event->mmap_mutex);
+
+ perf_mmap_data_put(data);
+ free_uid(user);
}
}
@@ -2629,13 +2720,10 @@
WARN_ON_ONCE(event->ctx->parent_ctx);
mutex_lock(&event->mmap_mutex);
- if (event->output) {
- ret = -EINVAL;
- goto unlock;
- }
-
- if (atomic_inc_not_zero(&event->mmap_count)) {
- if (nr_pages != event->data->nr_pages)
+ if (event->data) {
+ if (event->data->nr_pages == nr_pages)
+ atomic_inc(&event->data->refcount);
+ else
ret = -EINVAL;
goto unlock;
}
@@ -2667,21 +2755,23 @@
WARN_ON(event->data);
data = perf_mmap_data_alloc(event, nr_pages);
- ret = -ENOMEM;
- if (!data)
+ if (!data) {
+ ret = -ENOMEM;
goto unlock;
+ }
- ret = 0;
perf_mmap_data_init(event, data);
-
- atomic_set(&event->mmap_count, 1);
- atomic_long_add(user_extra, &user->locked_vm);
- vma->vm_mm->locked_vm += extra;
- event->data->nr_locked = extra;
if (vma->vm_flags & VM_WRITE)
event->data->writable = 1;
+ atomic_long_add(user_extra, &user->locked_vm);
+ event->mmap_locked = extra;
+ event->mmap_user = get_current_user();
+ vma->vm_mm->locked_vm += event->mmap_locked;
+
unlock:
+ if (!ret)
+ atomic_inc(&event->mmap_count);
mutex_unlock(&event->mmap_mutex);
vma->vm_flags |= VM_RESERVED;
@@ -2977,6 +3067,7 @@
len -= size;
handle->addr += size;
+ buf += size;
handle->size -= size;
if (!handle->size) {
struct perf_mmap_data *data = handle->data;
@@ -2993,7 +3084,6 @@
struct perf_event *event, unsigned int size,
int nmi, int sample)
{
- struct perf_event *output_event;
struct perf_mmap_data *data;
unsigned long tail, offset, head;
int have_lost;
@@ -3010,10 +3100,6 @@
if (event->parent)
event = event->parent;
- output_event = rcu_dereference(event->output);
- if (output_event)
- event = output_event;
-
data = rcu_dereference(event->data);
if (!data)
goto out;
@@ -3972,13 +4058,6 @@
}
}
-static void perf_swevent_unthrottle(struct perf_event *event)
-{
- /*
- * Nothing to do, we already reset hwc->interrupts.
- */
-}
-
static void perf_swevent_add(struct perf_event *event, u64 nr,
int nmi, struct perf_sample_data *data,
struct pt_regs *regs)
@@ -4193,11 +4272,22 @@
hlist_del_rcu(&event->hlist_entry);
}
+static void perf_swevent_void(struct perf_event *event)
+{
+}
+
+static int perf_swevent_int(struct perf_event *event)
+{
+ return 0;
+}
+
static const struct pmu perf_ops_generic = {
.enable = perf_swevent_enable,
.disable = perf_swevent_disable,
+ .start = perf_swevent_int,
+ .stop = perf_swevent_void,
.read = perf_swevent_read,
- .unthrottle = perf_swevent_unthrottle,
+ .unthrottle = perf_swevent_void, /* hwc->interrupts already reset */
};
/*
@@ -4478,8 +4568,10 @@
static const struct pmu perf_ops_tracepoint = {
.enable = perf_trace_enable,
.disable = perf_trace_disable,
+ .start = perf_swevent_int,
+ .stop = perf_swevent_void,
.read = perf_swevent_read,
- .unthrottle = perf_swevent_unthrottle,
+ .unthrottle = perf_swevent_void,
};
static int perf_tp_filter_match(struct perf_event *event,
@@ -4912,39 +5004,17 @@
goto out;
}
-static int perf_event_set_output(struct perf_event *event, int output_fd)
+static int
+perf_event_set_output(struct perf_event *event, struct perf_event *output_event)
{
- struct perf_event *output_event = NULL;
- struct file *output_file = NULL;
- struct perf_event *old_output;
- int fput_needed = 0;
+ struct perf_mmap_data *data = NULL, *old_data = NULL;
int ret = -EINVAL;
- /*
- * Don't allow output of inherited per-task events. This would
- * create performance issues due to cross cpu access.
- */
- if (event->cpu == -1 && event->attr.inherit)
- return -EINVAL;
-
- if (!output_fd)
+ if (!output_event)
goto set;
- output_file = fget_light(output_fd, &fput_needed);
- if (!output_file)
- return -EBADF;
-
- if (output_file->f_op != &perf_fops)
- goto out;
-
- output_event = output_file->private_data;
-
- /* Don't chain output fds */
- if (output_event->output)
- goto out;
-
- /* Don't set an output fd when we already have an output channel */
- if (event->data)
+ /* don't allow circular references */
+ if (event == output_event)
goto out;
/*
@@ -4959,26 +5029,28 @@
if (output_event->cpu == -1 && output_event->ctx != event->ctx)
goto out;
- atomic_long_inc(&output_file->f_count);
-
set:
mutex_lock(&event->mmap_mutex);
- old_output = event->output;
- rcu_assign_pointer(event->output, output_event);
- mutex_unlock(&event->mmap_mutex);
+ /* Can't redirect output if we've got an active mmap() */
+ if (atomic_read(&event->mmap_count))
+ goto unlock;
- if (old_output) {
- /*
- * we need to make sure no existing perf_output_*()
- * is still referencing this event.
- */
- synchronize_rcu();
- fput(old_output->filp);
+ if (output_event) {
+ /* get the buffer we want to redirect to */
+ data = perf_mmap_data_get(output_event);
+ if (!data)
+ goto unlock;
}
+ old_data = event->data;
+ rcu_assign_pointer(event->data, data);
ret = 0;
+unlock:
+ mutex_unlock(&event->mmap_mutex);
+
+ if (old_data)
+ perf_mmap_data_put(old_data);
out:
- fput_light(output_file, fput_needed);
return ret;
}
@@ -4994,7 +5066,7 @@
struct perf_event_attr __user *, attr_uptr,
pid_t, pid, int, cpu, int, group_fd, unsigned long, flags)
{
- struct perf_event *event, *group_leader;
+ struct perf_event *event, *group_leader = NULL, *output_event = NULL;
struct perf_event_attr attr;
struct perf_event_context *ctx;
struct file *event_file = NULL;
@@ -5034,19 +5106,25 @@
goto err_fd;
}
+ if (group_fd != -1) {
+ group_leader = perf_fget_light(group_fd, &fput_needed);
+ if (IS_ERR(group_leader)) {
+ err = PTR_ERR(group_leader);
+ goto err_put_context;
+ }
+ group_file = group_leader->filp;
+ if (flags & PERF_FLAG_FD_OUTPUT)
+ output_event = group_leader;
+ if (flags & PERF_FLAG_FD_NO_GROUP)
+ group_leader = NULL;
+ }
+
/*
* Look up the group leader (we will attach this event to it):
*/
- group_leader = NULL;
- if (group_fd != -1 && !(flags & PERF_FLAG_FD_NO_GROUP)) {
+ if (group_leader) {
err = -EINVAL;
- group_file = fget_light(group_fd, &fput_needed);
- if (!group_file)
- goto err_put_context;
- if (group_file->f_op != &perf_fops)
- goto err_put_context;
- group_leader = group_file->private_data;
/*
* Do not allow a recursive hierarchy (this new sibling
* becoming part of another group-sibling):
@@ -5068,9 +5146,16 @@
event = perf_event_alloc(&attr, cpu, ctx, group_leader,
NULL, NULL, GFP_KERNEL);
- err = PTR_ERR(event);
- if (IS_ERR(event))
+ if (IS_ERR(event)) {
+ err = PTR_ERR(event);
goto err_put_context;
+ }
+
+ if (output_event) {
+ err = perf_event_set_output(event, output_event);
+ if (err)
+ goto err_free_put_context;
+ }
event_file = anon_inode_getfile("[perf_event]", &perf_fops, event, O_RDWR);
if (IS_ERR(event_file)) {
@@ -5078,12 +5163,6 @@
goto err_free_put_context;
}
- if (flags & PERF_FLAG_FD_OUTPUT) {
- err = perf_event_set_output(event, group_fd);
- if (err)
- goto err_fput_free_put_context;
- }
-
event->filp = event_file;
WARN_ON_ONCE(ctx->parent_ctx);
mutex_lock(&ctx->mutex);
@@ -5097,12 +5176,16 @@
list_add_tail(&event->owner_entry, ¤t->perf_event_list);
mutex_unlock(¤t->perf_event_mutex);
+ /*
+ * Drop the reference on the group_event after placing the
+ * new event on the sibling_list. This ensures destruction
+ * of the group leader will find the pointer to itself in
+ * perf_group_detach().
+ */
fput_light(group_file, fput_needed);
fd_install(event_fd, event_file);
return event_fd;
-err_fput_free_put_context:
- fput(event_file);
err_free_put_context:
free_event(event);
err_put_context:
@@ -5420,6 +5503,7 @@
fput(parent->filp);
+ perf_group_detach(event);
list_del_event(event, ctx);
free_event(event);
}
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 5c36ea9..ca6066a 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -99,9 +99,13 @@
depends on PM_ADVANCED_DEBUG
default n
+config SUSPEND_NVS
+ bool
+
config SUSPEND
bool "Suspend to RAM and standby"
depends on PM && ARCH_SUSPEND_POSSIBLE
+ select SUSPEND_NVS if HAS_IOMEM
default y
---help---
Allow the system to enter sleep states in which main memory is
@@ -130,13 +134,10 @@
Turning OFF this setting is NOT recommended! If in doubt, say Y.
-config HIBERNATION_NVS
- bool
-
config HIBERNATION
bool "Hibernation (aka 'suspend to disk')"
depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE
- select HIBERNATION_NVS if HAS_IOMEM
+ select SUSPEND_NVS if HAS_IOMEM
---help---
Enable the suspend to disk (STD) functionality, which is usually
called "hibernation" in user interfaces. STD checkpoints the
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index 524e058..f9063c6 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -10,6 +10,6 @@
obj-$(CONFIG_PM_TEST_SUSPEND) += suspend_test.o
obj-$(CONFIG_HIBERNATION) += hibernate.o snapshot.o swap.o user.o \
block_io.o
-obj-$(CONFIG_HIBERNATION_NVS) += hibernate_nvs.o
+obj-$(CONFIG_SUSPEND_NVS) += nvs.o
obj-$(CONFIG_MAGIC_SYSRQ) += poweroff.o
diff --git a/kernel/power/hibernate_nvs.c b/kernel/power/nvs.c
similarity index 80%
rename from kernel/power/hibernate_nvs.c
rename to kernel/power/nvs.c
index fdcad9e..1836db6 100644
--- a/kernel/power/hibernate_nvs.c
+++ b/kernel/power/nvs.c
@@ -15,7 +15,7 @@
/*
* Platforms, like ACPI, may want us to save some memory used by them during
- * hibernation and to restore the contents of this memory during the subsequent
+ * suspend and to restore the contents of this memory during the subsequent
* resume. The code below implements a mechanism allowing us to do that.
*/
@@ -30,7 +30,7 @@
static LIST_HEAD(nvs_list);
/**
- * hibernate_nvs_register - register platform NVS memory region to save
+ * suspend_nvs_register - register platform NVS memory region to save
* @start - physical address of the region
* @size - size of the region
*
@@ -38,7 +38,7 @@
* things so that the data from page-aligned addresses in this region will
* be copied into separate RAM pages.
*/
-int hibernate_nvs_register(unsigned long start, unsigned long size)
+int suspend_nvs_register(unsigned long start, unsigned long size)
{
struct nvs_page *entry, *next;
@@ -68,9 +68,9 @@
}
/**
- * hibernate_nvs_free - free data pages allocated for saving NVS regions
+ * suspend_nvs_free - free data pages allocated for saving NVS regions
*/
-void hibernate_nvs_free(void)
+void suspend_nvs_free(void)
{
struct nvs_page *entry;
@@ -86,16 +86,16 @@
}
/**
- * hibernate_nvs_alloc - allocate memory necessary for saving NVS regions
+ * suspend_nvs_alloc - allocate memory necessary for saving NVS regions
*/
-int hibernate_nvs_alloc(void)
+int suspend_nvs_alloc(void)
{
struct nvs_page *entry;
list_for_each_entry(entry, &nvs_list, node) {
entry->data = (void *)__get_free_page(GFP_KERNEL);
if (!entry->data) {
- hibernate_nvs_free();
+ suspend_nvs_free();
return -ENOMEM;
}
}
@@ -103,9 +103,9 @@
}
/**
- * hibernate_nvs_save - save NVS memory regions
+ * suspend_nvs_save - save NVS memory regions
*/
-void hibernate_nvs_save(void)
+void suspend_nvs_save(void)
{
struct nvs_page *entry;
@@ -119,12 +119,12 @@
}
/**
- * hibernate_nvs_restore - restore NVS memory regions
+ * suspend_nvs_restore - restore NVS memory regions
*
* This function is going to be called with interrupts disabled, so it
* cannot iounmap the virtual addresses used to access the NVS region.
*/
-void hibernate_nvs_restore(void)
+void suspend_nvs_restore(void)
{
struct nvs_page *entry;
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index 56e7dbb..f37cb7d 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -16,6 +16,12 @@
#include <linux/cpu.h>
#include <linux/syscalls.h>
#include <linux/gfp.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/suspend.h>
#include "power.h"
diff --git a/kernel/sched.c b/kernel/sched.c
index d484081..cb816e3 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -306,52 +306,6 @@
*/
struct task_group init_task_group;
-/* return group to which a task belongs */
-static inline struct task_group *task_group(struct task_struct *p)
-{
- struct task_group *tg;
-
-#ifdef CONFIG_CGROUP_SCHED
- tg = container_of(task_subsys_state(p, cpu_cgroup_subsys_id),
- struct task_group, css);
-#else
- tg = &init_task_group;
-#endif
- return tg;
-}
-
-/* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */
-static inline void set_task_rq(struct task_struct *p, unsigned int cpu)
-{
- /*
- * Strictly speaking this rcu_read_lock() is not needed since the
- * task_group is tied to the cgroup, which in turn can never go away
- * as long as there are tasks attached to it.
- *
- * However since task_group() uses task_subsys_state() which is an
- * rcu_dereference() user, this quiets CONFIG_PROVE_RCU.
- */
- rcu_read_lock();
-#ifdef CONFIG_FAIR_GROUP_SCHED
- p->se.cfs_rq = task_group(p)->cfs_rq[cpu];
- p->se.parent = task_group(p)->se[cpu];
-#endif
-
-#ifdef CONFIG_RT_GROUP_SCHED
- p->rt.rt_rq = task_group(p)->rt_rq[cpu];
- p->rt.parent = task_group(p)->rt_se[cpu];
-#endif
- rcu_read_unlock();
-}
-
-#else
-
-static inline void set_task_rq(struct task_struct *p, unsigned int cpu) { }
-static inline struct task_group *task_group(struct task_struct *p)
-{
- return NULL;
-}
-
#endif /* CONFIG_CGROUP_SCHED */
/* CFS-related fields in a runqueue */
@@ -544,6 +498,8 @@
struct root_domain *rd;
struct sched_domain *sd;
+ unsigned long cpu_power;
+
unsigned char idle_at_tick;
/* For active balancing */
int post_schedule;
@@ -642,6 +598,49 @@
#define cpu_curr(cpu) (cpu_rq(cpu)->curr)
#define raw_rq() (&__raw_get_cpu_var(runqueues))
+#ifdef CONFIG_CGROUP_SCHED
+
+/*
+ * Return the group to which this tasks belongs.
+ *
+ * We use task_subsys_state_check() and extend the RCU verification
+ * with lockdep_is_held(&task_rq(p)->lock) because cpu_cgroup_attach()
+ * holds that lock for each task it moves into the cgroup. Therefore
+ * by holding that lock, we pin the task to the current cgroup.
+ */
+static inline struct task_group *task_group(struct task_struct *p)
+{
+ struct cgroup_subsys_state *css;
+
+ css = task_subsys_state_check(p, cpu_cgroup_subsys_id,
+ lockdep_is_held(&task_rq(p)->lock));
+ return container_of(css, struct task_group, css);
+}
+
+/* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */
+static inline void set_task_rq(struct task_struct *p, unsigned int cpu)
+{
+#ifdef CONFIG_FAIR_GROUP_SCHED
+ p->se.cfs_rq = task_group(p)->cfs_rq[cpu];
+ p->se.parent = task_group(p)->se[cpu];
+#endif
+
+#ifdef CONFIG_RT_GROUP_SCHED
+ p->rt.rt_rq = task_group(p)->rt_rq[cpu];
+ p->rt.parent = task_group(p)->rt_se[cpu];
+#endif
+}
+
+#else /* CONFIG_CGROUP_SCHED */
+
+static inline void set_task_rq(struct task_struct *p, unsigned int cpu) { }
+static inline struct task_group *task_group(struct task_struct *p)
+{
+ return NULL;
+}
+
+#endif /* CONFIG_CGROUP_SCHED */
+
inline void update_rq_clock(struct rq *rq)
{
if (!rq->skip_clock_update)
@@ -1255,6 +1254,12 @@
s64 period = sched_avg_period();
while ((s64)(rq->clock - rq->age_stamp) > period) {
+ /*
+ * Inline assembly required to prevent the compiler
+ * optimising this loop into a divmod call.
+ * See __iter_div_u64_rem() for another example of this.
+ */
+ asm("" : "+rm" (rq->age_stamp));
rq->age_stamp += period;
rq->rt_avg /= 2;
}
@@ -1499,24 +1504,9 @@
return max(rq->cpu_load[type-1], total);
}
-static struct sched_group *group_of(int cpu)
-{
- struct sched_domain *sd = rcu_dereference_sched(cpu_rq(cpu)->sd);
-
- if (!sd)
- return NULL;
-
- return sd->groups;
-}
-
static unsigned long power_of(int cpu)
{
- struct sched_group *group = group_of(cpu);
-
- if (!group)
- return SCHED_LOAD_SCALE;
-
- return group->cpu_power;
+ return cpu_rq(cpu)->cpu_power;
}
static int task_hot(struct task_struct *p, u64 now, struct sched_domain *sd);
@@ -1673,9 +1663,6 @@
static void update_h_load(long cpu)
{
- if (root_task_group_empty())
- return;
-
walk_tg_tree(tg_load_down, tg_nop, (void *)cpu);
}
@@ -1854,8 +1841,8 @@
static void set_load_weight(struct task_struct *p)
{
if (task_has_rt_policy(p)) {
- p->se.load.weight = prio_to_weight[0] * 2;
- p->se.load.inv_weight = prio_to_wmult[0] >> 1;
+ p->se.load.weight = 0;
+ p->se.load.inv_weight = WMULT_CONST;
return;
}
@@ -2507,7 +2494,16 @@
if (p->sched_class->task_fork)
p->sched_class->task_fork(p);
+ /*
+ * The child is not yet in the pid-hash so no cgroup attach races,
+ * and the cgroup is pinned to this child due to cgroup_fork()
+ * is ran before sched_fork().
+ *
+ * Silence PROVE_RCU.
+ */
+ rcu_read_lock();
set_task_cpu(p, cpu);
+ rcu_read_unlock();
#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
if (likely(sched_info_on()))
@@ -4478,16 +4474,6 @@
}
if (user) {
-#ifdef CONFIG_RT_GROUP_SCHED
- /*
- * Do not allow realtime tasks into groups that have no runtime
- * assigned.
- */
- if (rt_bandwidth_enabled() && rt_policy(policy) &&
- task_group(p)->rt_bandwidth.rt_runtime == 0)
- return -EPERM;
-#endif
-
retval = security_task_setscheduler(p, policy, param);
if (retval)
return retval;
@@ -4503,6 +4489,22 @@
* runqueue lock must be held.
*/
rq = __task_rq_lock(p);
+
+#ifdef CONFIG_RT_GROUP_SCHED
+ if (user) {
+ /*
+ * Do not allow realtime tasks into groups that have no runtime
+ * assigned.
+ */
+ if (rt_bandwidth_enabled() && rt_policy(policy) &&
+ task_group(p)->rt_bandwidth.rt_runtime == 0) {
+ __task_rq_unlock(rq);
+ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
+ return -EPERM;
+ }
+ }
+#endif
+
/* recheck policy now with rq lock held */
if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) {
policy = oldpolicy = -1;
@@ -7605,6 +7607,7 @@
#ifdef CONFIG_SMP
rq->sd = NULL;
rq->rd = NULL;
+ rq->cpu_power = SCHED_LOAD_SCALE;
rq->post_schedule = 0;
rq->active_balance = 0;
rq->next_balance = jiffies;
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
index 217e4a9..a878b53 100644
--- a/kernel/sched_fair.c
+++ b/kernel/sched_fair.c
@@ -1225,7 +1225,6 @@
unsigned long this_load, load;
int idx, this_cpu, prev_cpu;
unsigned long tl_per_task;
- unsigned int imbalance;
struct task_group *tg;
unsigned long weight;
int balanced;
@@ -1241,6 +1240,7 @@
* effect of the currently running task from the load
* of the current CPU:
*/
+ rcu_read_lock();
if (sync) {
tg = task_group(current);
weight = current->se.load.weight;
@@ -1252,8 +1252,6 @@
tg = task_group(p);
weight = p->se.load.weight;
- imbalance = 100 + (sd->imbalance_pct - 100) / 2;
-
/*
* In low-load situations, where prev_cpu is idle and this_cpu is idle
* due to the sync cause above having dropped this_load to 0, we'll
@@ -1263,9 +1261,22 @@
* Otherwise check if either cpus are near enough in load to allow this
* task to be woken on this_cpu.
*/
- balanced = !this_load ||
- 100*(this_load + effective_load(tg, this_cpu, weight, weight)) <=
- imbalance*(load + effective_load(tg, prev_cpu, 0, weight));
+ if (this_load) {
+ unsigned long this_eff_load, prev_eff_load;
+
+ this_eff_load = 100;
+ this_eff_load *= power_of(prev_cpu);
+ this_eff_load *= this_load +
+ effective_load(tg, this_cpu, weight, weight);
+
+ prev_eff_load = 100 + (sd->imbalance_pct - 100) / 2;
+ prev_eff_load *= power_of(this_cpu);
+ prev_eff_load *= load + effective_load(tg, prev_cpu, 0, weight);
+
+ balanced = this_eff_load <= prev_eff_load;
+ } else
+ balanced = true;
+ rcu_read_unlock();
/*
* If the currently running task will sleep within
@@ -2298,6 +2309,7 @@
if (!power)
power = 1;
+ cpu_rq(cpu)->cpu_power = power;
sdg->cpu_power = power;
}
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 825e112..07b4f1b 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -850,7 +850,7 @@
void *cpu = (void *)(long)smp_processor_id();
int err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
- BUG_ON(err == NOTIFY_BAD);
+ BUG_ON(err != NOTIFY_OK);
cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
register_cpu_notifier(&cpu_nfb);
return 0;
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index b4e7431..70f8d90 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -321,7 +321,7 @@
#ifdef CONFIG_HOTPLUG_CPU
case CPU_UP_CANCELED:
- case CPU_DEAD:
+ case CPU_POST_DEAD:
{
struct cpu_stop_work *work;
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 997080f..d24f761 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1471,12 +1471,12 @@
},
#endif
{
- .procname = "pipe-max-pages",
- .data = &pipe_max_pages,
+ .procname = "pipe-max-size",
+ .data = &pipe_max_size,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &proc_dointvec_minmax,
- .extra1 = &two,
+ .proc_handler = &pipe_proc_fn,
+ .extra1 = &pipe_min_size,
},
/*
* NOTE: do not add new entries to this table unless you have read
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 1d7b9bc..783fbad 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -315,9 +315,6 @@
goto end;
}
- if (nohz_ratelimit(cpu))
- goto end;
-
ts->idle_calls++;
/* Read jiffies and the time when jiffies were updated last */
do {
@@ -328,7 +325,7 @@
} while (read_seqretry(&xtime_lock, seq));
if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu) ||
- arch_needs_cpu(cpu)) {
+ arch_needs_cpu(cpu) || nohz_ratelimit(cpu)) {
next_jiffies = last_jiffies + 1;
delta_jiffies = 1;
} else {
diff --git a/kernel/timer.c b/kernel/timer.c
index 2454172..ee305c8 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -1717,7 +1717,7 @@
init_timer_stats();
- BUG_ON(err == NOTIFY_BAD);
+ BUG_ON(err != NOTIFY_OK);
register_cpu_notifier(&timers_nb);
open_softirq(TIMER_SOFTIRQ, run_timer_softirq);
}
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c
index 36ea2b6..638711c 100644
--- a/kernel/trace/blktrace.c
+++ b/kernel/trace/blktrace.c
@@ -842,6 +842,7 @@
/**
* blk_add_trace_remap - Add a trace for a remap operation
+ * @ignore: trace callback data parameter (not used)
* @q: queue the io is for
* @bio: the source bio
* @dev: target device
@@ -873,6 +874,7 @@
/**
* blk_add_trace_rq_remap - Add a trace for a request-remap operation
+ * @ignore: trace callback data parameter (not used)
* @q: queue the io is for
* @rq: the source request
* @dev: target device
diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c
index cb6f365..8a2b73f 100644
--- a/kernel/trace/trace_event_perf.c
+++ b/kernel/trace/trace_event_perf.c
@@ -96,7 +96,9 @@
mutex_lock(&event_mutex);
list_for_each_entry(tp_event, &ftrace_events, list) {
if (tp_event->event.type == event_id &&
- tp_event->class && tp_event->class->perf_probe &&
+ tp_event->class &&
+ (tp_event->class->perf_probe ||
+ tp_event->class->reg) &&
try_module_get(tp_event->mod)) {
ret = perf_trace_event_init(tp_event, p_event);
break;
@@ -116,7 +118,7 @@
if (WARN_ON_ONCE(!list))
return -EINVAL;
- list = per_cpu_ptr(list, smp_processor_id());
+ list = this_cpu_ptr(list);
hlist_add_head_rcu(&p_event->hlist_entry, list);
return 0;
@@ -132,8 +134,9 @@
struct ftrace_event_call *tp_event = p_event->tp_event;
int i;
+ mutex_lock(&event_mutex);
if (--tp_event->perf_refcount > 0)
- return;
+ goto out;
if (tp_event->class->reg)
tp_event->class->reg(tp_event, TRACE_REG_PERF_UNREGISTER);
@@ -142,6 +145,12 @@
tp_event->class->perf_probe,
tp_event);
+ /*
+ * Ensure our callback won't be called anymore. See
+ * tracepoint_probe_unregister() and __DO_TRACE().
+ */
+ synchronize_sched();
+
free_percpu(tp_event->perf_events);
tp_event->perf_events = NULL;
@@ -151,6 +160,8 @@
perf_trace_buf[i] = NULL;
}
}
+out:
+ mutex_unlock(&event_mutex);
}
__kprobes void *perf_trace_buf_prepare(int size, unsigned short type,
@@ -169,7 +180,7 @@
if (*rctxp < 0)
return NULL;
- raw_data = per_cpu_ptr(perf_trace_buf[*rctxp], smp_processor_id());
+ raw_data = this_cpu_ptr(perf_trace_buf[*rctxp]);
/* zero the dead bytes from align to not leak stack to user */
memset(&raw_data[size - sizeof(u64)], 0, sizeof(u64));
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index faf7cef..f52b5f5 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -1359,7 +1359,7 @@
for (i = 0; i < tp->nr_args; i++)
call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset);
- head = per_cpu_ptr(call->perf_events, smp_processor_id());
+ head = this_cpu_ptr(call->perf_events);
perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, regs, head);
}
@@ -1392,7 +1392,7 @@
for (i = 0; i < tp->nr_args; i++)
call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset);
- head = per_cpu_ptr(call->perf_events, smp_processor_id());
+ head = this_cpu_ptr(call->perf_events);
perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, regs, head);
}
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index d2c859c..34e3580 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -519,7 +519,7 @@
syscall_get_arguments(current, regs, 0, sys_data->nb_args,
(unsigned long *)&rec->args);
- head = per_cpu_ptr(sys_data->enter_event->perf_events, smp_processor_id());
+ head = this_cpu_ptr(sys_data->enter_event->perf_events);
perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head);
}
@@ -595,7 +595,7 @@
rec->nr = syscall_nr;
rec->ret = syscall_get_return_value(current, regs);
- head = per_cpu_ptr(sys_data->exit_event->perf_events, smp_processor_id());
+ head = this_cpu_ptr(sys_data->exit_event->perf_events);
perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head);
}
diff --git a/lib/atomic64_test.c b/lib/atomic64_test.c
index 9087d71..250ed11 100644
--- a/lib/atomic64_test.c
+++ b/lib/atomic64_test.c
@@ -113,7 +113,8 @@
r += one;
BUG_ON(v.counter != r);
-#if defined(CONFIG_X86) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(_ASM_GENERIC_ATOMIC64_H)
+#if defined(CONFIG_X86) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || \
+ defined(CONFIG_S390) || defined(_ASM_GENERIC_ATOMIC64_H)
INIT(onestwos);
BUG_ON(atomic64_dec_if_positive(&v) != (onestwos - 1));
r -= one;
diff --git a/lib/genalloc.c b/lib/genalloc.c
index 736c3b0..1923f14 100644
--- a/lib/genalloc.c
+++ b/lib/genalloc.c
@@ -128,7 +128,6 @@
chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk);
end_bit = (chunk->end_addr - chunk->start_addr) >> order;
- end_bit -= nbits + 1;
spin_lock_irqsave(&chunk->lock, flags);
start_bit = bitmap_find_next_zero_area(chunk->bits, end_bit, 0,
diff --git a/lib/idr.c b/lib/idr.c
index c1a2069..7f1a4f0 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -602,7 +602,7 @@
/* find first ent */
n = idp->layers * IDR_BITS;
max = 1 << n;
- p = rcu_dereference(idp->top);
+ p = rcu_dereference_raw(idp->top);
if (!p)
return NULL;
@@ -610,7 +610,7 @@
while (n > 0 && p) {
n -= IDR_BITS;
*paa++ = p;
- p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]);
+ p = rcu_dereference_raw(p->ary[(id >> n) & IDR_MASK]);
}
if (p) {
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 59c1551..b935795 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -83,6 +83,7 @@
return ret;
}
+#ifdef CONFIG_NET
static int kobj_bcast_filter(struct sock *dsk, struct sk_buff *skb, void *data)
{
struct kobject *kobj = data;
@@ -98,6 +99,7 @@
return 0;
}
+#endif
static int kobj_usermode_filter(struct kobject *kobj)
{
@@ -378,6 +380,7 @@
if (!ue_sk->sk) {
printk(KERN_ERR
"kobject_uevent: unable to create netlink socket!\n");
+ kfree(ue_sk);
return -ENODEV;
}
mutex_lock(&uevent_sock_mutex);
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index c6ece0a..20a8193 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -1370,7 +1370,7 @@
static void memcg_oom_recover(struct mem_cgroup *mem)
{
- if (mem->oom_kill_disable && atomic_read(&mem->oom_lock))
+ if (atomic_read(&mem->oom_lock))
memcg_wakeup_oom(mem);
}
@@ -3781,6 +3781,8 @@
return -EINVAL;
}
mem->oom_kill_disable = val;
+ if (!val)
+ memcg_oom_recover(mem);
cgroup_unlock();
return 0;
}
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 5d6fb33..5bc0a96 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -2094,7 +2094,7 @@
NODEMASK_SCRATCH(scratch);
if (!scratch)
- return;
+ goto put_mpol;
/* contextualize the tmpfs mount point mempolicy */
new = mpol_new(mpol->mode, mpol->flags, &mpol->w.user_nodemask);
if (IS_ERR(new))
@@ -2103,19 +2103,20 @@
task_lock(current);
ret = mpol_set_nodemask(new, &mpol->w.user_nodemask, scratch);
task_unlock(current);
- mpol_put(mpol); /* drop our ref on sb mpol */
if (ret)
- goto put_free;
+ goto put_new;
/* Create pseudo-vma that contains just the policy */
memset(&pvma, 0, sizeof(struct vm_area_struct));
pvma.vm_end = TASK_SIZE; /* policy covers entire file */
mpol_set_shared_policy(sp, &pvma, new); /* adds ref */
-put_free:
+put_new:
mpol_put(new); /* drop initial ref */
free_scratch:
NODEMASK_SCRATCH_FREE(scratch);
+put_mpol:
+ mpol_put(mpol); /* drop our incoming ref on sb mpol */
}
}
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index b289310..54f28bd 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -597,7 +597,7 @@
(!laptop_mode && ((global_page_state(NR_FILE_DIRTY)
+ global_page_state(NR_UNSTABLE_NFS))
> background_thresh)))
- bdi_start_writeback(bdi, NULL, 0, 0);
+ bdi_start_background_writeback(bdi);
}
void set_page_dirty_balance(struct page *page, int page_mkwrite)
@@ -705,9 +705,8 @@
* We want to write everything out, not just down to the dirty
* threshold
*/
-
if (bdi_has_dirty_io(&q->backing_dev_info))
- bdi_start_writeback(&q->backing_dev_info, NULL, nr_pages, 0);
+ bdi_start_writeback(&q->backing_dev_info, nr_pages);
}
/*
@@ -835,7 +834,6 @@
pgoff_t done_index;
int cycled;
int range_whole = 0;
- long nr_to_write = wbc->nr_to_write;
pagevec_init(&pvec, 0);
if (wbc->range_cyclic) {
@@ -852,7 +850,22 @@
if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
range_whole = 1;
cycled = 1; /* ignore range_cyclic tests */
+
+ /*
+ * If this is a data integrity sync, cap the writeback to the
+ * current end of file. Any extension to the file that occurs
+ * after this is a new write and we don't need to write those
+ * pages out to fulfil our data integrity requirements. If we
+ * try to write them out, we can get stuck in this scan until
+ * the concurrent writer stops adding dirty pages and extending
+ * EOF.
+ */
+ if (wbc->sync_mode == WB_SYNC_ALL &&
+ wbc->range_end == LLONG_MAX) {
+ end = i_size_read(mapping->host) >> PAGE_CACHE_SHIFT;
+ }
}
+
retry:
done_index = index;
while (!done && (index <= end)) {
@@ -935,11 +948,10 @@
done = 1;
break;
}
- }
+ }
- if (nr_to_write > 0) {
- nr_to_write--;
- if (nr_to_write == 0 &&
+ if (wbc->nr_to_write > 0) {
+ if (--wbc->nr_to_write == 0 &&
wbc->sync_mode == WB_SYNC_NONE) {
/*
* We stop writing back only if we are
@@ -970,11 +982,8 @@
end = writeback_index - 1;
goto retry;
}
- if (!wbc->no_nrwrite_index_update) {
- if (wbc->range_cyclic || (range_whole && nr_to_write > 0))
- mapping->writeback_index = done_index;
- wbc->nr_to_write = nr_to_write;
- }
+ if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
+ mapping->writeback_index = done_index;
return ret;
}
diff --git a/mm/percpu.c b/mm/percpu.c
index 39f7dfd..6470e77 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -229,8 +229,8 @@
return pcpu_unit_map[cpu] * pcpu_unit_pages + page_idx;
}
-static unsigned long __maybe_unused pcpu_chunk_addr(struct pcpu_chunk *chunk,
- unsigned int cpu, int page_idx)
+static unsigned long pcpu_chunk_addr(struct pcpu_chunk *chunk,
+ unsigned int cpu, int page_idx)
{
return (unsigned long)chunk->base_addr + pcpu_unit_offsets[cpu] +
(page_idx << PAGE_SHIFT);
@@ -978,7 +978,32 @@
*/
phys_addr_t per_cpu_ptr_to_phys(void *addr)
{
- if (pcpu_addr_in_first_chunk(addr)) {
+ void __percpu *base = __addr_to_pcpu_ptr(pcpu_base_addr);
+ bool in_first_chunk = false;
+ unsigned long first_start, first_end;
+ unsigned int cpu;
+
+ /*
+ * The following test on first_start/end isn't strictly
+ * necessary but will speed up lookups of addresses which
+ * aren't in the first chunk.
+ */
+ first_start = pcpu_chunk_addr(pcpu_first_chunk, pcpu_first_unit_cpu, 0);
+ first_end = pcpu_chunk_addr(pcpu_first_chunk, pcpu_last_unit_cpu,
+ pcpu_unit_pages);
+ if ((unsigned long)addr >= first_start &&
+ (unsigned long)addr < first_end) {
+ for_each_possible_cpu(cpu) {
+ void *start = per_cpu_ptr(base, cpu);
+
+ if (addr >= start && addr < start + pcpu_unit_size) {
+ in_first_chunk = true;
+ break;
+ }
+ }
+ }
+
+ if (in_first_chunk) {
if ((unsigned long)addr < VMALLOC_START ||
(unsigned long)addr >= VMALLOC_END)
return __pa(addr);
@@ -1086,7 +1111,7 @@
static int group_map[NR_CPUS] __initdata;
static int group_cnt[NR_CPUS] __initdata;
const size_t static_size = __per_cpu_end - __per_cpu_start;
- int group_cnt_max = 0, nr_groups = 1, nr_units = 0;
+ int nr_groups = 1, nr_units = 0;
size_t size_sum, min_unit_size, alloc_size;
int upa, max_upa, uninitialized_var(best_upa); /* units_per_alloc */
int last_allocs, group, unit;
@@ -1096,7 +1121,7 @@
/* this function may be called multiple times */
memset(group_map, 0, sizeof(group_map));
- memset(group_cnt, 0, sizeof(group_map));
+ memset(group_cnt, 0, sizeof(group_cnt));
/*
* Determine min_unit_size, alloc_size and max_upa such that
@@ -1130,7 +1155,6 @@
}
group_map[cpu] = group;
group_cnt[group]++;
- group_cnt_max = max(group_cnt_max, group_cnt[group]);
}
/*
diff --git a/mm/shmem.c b/mm/shmem.c
index 7e5030a..f65f840 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -764,10 +764,11 @@
static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
{
struct inode *inode = dentry->d_inode;
+ loff_t newsize = attr->ia_size;
int error;
- if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
- loff_t newsize = attr->ia_size;
+ if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)
+ && newsize != inode->i_size) {
struct page *page = NULL;
if (newsize < inode->i_size) {
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 915dceb..9c7e57c 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1724,13 +1724,13 @@
* If a zone is deemed to be full of pinned pages then just give it a light
* scan then give up on it.
*/
-static int shrink_zones(int priority, struct zonelist *zonelist,
+static bool shrink_zones(int priority, struct zonelist *zonelist,
struct scan_control *sc)
{
enum zone_type high_zoneidx = gfp_zone(sc->gfp_mask);
struct zoneref *z;
struct zone *zone;
- int progress = 0;
+ bool all_unreclaimable = true;
for_each_zone_zonelist_nodemask(zone, z, zonelist, high_zoneidx,
sc->nodemask) {
@@ -1757,9 +1757,9 @@
}
shrink_zone(priority, zone, sc);
- progress = 1;
+ all_unreclaimable = false;
}
- return progress;
+ return all_unreclaimable;
}
/*
@@ -1782,7 +1782,7 @@
struct scan_control *sc)
{
int priority;
- unsigned long ret = 0;
+ bool all_unreclaimable;
unsigned long total_scanned = 0;
struct reclaim_state *reclaim_state = current->reclaim_state;
unsigned long lru_pages = 0;
@@ -1813,7 +1813,7 @@
sc->nr_scanned = 0;
if (!priority)
disable_swap_token();
- ret = shrink_zones(priority, zonelist, sc);
+ all_unreclaimable = shrink_zones(priority, zonelist, sc);
/*
* Don't shrink slabs when reclaiming memory from
* over limit cgroups
@@ -1826,10 +1826,8 @@
}
}
total_scanned += sc->nr_scanned;
- if (sc->nr_reclaimed >= sc->nr_to_reclaim) {
- ret = sc->nr_reclaimed;
+ if (sc->nr_reclaimed >= sc->nr_to_reclaim)
goto out;
- }
/*
* Try to write back as many pages as we just scanned. This
@@ -1849,9 +1847,7 @@
priority < DEF_PRIORITY - 2)
congestion_wait(BLK_RW_ASYNC, HZ/10);
}
- /* top priority shrink_zones still had more to do? don't OOM, then */
- if (ret && scanning_global_lru(sc))
- ret = sc->nr_reclaimed;
+
out:
/*
* Now that we've scanned all the zones at this priority level, note
@@ -1877,7 +1873,14 @@
delayacct_freepages_end();
put_mems_allowed();
- return ret;
+ if (sc->nr_reclaimed)
+ return sc->nr_reclaimed;
+
+ /* top priority shrink_zones still had more to do? don't OOM, then */
+ if (scanning_global_lru(sc) && !all_unreclaimable)
+ return 1;
+
+ return 0;
}
unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index bd537fc..50f58f5f 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -12,7 +12,7 @@
return NET_RX_DROP;
if (skb_bond_should_drop(skb, ACCESS_ONCE(skb->dev->master)))
- goto drop;
+ skb->deliver_no_wcard = 1;
skb->skb_iif = skb->dev->ifindex;
__vlan_hwaccel_put_tag(skb, vlan_tci);
@@ -84,7 +84,7 @@
struct sk_buff *p;
if (skb_bond_should_drop(skb, ACCESS_ONCE(skb->dev->master)))
- goto drop;
+ skb->deliver_no_wcard = 1;
skb->skb_iif = skb->dev->ifindex;
__vlan_hwaccel_put_tag(skb, vlan_tci);
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 55be908..5298426 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -708,7 +708,8 @@
netif_carrier_off(dev);
/* IFF_BROADCAST|IFF_MULTICAST; ??? */
- dev->flags = real_dev->flags & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI);
+ dev->flags = real_dev->flags & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI |
+ IFF_MASTER | IFF_SLAVE);
dev->iflink = real_dev->ifindex;
dev->state = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) |
(1<<__LINK_STATE_DORMANT))) |
diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c
index 0faad5c..8c100c9 100644
--- a/net/bluetooth/bnep/netdev.c
+++ b/net/bluetooth/bnep/netdev.c
@@ -104,6 +104,8 @@
break;
memcpy(__skb_put(skb, ETH_ALEN), ha->addr, ETH_ALEN);
memcpy(__skb_put(skb, ETH_ALEN), ha->addr, ETH_ALEN);
+
+ i++;
}
r->len = htons(skb->len - len);
}
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 2663743..b01dde3 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -128,7 +128,7 @@
{
struct net_bridge *br = (struct net_bridge *)_data;
unsigned long delay = hold_time(br);
- unsigned long next_timer = jiffies + br->forward_delay;
+ unsigned long next_timer = jiffies + br->ageing_time;
int i;
spin_lock_bh(&br->hash_lock);
@@ -149,9 +149,7 @@
}
spin_unlock_bh(&br->hash_lock);
- /* Add HZ/4 to ensure we round the jiffies upwards to be after the next
- * timer, otherwise we might round down and will have no-op run. */
- mod_timer(&br->gc_timer, round_jiffies(next_timer + HZ/4));
+ mod_timer(&br->gc_timer, round_jiffies_up(next_timer));
}
/* Completely flush all dynamic entries in forwarding database.*/
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index a98ef13..a4e72a8 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -140,10 +140,10 @@
void (*__packet_hook)(const struct net_bridge_port *p,
struct sk_buff *skb))
{
+ struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
+
skb = skb_clone(skb, GFP_ATOMIC);
if (!skb) {
- struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
-
dev->stats.tx_dropped++;
return -ENOMEM;
}
diff --git a/net/caif/cfrfml.c b/net/caif/cfrfml.c
index cd2830f..fd27b17 100644
--- a/net/caif/cfrfml.c
+++ b/net/caif/cfrfml.c
@@ -83,7 +83,7 @@
if (!cfsrvl_ready(service, &ret))
return ret;
- if (!cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) {
+ if (cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) {
pr_err("CAIF: %s():Packet too large - size=%d\n",
__func__, cfpkt_getlen(pkt));
return -EOVERFLOW;
diff --git a/net/caif/cfveil.c b/net/caif/cfveil.c
index 0fd827f..e04f7d9 100644
--- a/net/caif/cfveil.c
+++ b/net/caif/cfveil.c
@@ -84,7 +84,7 @@
return ret;
caif_assert(layr->dn != NULL);
caif_assert(layr->dn->transmit != NULL);
- if (!cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) {
+ if (cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) {
pr_warning("CAIF: %s(): Packet too large - size=%d\n",
__func__, cfpkt_getlen(pkt));
return -EOVERFLOW;
diff --git a/net/core/dev.c b/net/core/dev.c
index 1845b08..2b3bf53 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2253,11 +2253,9 @@
if (skb_rx_queue_recorded(skb)) {
u16 index = skb_get_rx_queue(skb);
if (unlikely(index >= dev->num_rx_queues)) {
- if (net_ratelimit()) {
- pr_warning("%s received packet on queue "
- "%u, but number of RX queues is %u\n",
- dev->name, index, dev->num_rx_queues);
- }
+ WARN_ONCE(dev->num_rx_queues > 1, "%s received packet "
+ "on queue %u, but number of RX queues is %u\n",
+ dev->name, index, dev->num_rx_queues);
goto done;
}
rxqueue = dev->_rx + index;
@@ -2795,7 +2793,7 @@
struct net_device *orig_dev;
struct net_device *master;
struct net_device *null_or_orig;
- struct net_device *null_or_bond;
+ struct net_device *orig_or_bond;
int ret = NET_RX_DROP;
__be16 type;
@@ -2812,13 +2810,24 @@
if (!skb->skb_iif)
skb->skb_iif = skb->dev->ifindex;
+ /*
+ * bonding note: skbs received on inactive slaves should only
+ * be delivered to pkt handlers that are exact matches. Also
+ * the deliver_no_wcard flag will be set. If packet handlers
+ * are sensitive to duplicate packets these skbs will need to
+ * be dropped at the handler. The vlan accel path may have
+ * already set the deliver_no_wcard flag.
+ */
null_or_orig = NULL;
orig_dev = skb->dev;
master = ACCESS_ONCE(orig_dev->master);
- if (master) {
- if (skb_bond_should_drop(skb, master))
+ if (skb->deliver_no_wcard)
+ null_or_orig = orig_dev;
+ else if (master) {
+ if (skb_bond_should_drop(skb, master)) {
+ skb->deliver_no_wcard = 1;
null_or_orig = orig_dev; /* deliver only exact match */
- else
+ } else
skb->dev = master;
}
@@ -2868,10 +2877,10 @@
* device that may have registered for a specific ptype. The
* handler may have to adjust skb->dev and orig_dev.
*/
- null_or_bond = NULL;
+ orig_or_bond = orig_dev;
if ((skb->dev->priv_flags & IFF_802_1Q_VLAN) &&
(vlan_dev_real_dev(skb->dev)->priv_flags & IFF_BONDING)) {
- null_or_bond = vlan_dev_real_dev(skb->dev);
+ orig_or_bond = vlan_dev_real_dev(skb->dev);
}
type = skb->protocol;
@@ -2879,7 +2888,7 @@
&ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) {
if (ptype->type == type && (ptype->dev == null_or_orig ||
ptype->dev == skb->dev || ptype->dev == orig_dev ||
- ptype->dev == null_or_bond)) {
+ ptype->dev == orig_or_bond)) {
if (pt_prev)
ret = deliver_skb(skb, pt_prev, orig_dev);
pt_prev = ptype;
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c
index cf8e703..785e527 100644
--- a/net/core/gen_estimator.c
+++ b/net/core/gen_estimator.c
@@ -107,6 +107,7 @@
/* Protects against soft lockup during large deletion */
static struct rb_root est_root = RB_ROOT;
+static DEFINE_SPINLOCK(est_tree_lock);
static void est_timer(unsigned long arg)
{
@@ -201,7 +202,6 @@
*
* Returns 0 on success or a negative error code.
*
- * NOTE: Called under rtnl_mutex
*/
int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
struct gnet_stats_rate_est *rate_est,
@@ -232,6 +232,7 @@
est->last_packets = bstats->packets;
est->avpps = rate_est->pps<<10;
+ spin_lock(&est_tree_lock);
if (!elist[idx].timer.function) {
INIT_LIST_HEAD(&elist[idx].list);
setup_timer(&elist[idx].timer, est_timer, idx);
@@ -242,6 +243,7 @@
list_add_rcu(&est->list, &elist[idx].list);
gen_add_node(est);
+ spin_unlock(&est_tree_lock);
return 0;
}
@@ -261,13 +263,13 @@
*
* Removes the rate estimator specified by &bstats and &rate_est.
*
- * NOTE: Called under rtnl_mutex
*/
void gen_kill_estimator(struct gnet_stats_basic_packed *bstats,
struct gnet_stats_rate_est *rate_est)
{
struct gen_estimator *e;
+ spin_lock(&est_tree_lock);
while ((e = gen_find_node(bstats, rate_est))) {
rb_erase(&e->node, &est_root);
@@ -278,6 +280,7 @@
list_del_rcu(&e->list);
call_rcu(&e->e_rcu, __gen_kill_estimator);
}
+ spin_unlock(&est_tree_lock);
}
EXPORT_SYMBOL(gen_kill_estimator);
@@ -312,8 +315,14 @@
bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats,
const struct gnet_stats_rate_est *rate_est)
{
+ bool res;
+
ASSERT_RTNL();
- return gen_find_node(bstats, rate_est) != NULL;
+ spin_lock(&est_tree_lock);
+ res = gen_find_node(bstats, rate_est) != NULL;
+ spin_unlock(&est_tree_lock);
+
+ return res;
}
EXPORT_SYMBOL(gen_estimator_active);
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 2ad68da..1dacd7b 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -2170,7 +2170,7 @@
end_time = ktime_now();
pkt_dev->idle_acc += ktime_to_ns(ktime_sub(end_time, start_time));
- pkt_dev->next_tx = ktime_add_ns(end_time, pkt_dev->delay);
+ pkt_dev->next_tx = ktime_add_ns(spin_until, pkt_dev->delay);
}
static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 9f07e74..34432b4 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -532,6 +532,7 @@
new->ip_summed = old->ip_summed;
skb_copy_queue_mapping(new, old);
new->priority = old->priority;
+ new->deliver_no_wcard = old->deliver_no_wcard;
#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
new->ipvs_property = old->ipvs_property;
#endif
@@ -569,7 +570,6 @@
C(len);
C(data_len);
C(mac_len);
- C(rxhash);
n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len;
n->cloned = 1;
n->nohdr = 0;
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 8e3a1fd..7c3a7d1 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -303,7 +303,7 @@
If unsure, say N.
config SYN_COOKIES
- bool "IP: TCP syncookie support (disabled per default)"
+ bool "IP: TCP syncookie support"
---help---
Normal TCP/IP networking is open to an attack known as "SYN
flooding". This denial-of-service attack prevents legitimate remote
@@ -328,13 +328,13 @@
server is really overloaded. If this happens frequently better turn
them off.
- If you say Y here, note that SYN cookies aren't enabled by default;
- you can enable them by saying Y to "/proc file system support" and
+ If you say Y here, you can disable SYN cookies at run time by
+ saying Y to "/proc file system support" and
"Sysctl support" below and executing the command
- echo 1 >/proc/sys/net/ipv4/tcp_syncookies
+ echo 0 > /proc/sys/net/ipv4/tcp_syncookies
- at boot time after the /proc file system has been mounted.
+ after the /proc file system has been mounted.
If unsure, say N.
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 9a4a6c9..041d41d 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -873,8 +873,10 @@
!exthdrlen)
csummode = CHECKSUM_PARTIAL;
+ skb = skb_peek_tail(&sk->sk_write_queue);
+
inet->cork.length += length;
- if (((length> mtu) || !skb_queue_empty(&sk->sk_write_queue)) &&
+ if (((length > mtu) || (skb && skb_is_gso(skb))) &&
(sk->sk_protocol == IPPROTO_UDP) &&
(rt->u.dst.dev->features & NETIF_F_UFO)) {
err = ip_ufo_append_data(sk, getfrag, from, length, hh_len,
@@ -892,7 +894,7 @@
* adding appropriate IP header.
*/
- if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL)
+ if (!skb)
goto alloc_new_skb;
while (length > 0) {
@@ -1121,7 +1123,8 @@
return -EINVAL;
inet->cork.length += size;
- if ((sk->sk_protocol == IPPROTO_UDP) &&
+ if ((size + skb->len > mtu) &&
+ (sk->sk_protocol == IPPROTO_UDP) &&
(rt->u.dst.dev->features & NETIF_F_UFO)) {
skb_shinfo(skb)->gso_size = mtu - fragheaderlen;
skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 856123f..757f25eb 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -267,8 +267,10 @@
{
struct mr_table *mrt, *next;
- list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list)
+ list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list) {
+ list_del(&mrt->list);
kfree(mrt);
+ }
fib_rules_unregister(net->ipv4.mr_rules_ops);
}
#else
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index 5c24db4..9f6b222 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -347,7 +347,7 @@
{ .sport = th->dest,
.dport = th->source } } };
security_req_classify_flow(req, &fl);
- if (ip_route_output_key(&init_net, &rt, &fl)) {
+ if (ip_route_output_key(sock_net(sk), &rt, &fl)) {
reqsk_free(req);
goto out;
}
diff --git a/net/ipv4/tcp_hybla.c b/net/ipv4/tcp_hybla.c
index c209e05..377bc93 100644
--- a/net/ipv4/tcp_hybla.c
+++ b/net/ipv4/tcp_hybla.c
@@ -126,8 +126,8 @@
* calculate 2^fract in a <<7 value.
*/
is_slowstart = 1;
- increment = ((1 << ca->rho) * hybla_fraction(rho_fractions))
- - 128;
+ increment = ((1 << min(ca->rho, 16U)) *
+ hybla_fraction(rho_fractions)) - 128;
} else {
/*
* congestion avoidance
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 202cf09..fe193e5 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1555,6 +1555,7 @@
#endif
if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
+ sock_rps_save_rxhash(sk, skb->rxhash);
TCP_CHECK_TIMER(sk);
if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) {
rsk = sk;
@@ -1579,7 +1580,9 @@
}
return 0;
}
- }
+ } else
+ sock_rps_save_rxhash(sk, skb->rxhash);
+
TCP_CHECK_TIMER(sk);
if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) {
@@ -1672,8 +1675,6 @@
skb->dev = NULL;
- sock_rps_save_rxhash(sk, skb->rxhash);
-
bh_lock_sock_nested(sk);
ret = 0;
if (!sock_owned_by_user(sk)) {
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index ce79929..03e62f9 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -483,7 +483,7 @@
np->tclass, NULL, &fl, (struct rt6_info*)dst,
MSG_DONTWAIT, np->dontfrag);
if (err) {
- ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
+ ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS);
ip6_flush_pending_frames(sk);
goto out_put;
}
@@ -565,7 +565,7 @@
np->dontfrag);
if (err) {
- ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
+ ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS);
ip6_flush_pending_frames(sk);
goto out_put;
}
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 073071f..66078da 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -120,7 +120,7 @@
static void ipmr_expire_process(unsigned long arg);
#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
-#define ip6mr_for_each_table(mrt, met) \
+#define ip6mr_for_each_table(mrt, net) \
list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list)
static struct mr6_table *ip6mr_get_table(struct net *net, u32 id)
@@ -254,8 +254,10 @@
{
struct mr6_table *mrt, *next;
- list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list)
+ list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) {
+ list_del(&mrt->list);
ip6mr_free_table(mrt);
+ }
fib_rules_unregister(net->ipv6.mr6_rules_ops);
}
#else
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 59f1881..ab1622d 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -1356,7 +1356,10 @@
IPV6_TLV_PADN, 0 };
/* we assume size > sizeof(ra) here */
- skb = sock_alloc_send_skb(sk, size + LL_ALLOCATED_SPACE(dev), 1, &err);
+ size += LL_ALLOCATED_SPACE(dev);
+ /* limit our allocations to order-0 page */
+ size = min_t(int, size, SKB_MAX_ORDER(0, 0));
+ skb = sock_alloc_send_skb(sk, size, 1, &err);
if (!skb)
return NULL;
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 0abdc24..2efef52 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -586,6 +586,7 @@
src_addr = solicited_addr;
if (ifp->flags & IFA_F_OPTIMISTIC)
override = 0;
+ inc_opt |= ifp->idev->cnf.force_tllao;
in6_ifa_put(ifp);
} else {
if (ipv6_dev_get_saddr(dev_net(dev), dev, daddr,
@@ -599,7 +600,6 @@
icmp6h.icmp6_solicited = solicited;
icmp6h.icmp6_override = override;
- inc_opt |= ifp->idev->cnf.force_tllao;
__ndisc_send(dev, neigh, daddr, src_addr,
&icmp6h, solicited_addr,
inc_opt ? ND_OPT_TARGET_LL_ADDR : 0);
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index c163d0a..98258b7 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -332,14 +332,16 @@
IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
spin_unlock(&local->ampdu_lock);
- spin_unlock_bh(&sta->lock);
- /* send an addBA request */
+ /* prepare tid data */
sta->ampdu_mlme.dialog_token_allocator++;
sta->ampdu_mlme.tid_tx[tid]->dialog_token =
sta->ampdu_mlme.dialog_token_allocator;
sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num;
+ spin_unlock_bh(&sta->lock);
+
+ /* send AddBA request */
ieee80211_send_addba_request(sdata, pubsta->addr, tid,
sta->ampdu_mlme.tid_tx[tid]->dialog_token,
sta->ampdu_mlme.tid_tx[tid]->ssn,
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 4f22713..9c1da08 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -349,7 +349,7 @@
struct survey_info *survey)
{
int ret = -EOPNOTSUPP;
- if (local->ops->conf_tx)
+ if (local->ops->get_survey)
ret = local->ops->get_survey(&local->hw, idx, survey);
/* trace_drv_get_survey(local, idx, survey, ret); */
return ret;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 0839c4e..f803f8b 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1692,14 +1692,52 @@
rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
break;
case IEEE80211_STYPE_ACTION:
- if (mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT)
- break;
+ switch (mgmt->u.action.category) {
+ case WLAN_CATEGORY_BACK: {
+ struct ieee80211_local *local = sdata->local;
+ int len = skb->len;
+ struct sta_info *sta;
- ieee80211_sta_process_chanswitch(sdata,
- &mgmt->u.action.u.chan_switch.sw_elem,
- (void *)ifmgd->associated->priv,
- rx_status->mactime);
- break;
+ rcu_read_lock();
+ sta = sta_info_get(sdata, mgmt->sa);
+ if (!sta) {
+ rcu_read_unlock();
+ break;
+ }
+
+ local_bh_disable();
+
+ switch (mgmt->u.action.u.addba_req.action_code) {
+ case WLAN_ACTION_ADDBA_REQ:
+ if (len < (IEEE80211_MIN_ACTION_SIZE +
+ sizeof(mgmt->u.action.u.addba_req)))
+ break;
+ ieee80211_process_addba_request(local, sta, mgmt, len);
+ break;
+ case WLAN_ACTION_ADDBA_RESP:
+ if (len < (IEEE80211_MIN_ACTION_SIZE +
+ sizeof(mgmt->u.action.u.addba_resp)))
+ break;
+ ieee80211_process_addba_resp(local, sta, mgmt, len);
+ break;
+ case WLAN_ACTION_DELBA:
+ if (len < (IEEE80211_MIN_ACTION_SIZE +
+ sizeof(mgmt->u.action.u.delba)))
+ break;
+ ieee80211_process_delba(sdata, sta, mgmt, len);
+ break;
+ }
+ local_bh_enable();
+ rcu_read_unlock();
+ break;
+ }
+ case WLAN_CATEGORY_SPECTRUM_MGMT:
+ ieee80211_sta_process_chanswitch(sdata,
+ &mgmt->u.action.u.chan_switch.sw_elem,
+ (void *)ifmgd->associated->priv,
+ rx_status->mactime);
+ break;
+ }
}
mutex_unlock(&ifmgd->mtx);
@@ -1722,9 +1760,45 @@
mutex_unlock(&ifmgd->mtx);
if (skb->len >= 24 + 2 /* mgmt + deauth reason */ &&
- (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH)
- cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
+ (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH) {
+ struct ieee80211_local *local = sdata->local;
+ struct ieee80211_work *wk;
+ mutex_lock(&local->work_mtx);
+ list_for_each_entry(wk, &local->work_list, list) {
+ if (wk->sdata != sdata)
+ continue;
+
+ if (wk->type != IEEE80211_WORK_ASSOC)
+ continue;
+
+ if (memcmp(mgmt->bssid, wk->filter_ta, ETH_ALEN))
+ continue;
+ if (memcmp(mgmt->sa, wk->filter_ta, ETH_ALEN))
+ continue;
+
+ /*
+ * Printing the message only here means we can't
+ * spuriously print it, but it also means that it
+ * won't be printed when the frame comes in before
+ * we even tried to associate or in similar cases.
+ *
+ * Ultimately, I suspect cfg80211 should print the
+ * messages instead.
+ */
+ printk(KERN_DEBUG
+ "%s: deauthenticated from %pM (Reason: %u)\n",
+ sdata->name, mgmt->bssid,
+ le16_to_cpu(mgmt->u.deauth.reason_code));
+
+ list_del_rcu(&wk->list);
+ free_work(wk);
+ break;
+ }
+ mutex_unlock(&local->work_mtx);
+
+ cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
+ }
out:
kfree_skb(skb);
}
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 6e2a7bc..be9abc2 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1818,17 +1818,26 @@
return RX_CONTINUE;
if (ieee80211_is_back_req(bar->frame_control)) {
+ struct {
+ __le16 control, start_seq_num;
+ } __packed bar_data;
+
if (!rx->sta)
return RX_DROP_MONITOR;
+
+ if (skb_copy_bits(skb, offsetof(struct ieee80211_bar, control),
+ &bar_data, sizeof(bar_data)))
+ return RX_DROP_MONITOR;
+
spin_lock(&rx->sta->lock);
- tid = le16_to_cpu(bar->control) >> 12;
+ tid = le16_to_cpu(bar_data.control) >> 12;
if (!rx->sta->ampdu_mlme.tid_active_rx[tid]) {
spin_unlock(&rx->sta->lock);
return RX_DROP_MONITOR;
}
tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid];
- start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4;
+ start_seq_num = le16_to_cpu(bar_data.start_seq_num) >> 4;
/* reset session timer */
if (tid_agg_rx->timeout)
@@ -1935,6 +1944,9 @@
if (len < IEEE80211_MIN_ACTION_SIZE + 1)
break;
+ if (sdata->vif.type == NL80211_IFTYPE_STATION)
+ return ieee80211_sta_rx_mgmt(sdata, rx->skb);
+
switch (mgmt->u.action.u.addba_req.action_code) {
case WLAN_ACTION_ADDBA_REQ:
if (len < (IEEE80211_MIN_ACTION_SIZE +
diff --git a/net/mac80211/work.c b/net/mac80211/work.c
index be3d4a69..b025dc7 100644
--- a/net/mac80211/work.c
+++ b/net/mac80211/work.c
@@ -715,7 +715,7 @@
struct ieee80211_rx_status *rx_status;
struct ieee80211_mgmt *mgmt;
struct ieee80211_work *wk;
- enum work_action rma;
+ enum work_action rma = WORK_ACT_NONE;
u16 fc;
rx_status = (struct ieee80211_rx_status *) skb->cb;
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index d8f7e8e..ff04e9e 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -162,6 +162,7 @@
hash = ip_vs_conn_hashkey(cp->af, cp->protocol, &cp->caddr, cp->cport);
ct_write_lock(hash);
+ spin_lock(&cp->lock);
if (!(cp->flags & IP_VS_CONN_F_HASHED)) {
list_add(&cp->c_list, &ip_vs_conn_tab[hash]);
@@ -174,6 +175,7 @@
ret = 0;
}
+ spin_unlock(&cp->lock);
ct_write_unlock(hash);
return ret;
@@ -193,6 +195,7 @@
hash = ip_vs_conn_hashkey(cp->af, cp->protocol, &cp->caddr, cp->cport);
ct_write_lock(hash);
+ spin_lock(&cp->lock);
if (cp->flags & IP_VS_CONN_F_HASHED) {
list_del(&cp->c_list);
@@ -202,6 +205,7 @@
} else
ret = 0;
+ spin_unlock(&cp->lock);
ct_write_unlock(hash);
return ret;
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
index d885ba3..5709494 100644
--- a/net/sched/act_nat.c
+++ b/net/sched/act_nat.c
@@ -159,6 +159,9 @@
iph->daddr = new_addr;
csum_replace4(&iph->check, addr, new_addr);
+ } else if ((iph->frag_off & htons(IP_OFFSET)) ||
+ iph->protocol != IPPROTO_ICMP) {
+ goto out;
}
ihl = iph->ihl * 4;
@@ -247,6 +250,7 @@
break;
}
+out:
return action;
drop:
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index fdbd0b7..50e3d94 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -125,7 +125,7 @@
{
struct tcf_pedit *p = a->priv;
int i, munged = 0;
- u8 *pptr;
+ unsigned int off;
if (!(skb->tc_verd & TC_OK2MUNGE)) {
/* should we set skb->cloned? */
@@ -134,7 +134,7 @@
}
}
- pptr = skb_network_header(skb);
+ off = skb_network_offset(skb);
spin_lock(&p->tcf_lock);
@@ -144,17 +144,17 @@
struct tc_pedit_key *tkey = p->tcfp_keys;
for (i = p->tcfp_nkeys; i > 0; i--, tkey++) {
- u32 *ptr;
+ u32 *ptr, _data;
int offset = tkey->off;
if (tkey->offmask) {
- if (skb->len > tkey->at) {
- char *j = pptr + tkey->at;
- offset += ((*j & tkey->offmask) >>
- tkey->shift);
- } else {
+ char *d, _d;
+
+ d = skb_header_pointer(skb, off + tkey->at, 1,
+ &_d);
+ if (!d)
goto bad;
- }
+ offset += (*d & tkey->offmask) >> tkey->shift;
}
if (offset % 4) {
@@ -169,9 +169,13 @@
goto bad;
}
- ptr = (u32 *)(pptr+offset);
+ ptr = skb_header_pointer(skb, off + offset, 4, &_data);
+ if (!ptr)
+ goto bad;
/* just do it, baby */
*ptr = ((*ptr & tkey->mask) ^ tkey->val);
+ if (ptr == &_data)
+ skb_store_bits(skb, off + offset, ptr, 4);
munged++;
}
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 9627542..4f52214 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -98,11 +98,11 @@
{
struct {
struct tc_u_knode *knode;
- u8 *ptr;
+ unsigned int off;
} stack[TC_U32_MAXDEPTH];
struct tc_u_hnode *ht = (struct tc_u_hnode*)tp->root;
- u8 *ptr = skb_network_header(skb);
+ unsigned int off = skb_network_offset(skb);
struct tc_u_knode *n;
int sdepth = 0;
int off2 = 0;
@@ -134,8 +134,14 @@
#endif
for (i = n->sel.nkeys; i>0; i--, key++) {
+ unsigned int toff;
+ __be32 *data, _data;
- if ((*(__be32*)(ptr+key->off+(off2&key->offmask))^key->val)&key->mask) {
+ toff = off + key->off + (off2 & key->offmask);
+ data = skb_header_pointer(skb, toff, 4, &_data);
+ if (!data)
+ goto out;
+ if ((*data ^ key->val) & key->mask) {
n = n->next;
goto next_knode;
}
@@ -174,29 +180,45 @@
if (sdepth >= TC_U32_MAXDEPTH)
goto deadloop;
stack[sdepth].knode = n;
- stack[sdepth].ptr = ptr;
+ stack[sdepth].off = off;
sdepth++;
ht = n->ht_down;
sel = 0;
- if (ht->divisor)
- sel = ht->divisor&u32_hash_fold(*(__be32*)(ptr+n->sel.hoff), &n->sel,n->fshift);
+ if (ht->divisor) {
+ __be32 *data, _data;
+ data = skb_header_pointer(skb, off + n->sel.hoff, 4,
+ &_data);
+ if (!data)
+ goto out;
+ sel = ht->divisor & u32_hash_fold(*data, &n->sel,
+ n->fshift);
+ }
if (!(n->sel.flags&(TC_U32_VAROFFSET|TC_U32_OFFSET|TC_U32_EAT)))
goto next_ht;
if (n->sel.flags&(TC_U32_OFFSET|TC_U32_VAROFFSET)) {
off2 = n->sel.off + 3;
- if (n->sel.flags&TC_U32_VAROFFSET)
- off2 += ntohs(n->sel.offmask & *(__be16*)(ptr+n->sel.offoff)) >>n->sel.offshift;
+ if (n->sel.flags & TC_U32_VAROFFSET) {
+ __be16 *data, _data;
+
+ data = skb_header_pointer(skb,
+ off + n->sel.offoff,
+ 2, &_data);
+ if (!data)
+ goto out;
+ off2 += ntohs(n->sel.offmask & *data) >>
+ n->sel.offshift;
+ }
off2 &= ~3;
}
if (n->sel.flags&TC_U32_EAT) {
- ptr += off2;
+ off += off2;
off2 = 0;
}
- if (ptr < skb_tail_pointer(skb))
+ if (off < skb->len)
goto next_ht;
}
@@ -204,9 +226,10 @@
if (sdepth--) {
n = stack[sdepth].knode;
ht = n->ht_up;
- ptr = stack[sdepth].ptr;
+ off = stack[sdepth].off;
goto check_terminal;
}
+out:
return -1;
deadloop:
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index 3415b6c..807643b 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -449,6 +449,7 @@
dev->tx_queue_len = 100;
dev->flags = IFF_NOARP;
dev->hard_header_len = LL_MAX_HEADER;
+ dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
}
static LIST_HEAD(master_dev_list);
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 2a96751..7ca65c7 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -210,7 +210,8 @@
* State of TCP reply receive
*/
__be32 tcp_fraghdr,
- tcp_xid;
+ tcp_xid,
+ tcp_calldir;
u32 tcp_offset,
tcp_reclen;
@@ -927,7 +928,7 @@
{
size_t len, used;
u32 offset;
- __be32 calldir;
+ char *p;
/*
* We want transport->tcp_offset to be 8 at the end of this routine
@@ -936,26 +937,33 @@
* transport->tcp_offset is 4 (after having already read the xid).
*/
offset = transport->tcp_offset - sizeof(transport->tcp_xid);
- len = sizeof(calldir) - offset;
+ len = sizeof(transport->tcp_calldir) - offset;
dprintk("RPC: reading CALL/REPLY flag (%Zu bytes)\n", len);
- used = xdr_skb_read_bits(desc, &calldir, len);
+ p = ((char *) &transport->tcp_calldir) + offset;
+ used = xdr_skb_read_bits(desc, p, len);
transport->tcp_offset += used;
if (used != len)
return;
transport->tcp_flags &= ~TCP_RCV_READ_CALLDIR;
- transport->tcp_flags |= TCP_RCV_COPY_CALLDIR;
- transport->tcp_flags |= TCP_RCV_COPY_DATA;
/*
* We don't yet have the XDR buffer, so we will write the calldir
* out after we get the buffer from the 'struct rpc_rqst'
*/
- if (ntohl(calldir) == RPC_REPLY)
+ switch (ntohl(transport->tcp_calldir)) {
+ case RPC_REPLY:
+ transport->tcp_flags |= TCP_RCV_COPY_CALLDIR;
+ transport->tcp_flags |= TCP_RCV_COPY_DATA;
transport->tcp_flags |= TCP_RPC_REPLY;
- else
+ break;
+ case RPC_CALL:
+ transport->tcp_flags |= TCP_RCV_COPY_CALLDIR;
+ transport->tcp_flags |= TCP_RCV_COPY_DATA;
transport->tcp_flags &= ~TCP_RPC_REPLY;
- dprintk("RPC: reading %s CALL/REPLY flag %08x\n",
- (transport->tcp_flags & TCP_RPC_REPLY) ?
- "reply for" : "request with", calldir);
+ break;
+ default:
+ dprintk("RPC: invalid request message type\n");
+ xprt_force_disconnect(&transport->xprt);
+ }
xs_tcp_check_fraghdr(transport);
}
@@ -975,12 +983,10 @@
/*
* Save the RPC direction in the XDR buffer
*/
- __be32 calldir = transport->tcp_flags & TCP_RPC_REPLY ?
- htonl(RPC_REPLY) : 0;
-
memcpy(rcvbuf->head[0].iov_base + transport->tcp_copied,
- &calldir, sizeof(calldir));
- transport->tcp_copied += sizeof(calldir);
+ &transport->tcp_calldir,
+ sizeof(transport->tcp_calldir));
+ transport->tcp_copied += sizeof(transport->tcp_calldir);
transport->tcp_flags &= ~TCP_RCV_COPY_CALLDIR;
}
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 6a32915..a3cca0a 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -95,13 +95,13 @@
goto error_nolock;
}
- dst = dst_pop(dst);
+ dst = skb_dst_pop(skb);
if (!dst) {
XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTERROR);
err = -EHOSTUNREACH;
goto error_nolock;
}
- skb_dst_set(skb, dst);
+ skb_dst_set_noref(skb, dst);
x = dst->xfrm;
} while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL));
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index d965a2b..af1c173 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -2153,6 +2153,7 @@
return 0;
}
+ skb_dst_force(skb);
dst = skb_dst(skb);
res = xfrm_lookup(net, &dst, &fl, NULL, 0) == 0;
@@ -2299,7 +2300,8 @@
return 0;
if (xdst->xfrm_genid != dst->xfrm->genid)
return 0;
- if (xdst->policy_genid != atomic_read(&xdst->pols[0]->genid))
+ if (xdst->num_pols > 0 &&
+ xdst->policy_genid != atomic_read(&xdst->pols[0]->genid))
return 0;
if (strict && fl &&
diff --git a/scripts/Makefile.modbuiltin b/scripts/Makefile.modbuiltin
index 102a276..1adb974 100644
--- a/scripts/Makefile.modbuiltin
+++ b/scripts/Makefile.modbuiltin
@@ -14,6 +14,11 @@
include scripts/Kbuild.include
+ifneq ($(KBUILD_SRC),)
+# Create output directory if not already present
+_dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj))
+endif
+
# The filename Kbuild has precedence over Makefile
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 7cdae39..7ea649d 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -219,7 +219,7 @@
HOSTLOADLIBES_qconf = $(KC_QT_LIBS) -ldl
HOSTCXXFLAGS_qconf.o = $(KC_QT_CFLAGS) -D LKC_DIRECT_LINK
-HOSTLOADLIBES_gconf = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0`
+HOSTLOADLIBES_gconf = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0` -ldl
HOSTCFLAGS_gconf.o = `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \
-D LKC_DIRECT_LINK
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 3318692..f877900 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -1342,7 +1342,7 @@
int section = sechdr->sh_info;
return (void *)elf->hdr + sechdrs[section].sh_offset +
- (r->r_offset - sechdrs[section].sh_addr);
+ r->r_offset - sechdrs[section].sh_addr;
}
static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 13074b4..6261745 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -33,7 +33,7 @@
ret = strncpy_from_user(type, _type, len);
if (ret < 0)
- return -EFAULT;
+ return ret;
if (ret == 0 || ret >= len)
return -EINVAL;
@@ -1080,7 +1080,7 @@
return old_setting;
error:
abort_creds(new);
- return -EINVAL;
+ return ret;
} /* end keyctl_set_reqkey_keyring() */
diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/core.c
index 6789337..3ff8cc5 100644
--- a/sound/aoa/soundbus/i2sbus/core.c
+++ b/sound/aoa/soundbus/i2sbus/core.c
@@ -437,9 +437,11 @@
}
static struct macio_driver i2sbus_drv = {
- .name = "soundbus-i2s",
- .owner = THIS_MODULE,
- .match_table = i2sbus_match,
+ .driver = {
+ .name = "soundbus-i2s",
+ .owner = THIS_MODULE,
+ .of_match_table = i2sbus_match,
+ },
.probe = i2sbus_probe,
.remove = i2sbus_remove,
#ifdef CONFIG_PM
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c
index 428121a..10c3a87 100644
--- a/sound/atmel/ac97c.c
+++ b/sound/atmel/ac97c.c
@@ -657,7 +657,7 @@
if (sr & AC97C_SR_CAEVT) {
struct snd_pcm_runtime *runtime;
int offset, next_period, block_size;
- dev_info(&chip->pdev->dev, "channel A event%s%s%s%s%s%s\n",
+ dev_dbg(&chip->pdev->dev, "channel A event%s%s%s%s%s%s\n",
casr & AC97C_CSR_OVRUN ? " OVRUN" : "",
casr & AC97C_CSR_RXRDY ? " RXRDY" : "",
casr & AC97C_CSR_UNRUN ? " UNRUN" : "",
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c
index f74c737..1db586a 100644
--- a/sound/pci/asihpi/asihpi.c
+++ b/sound/pci/asihpi/asihpi.c
@@ -2578,6 +2578,9 @@
if (err)
return -err;
+ memset(&prev_ctl, 0, sizeof(prev_ctl));
+ prev_ctl.control_type = -1;
+
for (idx = 0; idx < 2000; idx++) {
err = hpi_mixer_get_control_by_index(
ss, asihpi->h_mixer,
diff --git a/sound/pci/asihpi/hpi6205.c b/sound/pci/asihpi/hpi6205.c
index e89991e..3b44134 100644
--- a/sound/pci/asihpi/hpi6205.c
+++ b/sound/pci/asihpi/hpi6205.c
@@ -941,11 +941,11 @@
}
-static long outstream_get_space_available(struct hpi_hostbuffer_status
+static u32 outstream_get_space_available(struct hpi_hostbuffer_status
*status)
{
- return status->size_in_bytes - ((long)(status->host_index) -
- (long)(status->dSP_index));
+ return status->size_in_bytes - (status->host_index -
+ status->dSP_index);
}
static void outstream_write(struct hpi_adapter_obj *pao,
@@ -954,7 +954,7 @@
struct hpi_hw_obj *phw = pao->priv;
struct bus_master_interface *interface = phw->p_interface_buffer;
struct hpi_hostbuffer_status *status;
- long space_available;
+ u32 space_available;
if (!phw->outstream_host_buffer_size[phm->obj_index]) {
/* there is no BBM buffer, write via message */
@@ -1007,7 +1007,7 @@
}
space_available = outstream_get_space_available(status);
- if (space_available < (long)phm->u.d.u.data.data_size) {
+ if (space_available < phm->u.d.u.data.data_size) {
phr->error = HPI_ERROR_INVALID_DATASIZE;
return;
}
@@ -1018,7 +1018,7 @@
&& hpios_locked_mem_valid(&phw->outstream_host_buffers[phm->
obj_index])) {
u8 *p_bbm_data;
- long l_first_write;
+ u32 l_first_write;
u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data;
if (hpios_locked_mem_get_virt_addr(&phw->
@@ -1248,9 +1248,9 @@
hw_message(pao, phm, phr);
}
-static long instream_get_bytes_available(struct hpi_hostbuffer_status *status)
+static u32 instream_get_bytes_available(struct hpi_hostbuffer_status *status)
{
- return (long)(status->dSP_index) - (long)(status->host_index);
+ return status->dSP_index - status->host_index;
}
static void instream_read(struct hpi_adapter_obj *pao,
@@ -1259,9 +1259,9 @@
struct hpi_hw_obj *phw = pao->priv;
struct bus_master_interface *interface = phw->p_interface_buffer;
struct hpi_hostbuffer_status *status;
- long data_available;
+ u32 data_available;
u8 *p_bbm_data;
- long l_first_read;
+ u32 l_first_read;
u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data;
if (!phw->instream_host_buffer_size[phm->obj_index]) {
@@ -1272,7 +1272,7 @@
status = &interface->instream_host_buffer_status[phm->obj_index];
data_available = instream_get_bytes_available(status);
- if (data_available < (long)phm->u.d.u.data.data_size) {
+ if (data_available < phm->u.d.u.data.data_size) {
phr->error = HPI_ERROR_INVALID_DATASIZE;
return;
}
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index dc79564..1df25cf 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -1913,11 +1913,11 @@
if (WARN_ONCE(!azx_dev->period_bytes,
"hda-intel: zero azx_dev->period_bytes"))
return -1; /* this shouldn't happen! */
- if (wallclk <= azx_dev->period_wallclk &&
+ if (wallclk < (azx_dev->period_wallclk * 5) / 4 &&
pos % azx_dev->period_bytes > azx_dev->period_bytes / 2)
/* NG - it's below the first next period boundary */
return bdl_pos_adj[chip->dev_index] ? 0 : -1;
- azx_dev->start_wallclk = wallclk;
+ azx_dev->start_wallclk += wallclk;
return 1; /* OK, it's fine */
}
@@ -2288,6 +2288,8 @@
SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB),
SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
+ SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB),
+ SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB),
SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba A100-259", POS_FIX_LPIB),
@@ -2296,6 +2298,7 @@
SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1565, 0x820f, "Biostar Microtech", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1565, 0x8218, "Biostar Microtech", POS_FIX_LPIB),
+ SND_PCI_QUIRK(0x1849, 0x0888, "775Dual-VSTA", POS_FIX_LPIB),
SND_PCI_QUIRK(0x8086, 0x2503, "DG965OT AAD63733-203", POS_FIX_LPIB),
SND_PCI_QUIRK(0x8086, 0xd601, "eMachines T5212", POS_FIX_LPIB),
{}
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 17d4548..f1ce7d7 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -2619,16 +2619,18 @@
}
/* assign Capture Source enums to NID */
- kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
- if (!kctl)
- kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
- for (i = 0; kctl && i < kctl->count; i++) {
- hda_nid_t *nids = spec->capsrc_nids;
- if (!nids)
- nids = spec->adc_nids;
- err = snd_hda_add_nid(codec, kctl, i, nids[i]);
- if (err < 0)
- return err;
+ if (spec->capsrc_nids || spec->adc_nids) {
+ kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
+ if (!kctl)
+ kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
+ for (i = 0; kctl && i < kctl->count; i++) {
+ hda_nid_t *nids = spec->capsrc_nids;
+ if (!nids)
+ nids = spec->adc_nids;
+ err = snd_hda_add_nid(codec, kctl, i, nids[i]);
+ if (err < 0)
+ return err;
+ }
}
if (spec->cap_mixer) {
const char *kname = kctl ? kctl->id.name : NULL;
@@ -6948,7 +6950,7 @@
.num_items = 3,
.items = {
{ "Mic", 0x1 },
- { "Line", 0x2 },
+ { "Line", 0x7 },
{ "CD", 0x4 },
},
};
@@ -7469,8 +7471,8 @@
HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT),
+ HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
HDA_CODEC_VOLUME("Line Boost", 0x15, 0x00, HDA_INPUT),
@@ -7853,10 +7855,9 @@
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0x1)},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x7)},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x4)},
{ }
};
@@ -9476,6 +9477,10 @@
SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_IMAC24),
SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_IMAC24),
SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC885_MBP3),
+ SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889A_MB31),
+ SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_ASUS_A7M),
+ SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC885_MBP3),
+ SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC885_MBA21),
SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889A_MB31),
SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC885_MBP3),
SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_IMAC24),
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 79f0f4a..d395509 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -612,7 +612,6 @@
NUMDMA_MASK);
mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL,
((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK);
- mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE);
}
if (dev->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) {
@@ -623,7 +622,6 @@
NUMDMA_MASK);
mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL,
((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK);
- mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE);
}
}
diff --git a/sound/soc/fsl/mpc5200_dma.h b/sound/soc/fsl/mpc5200_dma.h
index 22208b3..e1ec6d9 100644
--- a/sound/soc/fsl/mpc5200_dma.h
+++ b/sound/soc/fsl/mpc5200_dma.h
@@ -73,7 +73,7 @@
};
/* Utility for retrieving psc_dma_stream structure from a substream */
-inline struct psc_dma_stream *
+static inline struct psc_dma_stream *
to_psc_dma_stream(struct snd_pcm_substream *substream, struct psc_dma *psc_dma)
{
if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig
index eba9b9d..252defe 100644
--- a/sound/soc/imx/Kconfig
+++ b/sound/soc/imx/Kconfig
@@ -13,9 +13,18 @@
config SND_MXC_SOC_WM1133_EV1
tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted"
- depends on SND_IMX_SOC && EXPERIMENTAL
+ depends on SND_IMX_SOC && MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL
select SND_SOC_WM8350
select SND_MXC_SOC_SSI
help
Enable support for audio on the i.MX31ADS with the WM1133-EV1
PMIC board with WM8835x fitted.
+
+config SND_SOC_PHYCORE_AC97
+ tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards"
+ depends on MACH_PCM043 || MACH_PCA100
+ select SND_MXC_SOC_SSI
+ select SND_SOC_WM9712
+ help
+ Say Y if you want to add support for SoC audio on Phytec phyCORE
+ and phyCARD boards in AC97 mode
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
index 1941a35..d256f5f 100644
--- a/sound/soc/pxa/spitz.c
+++ b/sound/soc/pxa/spitz.c
@@ -328,38 +328,6 @@
.codec_dev = &soc_codec_dev_wm8750,
};
-/*
- * FIXME: This is a temporary bodge to avoid cross-tree merge issues.
- * New drivers should register the wm8750 I2C device in the machine
- * setup code (under arch/arm for ARM systems).
- */
-static int wm8750_i2c_register(void)
-{
- struct i2c_board_info info;
- struct i2c_adapter *adapter;
- struct i2c_client *client;
-
- memset(&info, 0, sizeof(struct i2c_board_info));
- info.addr = 0x1b;
- strlcpy(info.type, "wm8750", I2C_NAME_SIZE);
-
- adapter = i2c_get_adapter(0);
- if (!adapter) {
- printk(KERN_ERR "can't get i2c adapter 0\n");
- return -ENODEV;
- }
-
- client = i2c_new_device(adapter, &info);
- i2c_put_adapter(adapter);
- if (!client) {
- printk(KERN_ERR "can't add i2c device at 0x%x\n",
- (unsigned int)info.addr);
- return -ENODEV;
- }
-
- return 0;
-}
-
static struct platform_device *spitz_snd_device;
static int __init spitz_init(void)
@@ -369,10 +337,6 @@
if (!(machine_is_spitz() || machine_is_borzoi() || machine_is_akita()))
return -ENODEV;
- ret = wm8750_i2c_setup();
- if (ret != 0)
- return ret;
-
spitz_snd_device = platform_device_alloc("soc-audio", -1);
if (!spitz_snd_device)
return -ENOMEM;
diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c
index 4c7b051..1bc56b2 100644
--- a/sound/spi/at73c213.c
+++ b/sound/spi/at73c213.c
@@ -69,7 +69,6 @@
int irq;
int period;
unsigned long bitrate;
- struct clk *bitclk;
struct ssc_device *ssc;
struct spi_device *spi;
u8 spi_wbuffer[2];
diff --git a/sound/usb/Makefile b/sound/usb/Makefile
index e7ac7f4..1e362bf 100644
--- a/sound/usb/Makefile
+++ b/sound/usb/Makefile
@@ -11,7 +11,8 @@
endpoint.o \
urb.o \
pcm.o \
- helper.o
+ helper.o \
+ clock.o
snd-usbmidi-lib-objs := midi.o
diff --git a/sound/usb/card.c b/sound/usb/card.c
index da1346b..7a8ac1d 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -236,7 +236,6 @@
}
case UAC_VERSION_2: {
- struct uac_clock_source_descriptor *cs;
struct usb_interface_assoc_descriptor *assoc =
usb_ifnum_to_if(dev, ctrlif)->intf_assoc;
@@ -245,21 +244,6 @@
return -EINVAL;
}
- /* FIXME: for now, we expect there is at least one clock source
- * descriptor and we always take the first one.
- * We should properly support devices with multiple clock sources,
- * clock selectors and sample rate conversion units. */
-
- cs = snd_usb_find_csint_desc(host_iface->extra, host_iface->extralen,
- NULL, UAC2_CLOCK_SOURCE);
-
- if (!cs) {
- snd_printk(KERN_ERR "CLOCK_SOURCE descriptor not found\n");
- return -EINVAL;
- }
-
- chip->clock_id = cs->bClockID;
-
for (i = 0; i < assoc->bInterfaceCount; i++) {
int intf = assoc->bFirstInterface + i;
@@ -481,6 +465,8 @@
goto __error;
}
+ chip->ctrl_intf = alts;
+
if (err > 0) {
/* create normal USB audio interfaces */
if (snd_usb_create_streams(chip, ifnum) < 0 ||
diff --git a/sound/usb/card.h b/sound/usb/card.h
index ed92420..1febf2f 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -25,6 +25,7 @@
unsigned int rate_min, rate_max; /* min/max rates */
unsigned int nr_rates; /* number of rate table entries */
unsigned int *rate_table; /* rate table */
+ unsigned char clock; /* associated clock */
};
struct snd_usb_substream;
diff --git a/sound/usb/clock.c b/sound/usb/clock.c
new file mode 100644
index 0000000..b585511
--- /dev/null
+++ b/sound/usb/clock.c
@@ -0,0 +1,315 @@
+/*
+ * Clock domain and sample rate management functions
+ *
+ * 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/bitops.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/usb.h>
+#include <linux/moduleparam.h>
+#include <linux/mutex.h>
+#include <linux/usb/audio.h>
+#include <linux/usb/audio-v2.h>
+
+#include <sound/core.h>
+#include <sound/info.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+
+#include "usbaudio.h"
+#include "card.h"
+#include "midi.h"
+#include "mixer.h"
+#include "proc.h"
+#include "quirks.h"
+#include "endpoint.h"
+#include "helper.h"
+#include "debug.h"
+#include "pcm.h"
+#include "urb.h"
+#include "format.h"
+
+static struct uac_clock_source_descriptor *
+ snd_usb_find_clock_source(struct usb_host_interface *ctrl_iface,
+ int clock_id)
+{
+ struct uac_clock_source_descriptor *cs = NULL;
+
+ while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra,
+ ctrl_iface->extralen,
+ cs, UAC2_CLOCK_SOURCE))) {
+ if (cs->bClockID == clock_id)
+ return cs;
+ }
+
+ return NULL;
+}
+
+static struct uac_clock_selector_descriptor *
+ snd_usb_find_clock_selector(struct usb_host_interface *ctrl_iface,
+ int clock_id)
+{
+ struct uac_clock_selector_descriptor *cs = NULL;
+
+ while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra,
+ ctrl_iface->extralen,
+ cs, UAC2_CLOCK_SELECTOR))) {
+ if (cs->bClockID == clock_id)
+ return cs;
+ }
+
+ return NULL;
+}
+
+static struct uac_clock_multiplier_descriptor *
+ snd_usb_find_clock_multiplier(struct usb_host_interface *ctrl_iface,
+ int clock_id)
+{
+ struct uac_clock_multiplier_descriptor *cs = NULL;
+
+ while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra,
+ ctrl_iface->extralen,
+ cs, UAC2_CLOCK_MULTIPLIER))) {
+ if (cs->bClockID == clock_id)
+ return cs;
+ }
+
+ return NULL;
+}
+
+static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_id)
+{
+ unsigned char buf;
+ int ret;
+
+ ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
+ UAC2_CS_CUR,
+ USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+ UAC2_CX_CLOCK_SELECTOR << 8,
+ snd_usb_ctrl_intf(chip) | (selector_id << 8),
+ &buf, sizeof(buf), 1000);
+
+ if (ret < 0)
+ return ret;
+
+ return buf;
+}
+
+static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id)
+{
+ int err;
+ unsigned char data;
+ struct usb_device *dev = chip->dev;
+
+ err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
+ USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+ UAC2_CS_CONTROL_CLOCK_VALID << 8,
+ snd_usb_ctrl_intf(chip) | (source_id << 8),
+ &data, sizeof(data), 1000);
+
+ if (err < 0) {
+ snd_printk(KERN_WARNING "%s(): cannot get clock validity for id %d\n",
+ __func__, source_id);
+ return err;
+ }
+
+ return !!data;
+}
+
+/* Try to find the clock source ID of a given clock entity */
+
+static int __uac_clock_find_source(struct snd_usb_audio *chip,
+ struct usb_host_interface *host_iface,
+ int entity_id, unsigned long *visited)
+{
+ struct uac_clock_source_descriptor *source;
+ struct uac_clock_selector_descriptor *selector;
+ struct uac_clock_multiplier_descriptor *multiplier;
+
+ entity_id &= 0xff;
+
+ if (test_and_set_bit(entity_id, visited)) {
+ snd_printk(KERN_WARNING
+ "%s(): recursive clock topology detected, id %d.\n",
+ __func__, entity_id);
+ return -EINVAL;
+ }
+
+ /* first, see if the ID we're looking for is a clock source already */
+ source = snd_usb_find_clock_source(host_iface, entity_id);
+ if (source)
+ return source->bClockID;
+
+ selector = snd_usb_find_clock_selector(host_iface, entity_id);
+ if (selector) {
+ int ret;
+
+ /* the entity ID we are looking for is a selector.
+ * find out what it currently selects */
+ ret = uac_clock_selector_get_val(chip, selector->bClockID);
+ if (ret < 0)
+ return ret;
+
+ if (ret > selector->bNrInPins || ret < 1) {
+ printk(KERN_ERR
+ "%s(): selector reported illegal value, id %d, ret %d\n",
+ __func__, selector->bClockID, ret);
+
+ return -EINVAL;
+ }
+
+ return __uac_clock_find_source(chip, host_iface,
+ selector->baCSourceID[ret-1],
+ visited);
+ }
+
+ /* FIXME: multipliers only act as pass-thru element for now */
+ multiplier = snd_usb_find_clock_multiplier(host_iface, entity_id);
+ if (multiplier)
+ return __uac_clock_find_source(chip, host_iface,
+ multiplier->bCSourceID, visited);
+
+ return -EINVAL;
+}
+
+int snd_usb_clock_find_source(struct snd_usb_audio *chip,
+ struct usb_host_interface *host_iface,
+ int entity_id)
+{
+ DECLARE_BITMAP(visited, 256);
+ memset(visited, 0, sizeof(visited));
+ return __uac_clock_find_source(chip, host_iface, entity_id, visited);
+}
+
+static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
+ struct usb_host_interface *alts,
+ struct audioformat *fmt, int rate)
+{
+ struct usb_device *dev = chip->dev;
+ unsigned int ep;
+ unsigned char data[3];
+ int err, crate;
+
+ ep = get_endpoint(alts, 0)->bEndpointAddress;
+
+ /* if endpoint doesn't have sampling rate control, bail out */
+ if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE)) {
+ snd_printk(KERN_WARNING "%d:%d:%d: endpoint lacks sample rate attribute bit, cannot set.\n",
+ dev->devnum, iface, fmt->altsetting);
+ return 0;
+ }
+
+ data[0] = rate;
+ data[1] = rate >> 8;
+ data[2] = rate >> 16;
+ if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
+ USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,
+ UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
+ data, sizeof(data), 1000)) < 0) {
+ snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n",
+ dev->devnum, iface, fmt->altsetting, rate, ep);
+ return err;
+ }
+
+ if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,
+ USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN,
+ UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
+ data, sizeof(data), 1000)) < 0) {
+ snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n",
+ dev->devnum, iface, fmt->altsetting, ep);
+ return 0; /* some devices don't support reading */
+ }
+
+ crate = data[0] | (data[1] << 8) | (data[2] << 16);
+ if (crate != rate) {
+ snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate);
+ // runtime->rate = crate;
+ }
+
+ return 0;
+}
+
+static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
+ struct usb_host_interface *alts,
+ struct audioformat *fmt, int rate)
+{
+ struct usb_device *dev = chip->dev;
+ unsigned char data[4];
+ int err, crate;
+ int clock = snd_usb_clock_find_source(chip, chip->ctrl_intf, fmt->clock);
+
+ if (clock < 0)
+ return clock;
+
+ if (!uac_clock_source_is_valid(chip, clock)) {
+ snd_printk(KERN_ERR "%d:%d:%d: clock source %d is not valid, cannot use\n",
+ dev->devnum, iface, fmt->altsetting, clock);
+ return -ENXIO;
+ }
+
+ data[0] = rate;
+ data[1] = rate >> 8;
+ data[2] = rate >> 16;
+ data[3] = rate >> 24;
+ if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
+ USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ UAC2_CS_CONTROL_SAM_FREQ << 8,
+ snd_usb_ctrl_intf(chip) | (clock << 8),
+ data, sizeof(data), 1000)) < 0) {
+ snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2)\n",
+ dev->devnum, iface, fmt->altsetting, rate);
+ return err;
+ }
+
+ if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
+ USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+ UAC2_CS_CONTROL_SAM_FREQ << 8,
+ snd_usb_ctrl_intf(chip) | (clock << 8),
+ data, sizeof(data), 1000)) < 0) {
+ snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n",
+ dev->devnum, iface, fmt->altsetting);
+ return err;
+ }
+
+ crate = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
+ if (crate != rate)
+ snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate);
+
+ return 0;
+}
+
+int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
+ struct usb_host_interface *alts,
+ struct audioformat *fmt, int rate)
+{
+ struct usb_interface_descriptor *altsd = get_iface_desc(alts);
+
+ switch (altsd->bInterfaceProtocol) {
+ case UAC_VERSION_1:
+ return set_sample_rate_v1(chip, iface, alts, fmt, rate);
+
+ case UAC_VERSION_2:
+ return set_sample_rate_v2(chip, iface, alts, fmt, rate);
+ }
+
+ return -EINVAL;
+}
+
diff --git a/sound/usb/clock.h b/sound/usb/clock.h
new file mode 100644
index 0000000..beb2536
--- /dev/null
+++ b/sound/usb/clock.h
@@ -0,0 +1,12 @@
+#ifndef __USBAUDIO_CLOCK_H
+#define __USBAUDIO_CLOCK_H
+
+int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
+ struct usb_host_interface *alts,
+ struct audioformat *fmt, int rate);
+
+int snd_usb_clock_find_source(struct snd_usb_audio *chip,
+ struct usb_host_interface *host_iface,
+ int entity_id);
+
+#endif /* __USBAUDIO_CLOCK_H */
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 28ee1ce..6f6596c 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -190,6 +190,38 @@
return attributes;
}
+static struct uac2_input_terminal_descriptor *
+ snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface,
+ int terminal_id)
+{
+ struct uac2_input_terminal_descriptor *term = NULL;
+
+ while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
+ ctrl_iface->extralen,
+ term, UAC_INPUT_TERMINAL))) {
+ if (term->bTerminalID == terminal_id)
+ return term;
+ }
+
+ return NULL;
+}
+
+static struct uac2_output_terminal_descriptor *
+ snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface,
+ int terminal_id)
+{
+ struct uac2_output_terminal_descriptor *term = NULL;
+
+ while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
+ ctrl_iface->extralen,
+ term, UAC_OUTPUT_TERMINAL))) {
+ if (term->bTerminalID == terminal_id)
+ return term;
+ }
+
+ return NULL;
+}
+
int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
{
struct usb_device *dev;
@@ -199,7 +231,7 @@
int i, altno, err, stream;
int format = 0, num_channels = 0;
struct audioformat *fp = NULL;
- int num, protocol;
+ int num, protocol, clock = 0;
struct uac_format_type_i_continuous_descriptor *fmt;
dev = chip->dev;
@@ -263,6 +295,8 @@
}
case UAC_VERSION_2: {
+ struct uac2_input_terminal_descriptor *input_term;
+ struct uac2_output_terminal_descriptor *output_term;
struct uac_as_header_descriptor_v2 *as =
snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
@@ -281,7 +315,25 @@
num_channels = as->bNrChannels;
format = le32_to_cpu(as->bmFormats);
- break;
+ /* lookup the terminal associated to this interface
+ * to extract the clock */
+ input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
+ as->bTerminalLink);
+ if (input_term) {
+ clock = input_term->bCSourceID;
+ break;
+ }
+
+ output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
+ as->bTerminalLink);
+ if (output_term) {
+ clock = output_term->bCSourceID;
+ break;
+ }
+
+ snd_printk(KERN_ERR "%d:%u:%d : bogus bTerminalLink %d\n",
+ dev->devnum, iface_no, altno, as->bTerminalLink);
+ continue;
}
default:
@@ -338,6 +390,7 @@
fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
* (fp->maxpacksize & 0x7ff);
fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no);
+ fp->clock = clock;
/* some quirks for attributes here */
@@ -374,6 +427,7 @@
if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream, alts) < 0) {
kfree(fp->rate_table);
kfree(fp);
+ fp = NULL;
continue;
}
diff --git a/sound/usb/format.c b/sound/usb/format.c
index fe29d61..30364ab 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -29,6 +29,7 @@
#include "quirks.h"
#include "helper.h"
#include "debug.h"
+#include "clock.h"
/*
* parse the audio format type I descriptor
@@ -205,6 +206,60 @@
}
/*
+ * Helper function to walk the array of sample rate triplets reported by
+ * the device. The problem is that we need to parse whole array first to
+ * get to know how many sample rates we have to expect.
+ * Then fp->rate_table can be allocated and filled.
+ */
+static int parse_uac2_sample_rate_range(struct audioformat *fp, int nr_triplets,
+ const unsigned char *data)
+{
+ int i, nr_rates = 0;
+
+ fp->rates = fp->rate_min = fp->rate_max = 0;
+
+ for (i = 0; i < nr_triplets; i++) {
+ int min = combine_quad(&data[2 + 12 * i]);
+ int max = combine_quad(&data[6 + 12 * i]);
+ int res = combine_quad(&data[10 + 12 * i]);
+ int rate;
+
+ if ((max < 0) || (min < 0) || (res < 0) || (max < min))
+ continue;
+
+ /*
+ * for ranges with res == 1, we announce a continuous sample
+ * rate range, and this function should return 0 for no further
+ * parsing.
+ */
+ if (res == 1) {
+ fp->rate_min = min;
+ fp->rate_max = max;
+ fp->rates = SNDRV_PCM_RATE_CONTINUOUS;
+ return 0;
+ }
+
+ for (rate = min; rate <= max; rate += res) {
+ if (fp->rate_table)
+ fp->rate_table[nr_rates] = rate;
+ if (!fp->rate_min || rate < fp->rate_min)
+ fp->rate_min = rate;
+ if (!fp->rate_max || rate > fp->rate_max)
+ fp->rate_max = rate;
+ fp->rates |= snd_pcm_rate_to_rate_bit(rate);
+
+ nr_rates++;
+
+ /* avoid endless loop */
+ if (res == 0)
+ break;
+ }
+ }
+
+ return nr_rates;
+}
+
+/*
* parse the format descriptor and stores the possible sample rates
* on the audioformat table (audio class v2).
*/
@@ -214,21 +269,30 @@
{
struct usb_device *dev = chip->dev;
unsigned char tmp[2], *data;
- int i, nr_rates, data_size, ret = 0;
+ int nr_triplets, data_size, ret = 0;
+ int clock = snd_usb_clock_find_source(chip, chip->ctrl_intf, fp->clock);
+
+ if (clock < 0) {
+ snd_printk(KERN_ERR "%s(): unable to find clock source (clock %d)\n",
+ __func__, clock);
+ goto err;
+ }
/* get the number of sample rates first by only fetching 2 bytes */
ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE,
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
- UAC2_CS_CONTROL_SAM_FREQ << 8, chip->clock_id << 8,
+ UAC2_CS_CONTROL_SAM_FREQ << 8,
+ snd_usb_ctrl_intf(chip) | (clock << 8),
tmp, sizeof(tmp), 1000);
if (ret < 0) {
- snd_printk(KERN_ERR "unable to retrieve number of sample rates\n");
+ snd_printk(KERN_ERR "%s(): unable to retrieve number of sample rates (clock %d)\n",
+ __func__, clock);
goto err;
}
- nr_rates = (tmp[1] << 8) | tmp[0];
- data_size = 2 + 12 * nr_rates;
+ nr_triplets = (tmp[1] << 8) | tmp[0];
+ data_size = 2 + 12 * nr_triplets;
data = kzalloc(data_size, GFP_KERNEL);
if (!data) {
ret = -ENOMEM;
@@ -237,36 +301,40 @@
/* now get the full information */
ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE,
- USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
- UAC2_CS_CONTROL_SAM_FREQ << 8, chip->clock_id << 8,
- data, data_size, 1000);
+ USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+ UAC2_CS_CONTROL_SAM_FREQ << 8,
+ snd_usb_ctrl_intf(chip) | (clock << 8),
+ data, data_size, 1000);
if (ret < 0) {
- snd_printk(KERN_ERR "unable to retrieve sample rate range\n");
+ snd_printk(KERN_ERR "%s(): unable to retrieve sample rate range (clock %d)\n",
+ __func__, clock);
ret = -EINVAL;
goto err_free;
}
- fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL);
+ /* Call the triplet parser, and make sure fp->rate_table is NULL.
+ * We just use the return value to know how many sample rates we
+ * will have to deal with. */
+ kfree(fp->rate_table);
+ fp->rate_table = NULL;
+ fp->nr_rates = parse_uac2_sample_rate_range(fp, nr_triplets, data);
+
+ if (fp->nr_rates == 0) {
+ /* SNDRV_PCM_RATE_CONTINUOUS */
+ ret = 0;
+ goto err_free;
+ }
+
+ fp->rate_table = kmalloc(sizeof(int) * fp->nr_rates, GFP_KERNEL);
if (!fp->rate_table) {
ret = -ENOMEM;
goto err_free;
}
- fp->nr_rates = 0;
- fp->rate_min = fp->rate_max = 0;
-
- for (i = 0; i < nr_rates; i++) {
- int rate = combine_quad(&data[2 + 12 * i]);
-
- fp->rate_table[fp->nr_rates] = rate;
- if (!fp->rate_min || rate < fp->rate_min)
- fp->rate_min = rate;
- if (!fp->rate_max || rate > fp->rate_max)
- fp->rate_max = rate;
- fp->rates |= snd_pcm_rate_to_rate_bit(rate);
- fp->nr_rates++;
- }
+ /* Call the triplet parser again, but this time, fp->rate_table is
+ * allocated, so the rates will be stored */
+ parse_uac2_sample_rate_range(fp, nr_triplets, data);
err_free:
kfree(data);
diff --git a/sound/usb/helper.h b/sound/usb/helper.h
index a6b0e51..09bd943 100644
--- a/sound/usb/helper.h
+++ b/sound/usb/helper.h
@@ -28,5 +28,9 @@
#define snd_usb_get_speed(dev) ((dev)->speed)
#endif
+static inline int snd_usb_ctrl_intf(struct snd_usb_audio *chip)
+{
+ return get_iface_desc(chip->ctrl_intf)->bInterfaceNumber;
+}
#endif /* __USBAUDIO_HELPER_H */
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 03ce971..6939d0f5 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -78,39 +78,6 @@
USB_MIXER_U16,
};
-enum {
- USB_PROC_UPDOWN = 1,
- USB_PROC_UPDOWN_SWITCH = 1,
- USB_PROC_UPDOWN_MODE_SEL = 2,
-
- USB_PROC_PROLOGIC = 2,
- USB_PROC_PROLOGIC_SWITCH = 1,
- USB_PROC_PROLOGIC_MODE_SEL = 2,
-
- USB_PROC_3DENH = 3,
- USB_PROC_3DENH_SWITCH = 1,
- USB_PROC_3DENH_SPACE = 2,
-
- USB_PROC_REVERB = 4,
- USB_PROC_REVERB_SWITCH = 1,
- USB_PROC_REVERB_LEVEL = 2,
- USB_PROC_REVERB_TIME = 3,
- USB_PROC_REVERB_DELAY = 4,
-
- USB_PROC_CHORUS = 5,
- USB_PROC_CHORUS_SWITCH = 1,
- USB_PROC_CHORUS_LEVEL = 2,
- USB_PROC_CHORUS_RATE = 3,
- USB_PROC_CHORUS_DEPTH = 4,
-
- USB_PROC_DCR = 6,
- USB_PROC_DCR_SWITCH = 1,
- USB_PROC_DCR_RATIO = 2,
- USB_PROC_DCR_MAX_AMP = 3,
- USB_PROC_DCR_THRESHOLD = 4,
- USB_PROC_DCR_ATTACK = 5,
- USB_PROC_DCR_RELEASE = 6,
-};
/*E-mu 0202(0404) eXtension Unit(XU) control*/
enum {
@@ -198,22 +165,24 @@
/*
* find an audio control unit with the given unit id
- * this doesn't return any clock related units, so they need to be handled elsewhere
*/
static void *find_audio_control_unit(struct mixer_build *state, unsigned char unit)
{
- unsigned char *p;
+ /* we just parse the header */
+ struct uac_feature_unit_descriptor *hdr = NULL;
- p = NULL;
- while ((p = snd_usb_find_desc(state->buffer, state->buflen, p,
- USB_DT_CS_INTERFACE)) != NULL) {
- if (p[0] >= 4 && p[2] >= UAC_INPUT_TERMINAL && p[2] <= UAC2_EXTENSION_UNIT_V2 && p[3] == unit)
- return p;
+ while ((hdr = snd_usb_find_desc(state->buffer, state->buflen, hdr,
+ USB_DT_CS_INTERFACE)) != NULL) {
+ if (hdr->bLength >= 4 &&
+ hdr->bDescriptorSubtype >= UAC_INPUT_TERMINAL &&
+ hdr->bDescriptorSubtype <= UAC2_SAMPLE_RATE_CONVERTER &&
+ hdr->bUnitID == unit)
+ return hdr;
}
+
return NULL;
}
-
/*
* copy a string with the given id
*/
@@ -328,27 +297,36 @@
static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
{
- unsigned char buf[14]; /* enough space for one range of 4 bytes */
+ unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */
unsigned char *val;
- int ret;
+ int ret, size;
__u8 bRequest;
- bRequest = (request == UAC_GET_CUR) ?
- UAC2_CS_CUR : UAC2_CS_RANGE;
+ if (request == UAC_GET_CUR) {
+ bRequest = UAC2_CS_CUR;
+ size = sizeof(__u16);
+ } else {
+ bRequest = UAC2_CS_RANGE;
+ size = sizeof(buf);
+ }
+
+ memset(buf, 0, sizeof(buf));
ret = snd_usb_ctl_msg(cval->mixer->chip->dev,
usb_rcvctrlpipe(cval->mixer->chip->dev, 0),
bRequest,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
validx, cval->mixer->ctrlif | (cval->id << 8),
- buf, sizeof(buf), 1000);
+ buf, size, 1000);
if (ret < 0) {
- snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
- request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type);
+ snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
+ request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type);
return ret;
}
+ /* FIXME: how should we handle multiple triplets here? */
+
switch (request) {
case UAC_GET_CUR:
val = buf;
@@ -462,6 +440,16 @@
int index, int value)
{
int err;
+ unsigned int read_only = (channel == 0) ?
+ cval->master_readonly :
+ cval->ch_readonly & (1 << (channel - 1));
+
+ if (read_only) {
+ snd_printdd(KERN_INFO "%s(): channel %d of control %d is read_only\n",
+ __func__, channel, cval->control);
+ return 0;
+ }
+
err = snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, (cval->control << 8) | channel,
value);
if (err < 0)
@@ -631,6 +619,7 @@
*/
static int check_input_term(struct mixer_build *state, int id, struct usb_audio_term *term)
{
+ int err;
void *p1;
memset(term, 0, sizeof(*term));
@@ -651,6 +640,11 @@
term->channels = d->bNrChannels;
term->chconfig = le32_to_cpu(d->bmChannelConfig);
term->name = d->iTerminal;
+
+ /* call recursively to get the clock selectors */
+ err = check_input_term(state, d->bCSourceID, term);
+ if (err < 0)
+ return err;
}
return 0;
case UAC_FEATURE_UNIT: {
@@ -667,7 +661,8 @@
term->name = uac_mixer_unit_iMixer(d);
return 0;
}
- case UAC_SELECTOR_UNIT: {
+ case UAC_SELECTOR_UNIT:
+ case UAC2_CLOCK_SELECTOR: {
struct uac_selector_unit_descriptor *d = p1;
/* call recursively to retrieve the channel info */
if (check_input_term(state, d->baSourceID[0], term) < 0)
@@ -690,6 +685,13 @@
term->name = uac_processing_unit_iProcessing(d, state->mixer->protocol);
return 0;
}
+ case UAC2_CLOCK_SOURCE: {
+ struct uac_clock_source_descriptor *d = p1;
+ term->type = d->bDescriptorSubtype << 16; /* virtual type */
+ term->id = id;
+ term->name = d->iClockSource;
+ return 0;
+ }
default:
return -ENODEV;
}
@@ -709,16 +711,20 @@
};
static struct usb_feature_control_info audio_feature_info[] = {
- { "Mute", USB_MIXER_INV_BOOLEAN },
- { "Volume", USB_MIXER_S16 },
+ { "Mute", USB_MIXER_INV_BOOLEAN },
+ { "Volume", USB_MIXER_S16 },
{ "Tone Control - Bass", USB_MIXER_S8 },
{ "Tone Control - Mid", USB_MIXER_S8 },
{ "Tone Control - Treble", USB_MIXER_S8 },
{ "Graphic Equalizer", USB_MIXER_S8 }, /* FIXME: not implemeted yet */
- { "Auto Gain Control", USB_MIXER_BOOLEAN },
- { "Delay Control", USB_MIXER_U16 },
- { "Bass Boost", USB_MIXER_BOOLEAN },
- { "Loudness", USB_MIXER_BOOLEAN },
+ { "Auto Gain Control", USB_MIXER_BOOLEAN },
+ { "Delay Control", USB_MIXER_U16 },
+ { "Bass Boost", USB_MIXER_BOOLEAN },
+ { "Loudness", USB_MIXER_BOOLEAN },
+ /* UAC2 specific */
+ { "Input Gain Control", USB_MIXER_U16 },
+ { "Input Gain Pad Control", USB_MIXER_BOOLEAN },
+ { "Phase Inverter Control", USB_MIXER_BOOLEAN },
};
@@ -958,7 +964,7 @@
static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
unsigned int ctl_mask, int control,
struct usb_audio_term *iterm, int unitid,
- int read_only)
+ int readonly_mask)
{
struct uac_feature_unit_descriptor *desc = raw_desc;
unsigned int len = 0;
@@ -970,7 +976,7 @@
control++; /* change from zero-based to 1-based value */
- if (control == UAC_GRAPHIC_EQUALIZER_CONTROL) {
+ if (control == UAC_FU_GRAPHIC_EQUALIZER) {
/* FIXME: not supported yet */
return;
}
@@ -989,20 +995,25 @@
cval->control = control;
cval->cmask = ctl_mask;
cval->val_type = audio_feature_info[control-1].type;
- if (ctl_mask == 0)
+ if (ctl_mask == 0) {
cval->channels = 1; /* master channel */
- else {
+ cval->master_readonly = readonly_mask;
+ } else {
int i, c = 0;
for (i = 0; i < 16; i++)
if (ctl_mask & (1 << i))
c++;
cval->channels = c;
+ cval->ch_readonly = readonly_mask;
}
/* get min/max values */
get_min_max(cval, 0);
- if (read_only)
+ /* if all channels in the mask are marked read-only, make the control
+ * read-only. set_cur_mix_value() will check the mask again and won't
+ * issue write commands to read-only channels. */
+ if (cval->channels == readonly_mask)
kctl = snd_ctl_new1(&usb_feature_unit_ctl_ro, cval);
else
kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval);
@@ -1021,8 +1032,8 @@
kctl->id.name, sizeof(kctl->id.name));
switch (control) {
- case UAC_MUTE_CONTROL:
- case UAC_VOLUME_CONTROL:
+ case UAC_FU_MUTE:
+ case UAC_FU_VOLUME:
/* determine the control name. the rule is:
* - if a name id is given in descriptor, use it.
* - if the connected input can be determined, then use the name
@@ -1049,9 +1060,9 @@
len = append_ctl_name(kctl, " Playback");
}
}
- append_ctl_name(kctl, control == UAC_MUTE_CONTROL ?
+ append_ctl_name(kctl, control == UAC_FU_MUTE ?
" Switch" : " Volume");
- if (control == UAC_VOLUME_CONTROL) {
+ if (control == UAC_FU_VOLUME) {
kctl->tlv.c = mixer_vol_tlv;
kctl->vd[0].access |=
SNDRV_CTL_ELEM_ACCESS_TLV_READ |
@@ -1150,7 +1161,7 @@
snd_printk(KERN_INFO
"usbmixer: master volume quirk for PCM2702 chip\n");
/* disable non-functional volume control */
- master_bits &= ~UAC_FU_VOLUME;
+ master_bits &= ~UAC_CONTROL_BIT(UAC_FU_VOLUME);
break;
}
if (channels > 0)
@@ -1188,19 +1199,22 @@
for (j = 0; j < channels; j++) {
unsigned int mask = snd_usb_combine_bytes(bmaControls + csize * (j+1), csize);
- if (mask & (1 << (i * 2))) {
+ if (uac2_control_is_readable(mask, i)) {
ch_bits |= (1 << j);
- if (~mask & (1 << ((i * 2) + 1)))
+ if (!uac2_control_is_writeable(mask, i))
ch_read_only |= (1 << j);
}
}
- /* FIXME: the whole unit is read-only if any of the channels is marked read-only */
+ /* NOTE: build_feature_ctl() will mark the control read-only if all channels
+ * are marked read-only in the descriptors. Otherwise, the control will be
+ * reported as writeable, but the driver will not actually issue a write
+ * command for read-only channels */
if (ch_bits & 1) /* the first channel must be set (for ease of programming) */
- build_feature_ctl(state, _ftr, ch_bits, i, &iterm, unitid, !!ch_read_only);
- if (master_bits & (1 << i * 2))
+ build_feature_ctl(state, _ftr, ch_bits, i, &iterm, unitid, ch_read_only);
+ if (uac2_control_is_readable(master_bits, i))
build_feature_ctl(state, _ftr, 0, i, &iterm, unitid,
- ~master_bits & (1 << ((i * 2) + 1)));
+ !uac2_control_is_writeable(master_bits, i));
}
}
@@ -1392,51 +1406,51 @@
};
static struct procunit_value_info updown_proc_info[] = {
- { USB_PROC_UPDOWN_SWITCH, "Switch", USB_MIXER_BOOLEAN },
- { USB_PROC_UPDOWN_MODE_SEL, "Mode Select", USB_MIXER_U8, 1 },
+ { UAC_UD_ENABLE, "Switch", USB_MIXER_BOOLEAN },
+ { UAC_UD_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 },
{ 0 }
};
static struct procunit_value_info prologic_proc_info[] = {
- { USB_PROC_PROLOGIC_SWITCH, "Switch", USB_MIXER_BOOLEAN },
- { USB_PROC_PROLOGIC_MODE_SEL, "Mode Select", USB_MIXER_U8, 1 },
+ { UAC_DP_ENABLE, "Switch", USB_MIXER_BOOLEAN },
+ { UAC_DP_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 },
{ 0 }
};
static struct procunit_value_info threed_enh_proc_info[] = {
- { USB_PROC_3DENH_SWITCH, "Switch", USB_MIXER_BOOLEAN },
- { USB_PROC_3DENH_SPACE, "Spaciousness", USB_MIXER_U8 },
+ { UAC_3D_ENABLE, "Switch", USB_MIXER_BOOLEAN },
+ { UAC_3D_SPACE, "Spaciousness", USB_MIXER_U8 },
{ 0 }
};
static struct procunit_value_info reverb_proc_info[] = {
- { USB_PROC_REVERB_SWITCH, "Switch", USB_MIXER_BOOLEAN },
- { USB_PROC_REVERB_LEVEL, "Level", USB_MIXER_U8 },
- { USB_PROC_REVERB_TIME, "Time", USB_MIXER_U16 },
- { USB_PROC_REVERB_DELAY, "Delay", USB_MIXER_U8 },
+ { UAC_REVERB_ENABLE, "Switch", USB_MIXER_BOOLEAN },
+ { UAC_REVERB_LEVEL, "Level", USB_MIXER_U8 },
+ { UAC_REVERB_TIME, "Time", USB_MIXER_U16 },
+ { UAC_REVERB_FEEDBACK, "Feedback", USB_MIXER_U8 },
{ 0 }
};
static struct procunit_value_info chorus_proc_info[] = {
- { USB_PROC_CHORUS_SWITCH, "Switch", USB_MIXER_BOOLEAN },
- { USB_PROC_CHORUS_LEVEL, "Level", USB_MIXER_U8 },
- { USB_PROC_CHORUS_RATE, "Rate", USB_MIXER_U16 },
- { USB_PROC_CHORUS_DEPTH, "Depth", USB_MIXER_U16 },
+ { UAC_CHORUS_ENABLE, "Switch", USB_MIXER_BOOLEAN },
+ { UAC_CHORUS_LEVEL, "Level", USB_MIXER_U8 },
+ { UAC_CHORUS_RATE, "Rate", USB_MIXER_U16 },
+ { UAC_CHORUS_DEPTH, "Depth", USB_MIXER_U16 },
{ 0 }
};
static struct procunit_value_info dcr_proc_info[] = {
- { USB_PROC_DCR_SWITCH, "Switch", USB_MIXER_BOOLEAN },
- { USB_PROC_DCR_RATIO, "Ratio", USB_MIXER_U16 },
- { USB_PROC_DCR_MAX_AMP, "Max Amp", USB_MIXER_S16 },
- { USB_PROC_DCR_THRESHOLD, "Threshold", USB_MIXER_S16 },
- { USB_PROC_DCR_ATTACK, "Attack Time", USB_MIXER_U16 },
- { USB_PROC_DCR_RELEASE, "Release Time", USB_MIXER_U16 },
+ { UAC_DCR_ENABLE, "Switch", USB_MIXER_BOOLEAN },
+ { UAC_DCR_RATE, "Ratio", USB_MIXER_U16 },
+ { UAC_DCR_MAXAMPL, "Max Amp", USB_MIXER_S16 },
+ { UAC_DCR_THRESHOLD, "Threshold", USB_MIXER_S16 },
+ { UAC_DCR_ATTACK_TIME, "Attack Time", USB_MIXER_U16 },
+ { UAC_DCR_RELEASE_TIME, "Release Time", USB_MIXER_U16 },
{ 0 }
};
static struct procunit_info procunits[] = {
- { USB_PROC_UPDOWN, "Up Down", updown_proc_info },
- { USB_PROC_PROLOGIC, "Dolby Prologic", prologic_proc_info },
- { USB_PROC_3DENH, "3D Stereo Extender", threed_enh_proc_info },
- { USB_PROC_REVERB, "Reverb", reverb_proc_info },
- { USB_PROC_CHORUS, "Chorus", chorus_proc_info },
- { USB_PROC_DCR, "DCR", dcr_proc_info },
+ { UAC_PROCESS_UP_DOWNMIX, "Up Down", updown_proc_info },
+ { UAC_PROCESS_DOLBY_PROLOGIC, "Dolby Prologic", prologic_proc_info },
+ { UAC_PROCESS_STEREO_EXTENDER, "3D Stereo Extender", threed_enh_proc_info },
+ { UAC_PROCESS_REVERB, "Reverb", reverb_proc_info },
+ { UAC_PROCESS_CHORUS, "Chorus", chorus_proc_info },
+ { UAC_PROCESS_DYN_RANGE_COMP, "DCR", dcr_proc_info },
{ 0 },
};
/*
@@ -1524,7 +1538,7 @@
cval->channels = 1;
/* get min/max values */
- if (type == USB_PROC_UPDOWN && cval->control == USB_PROC_UPDOWN_MODE_SEL) {
+ if (type == UAC_PROCESS_UP_DOWNMIX && cval->control == UAC_UD_MODE_SELECT) {
__u8 *control_spec = uac_processing_unit_specific(desc, state->mixer->protocol);
/* FIXME: hard-coded */
cval->min = 1;
@@ -1619,7 +1633,7 @@
struct usb_mixer_elem_info *cval = kcontrol->private_data;
int val, err;
- err = get_cur_ctl_value(cval, 0, &val);
+ err = get_cur_ctl_value(cval, cval->control << 8, &val);
if (err < 0) {
if (cval->mixer->ignore_ctl_error) {
ucontrol->value.enumerated.item[0] = 0;
@@ -1638,7 +1652,7 @@
struct usb_mixer_elem_info *cval = kcontrol->private_data;
int val, oval, err;
- err = get_cur_ctl_value(cval, 0, &oval);
+ err = get_cur_ctl_value(cval, cval->control << 8, &oval);
if (err < 0) {
if (cval->mixer->ignore_ctl_error)
return 0;
@@ -1647,7 +1661,7 @@
val = ucontrol->value.enumerated.item[0];
val = get_abs_value(cval, val);
if (val != oval) {
- set_cur_ctl_value(cval, 0, val);
+ set_cur_ctl_value(cval, cval->control << 8, val);
return 1;
}
return 0;
@@ -1729,6 +1743,11 @@
cval->res = 1;
cval->initialized = 1;
+ if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR)
+ cval->control = UAC2_CX_CLOCK_SELECTOR;
+ else
+ cval->control = 0;
+
namelist = kmalloc(sizeof(char *) * desc->bNrInPins, GFP_KERNEL);
if (! namelist) {
snd_printk(KERN_ERR "cannot malloc\n");
@@ -1778,7 +1797,9 @@
if (! len)
strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name));
- if ((state->oterm.type & 0xff00) == 0x0100)
+ if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR)
+ append_ctl_name(kctl, " Clock Source");
+ else if ((state->oterm.type & 0xff00) == 0x0100)
append_ctl_name(kctl, " Capture Source");
else
append_ctl_name(kctl, " Playback Source");
@@ -1812,10 +1833,12 @@
switch (p1[2]) {
case UAC_INPUT_TERMINAL:
+ case UAC2_CLOCK_SOURCE:
return 0; /* NOP */
case UAC_MIXER_UNIT:
return parse_audio_mixer_unit(state, unitid, p1);
case UAC_SELECTOR_UNIT:
+ case UAC2_CLOCK_SELECTOR:
return parse_audio_selector_unit(state, unitid, p1);
case UAC_FEATURE_UNIT:
return parse_audio_feature_unit(state, unitid, p1);
@@ -1912,6 +1935,11 @@
err = parse_audio_unit(&state, desc->bSourceID);
if (err < 0)
return err;
+
+ /* for UAC2, use the same approach to also add the clock selectors */
+ err = parse_audio_unit(&state, desc->bCSourceID);
+ if (err < 0)
+ return err;
}
}
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
index 1301238..a7cf100 100644
--- a/sound/usb/mixer.h
+++ b/sound/usb/mixer.h
@@ -34,6 +34,8 @@
unsigned int id;
unsigned int control; /* CS or ICN (high byte) */
unsigned int cmask; /* channel mask bitmap: 0 = master */
+ unsigned int ch_readonly;
+ unsigned int master_readonly;
int channels;
int val_type;
int min, max, res;
diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c
index d93fc89..f1324c4 100644
--- a/sound/usb/mixer_maps.c
+++ b/sound/usb/mixer_maps.c
@@ -85,8 +85,8 @@
/* 16: MU (w/o controls) */
{ 17, NULL, 1 }, /* DISABLED: PU-switch (any effect?) */
{ 17, "Channel Routing", 2 }, /* PU: mode select */
- { 18, "Tone Control - Bass", UAC_BASS_CONTROL }, /* FU */
- { 18, "Tone Control - Treble", UAC_TREBLE_CONTROL }, /* FU */
+ { 18, "Tone Control - Bass", UAC_FU_BASS }, /* FU */
+ { 18, "Tone Control - Treble", UAC_FU_TREBLE }, /* FU */
{ 18, "Master Playback" }, /* FU; others */
/* 19: OT speaker */
/* 20: OT headphone */
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 056587d..4568298 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -31,6 +31,7 @@
#include "urb.h"
#include "helper.h"
#include "pcm.h"
+#include "clock.h"
/*
* return the current pcm pointer. just based on the hwptr_done value.
@@ -181,103 +182,6 @@
return -EINVAL;
}
-static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
- struct usb_host_interface *alts,
- struct audioformat *fmt, int rate)
-{
- struct usb_device *dev = chip->dev;
- unsigned int ep;
- unsigned char data[3];
- int err, crate;
-
- ep = get_endpoint(alts, 0)->bEndpointAddress;
- /* if endpoint doesn't have sampling rate control, bail out */
- if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE)) {
- snd_printk(KERN_WARNING "%d:%d:%d: endpoint lacks sample rate attribute bit, cannot set.\n",
- dev->devnum, iface, fmt->altsetting);
- return 0;
- }
-
- data[0] = rate;
- data[1] = rate >> 8;
- data[2] = rate >> 16;
- if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
- USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
- UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
- data, sizeof(data), 1000)) < 0) {
- snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n",
- dev->devnum, iface, fmt->altsetting, rate, ep);
- return err;
- }
- if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,
- USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
- UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
- data, sizeof(data), 1000)) < 0) {
- snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n",
- dev->devnum, iface, fmt->altsetting, ep);
- return 0; /* some devices don't support reading */
- }
- crate = data[0] | (data[1] << 8) | (data[2] << 16);
- if (crate != rate) {
- snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate);
- // runtime->rate = crate;
- }
-
- return 0;
-}
-
-static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
- struct usb_host_interface *alts,
- struct audioformat *fmt, int rate)
-{
- struct usb_device *dev = chip->dev;
- unsigned char data[4];
- int err, crate;
-
- data[0] = rate;
- data[1] = rate >> 8;
- data[2] = rate >> 16;
- data[3] = rate >> 24;
- if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
- USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
- UAC2_CS_CONTROL_SAM_FREQ << 8, chip->clock_id << 8,
- data, sizeof(data), 1000)) < 0) {
- snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2)\n",
- dev->devnum, iface, fmt->altsetting, rate);
- return err;
- }
- if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
- USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
- UAC2_CS_CONTROL_SAM_FREQ << 8, chip->clock_id << 8,
- data, sizeof(data), 1000)) < 0) {
- snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n",
- dev->devnum, iface, fmt->altsetting);
- return err;
- }
- crate = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
- if (crate != rate)
- snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate);
-
- return 0;
-}
-
-int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
- struct usb_host_interface *alts,
- struct audioformat *fmt, int rate)
-{
- struct usb_interface_descriptor *altsd = get_iface_desc(alts);
-
- switch (altsd->bInterfaceProtocol) {
- case UAC_VERSION_1:
- return set_sample_rate_v1(chip, iface, alts, fmt, rate);
-
- case UAC_VERSION_2:
- return set_sample_rate_v2(chip, iface, alts, fmt, rate);
- }
-
- return -EINVAL;
-}
-
/*
* find a matching format and set up the interface
*/
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 06ebf24..24d3319 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -40,9 +40,6 @@
int num_interfaces;
int num_suspended_intf;
- /* for audio class v2 */
- int clock_id;
-
struct list_head pcm_list; /* list of pcm streams */
int pcm_devs;
@@ -53,6 +50,8 @@
int setup; /* from the 'device_setup' module param */
int nrpacks; /* from the 'nrpacks' module param */
int async_unlink; /* from the 'async_unlink' module param */
+
+ struct usb_host_interface *ctrl_intf; /* the audio control interface */
};
/*
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 44a47e1..9989072 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -43,8 +43,10 @@
if (session == NULL)
return -1;
- if (with_hits)
+ if (with_hits) {
+ symbol_conf.full_paths = true;
perf_session__process_events(session, &build_id__mark_dso_hit_ops);
+ }
perf_session__fprintf_dsos_buildid(session, stdout, with_hits);
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 9bc8905..711745f 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -193,7 +193,7 @@
static void sig_atexit(void)
{
- if (child_pid != -1)
+ if (child_pid > 0)
kill(child_pid, SIGTERM);
if (signr == -1)
@@ -503,7 +503,6 @@
{
int i, counter;
struct stat st;
- pid_t pid = 0;
int flags;
int err;
unsigned long waking = 0;
@@ -572,7 +571,7 @@
if (forks) {
child_pid = fork();
- if (pid < 0) {
+ if (child_pid < 0) {
perror("failed to fork");
exit(-1);
}
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index f67bce2..55f3b5d 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1645,6 +1645,7 @@
.sample = process_sample_event,
.comm = event__process_comm,
.lost = event__process_lost,
+ .fork = event__process_task,
.ordered_samples = true,
};
diff --git a/tools/perf/scripts/python/check-perf-trace.py b/tools/perf/scripts/python/check-perf-trace.py
index 964d934..d9f7893 100644
--- a/tools/perf/scripts/python/check-perf-trace.py
+++ b/tools/perf/scripts/python/check-perf-trace.py
@@ -51,8 +51,7 @@
flag_str("kmem__kmalloc", "gfp_flags", gfp_flags)),
-def trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs,
- common_pid, common_comm):
+def trace_unhandled(event_name, context, event_fields_dict):
try:
unhandled[event_name] += 1
except TypeError:
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 50771b5..2fbf6a4 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -370,9 +370,9 @@
int event__process_comm(event_t *self, struct perf_session *session)
{
- struct thread *thread = perf_session__findnew(session, self->comm.pid);
+ struct thread *thread = perf_session__findnew(session, self->comm.tid);
- dump_printf(": %s:%d\n", self->comm.comm, self->comm.pid);
+ dump_printf(": %s:%d\n", self->comm.comm, self->comm.tid);
if (thread == NULL || thread__set_comm_adjust(thread, self->comm.comm)) {
dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
@@ -532,19 +532,16 @@
int event__process_task(event_t *self, struct perf_session *session)
{
- struct thread *thread = perf_session__findnew(session, self->fork.pid);
- struct thread *parent = perf_session__findnew(session, self->fork.ppid);
+ struct thread *thread = perf_session__findnew(session, self->fork.tid);
+ struct thread *parent = perf_session__findnew(session, self->fork.ptid);
dump_printf("(%d:%d):(%d:%d)\n", self->fork.pid, self->fork.tid,
self->fork.ppid, self->fork.ptid);
- /*
- * A thread clone will have the same PID for both parent and child.
- */
- if (thread == parent)
- return 0;
- if (self->header.type == PERF_RECORD_EXIT)
+ if (self->header.type == PERF_RECORD_EXIT) {
+ perf_session__remove_thread(session, thread);
return 0;
+ }
if (thread == NULL || parent == NULL ||
thread__fork(thread, parent) < 0) {
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index cbf7eae..07f89b66 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -965,7 +965,7 @@
* Parse hexa addresses followed by ':'
*/
line_ip = strtoull(tmp, &tmp2, 16);
- if (*tmp2 != ':')
+ if (*tmp2 != ':' || tmp == tmp2)
line_ip = -1;
}
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c
index cf182ca..7537ca1 100644
--- a/tools/perf/util/newt.c
+++ b/tools/perf/util/newt.c
@@ -43,6 +43,9 @@
if (self != NULL) {
int cols;
+
+ if (use_browser <= 0)
+ return self;
newtGetScreenSize(&cols, NULL);
cols -= 4;
newtCenteredWindow(cols, 1, title);
@@ -67,14 +70,22 @@
void ui_progress__update(struct ui_progress *self, u64 curr)
{
+ /*
+ * FIXME: We should have a per UI backend way of showing progress,
+ * stdio will just show a percentage as NN%, etc.
+ */
+ if (use_browser <= 0)
+ return;
newtScaleSet(self->scale, curr);
newtRefresh();
}
void ui_progress__delete(struct ui_progress *self)
{
- newtFormDestroy(self->form);
- newtPopWindow();
+ if (use_browser > 0) {
+ newtFormDestroy(self->form);
+ newtPopWindow();
+ }
free(self);
}
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 81f39ca..33a6325 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -208,7 +208,7 @@
int size __unused,
unsigned long long nsecs, char *comm)
{
- PyObject *handler, *retval, *context, *t, *obj;
+ PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;
static char handler_name[256];
struct format_field *field;
unsigned long long val;
@@ -232,6 +232,14 @@
sprintf(handler_name, "%s__%s", event->system, event->name);
+ handler = PyDict_GetItemString(main_dict, handler_name);
+ if (handler && !PyCallable_Check(handler))
+ handler = NULL;
+ if (!handler) {
+ dict = PyDict_New();
+ if (!dict)
+ Py_FatalError("couldn't create Python dict");
+ }
s = nsecs / NSECS_PER_SEC;
ns = nsecs - s * NSECS_PER_SEC;
@@ -242,12 +250,20 @@
PyTuple_SetItem(t, n++, PyString_FromString(handler_name));
PyTuple_SetItem(t, n++,
PyCObject_FromVoidPtr(scripting_context, NULL));
- PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
- PyTuple_SetItem(t, n++, PyInt_FromLong(s));
- PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
- PyTuple_SetItem(t, n++, PyInt_FromLong(pid));
- PyTuple_SetItem(t, n++, PyString_FromString(comm));
+ if (handler) {
+ PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
+ PyTuple_SetItem(t, n++, PyInt_FromLong(s));
+ PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
+ PyTuple_SetItem(t, n++, PyInt_FromLong(pid));
+ PyTuple_SetItem(t, n++, PyString_FromString(comm));
+ } else {
+ PyDict_SetItemString(dict, "common_cpu", PyInt_FromLong(cpu));
+ PyDict_SetItemString(dict, "common_s", PyInt_FromLong(s));
+ PyDict_SetItemString(dict, "common_ns", PyInt_FromLong(ns));
+ PyDict_SetItemString(dict, "common_pid", PyInt_FromLong(pid));
+ PyDict_SetItemString(dict, "common_comm", PyString_FromString(comm));
+ }
for (field = event->format.fields; field; field = field->next) {
if (field->flags & FIELD_IS_STRING) {
int offset;
@@ -272,27 +288,31 @@
obj = PyLong_FromUnsignedLongLong(val);
}
}
- PyTuple_SetItem(t, n++, obj);
+ if (handler)
+ PyTuple_SetItem(t, n++, obj);
+ else
+ PyDict_SetItemString(dict, field->name, obj);
+
}
+ if (!handler)
+ PyTuple_SetItem(t, n++, dict);
if (_PyTuple_Resize(&t, n) == -1)
Py_FatalError("error resizing Python tuple");
- handler = PyDict_GetItemString(main_dict, handler_name);
- if (handler && PyCallable_Check(handler)) {
+ if (handler) {
retval = PyObject_CallObject(handler, t);
if (retval == NULL)
handler_call_die(handler_name);
} else {
handler = PyDict_GetItemString(main_dict, "trace_unhandled");
if (handler && PyCallable_Check(handler)) {
- if (_PyTuple_Resize(&t, N_COMMON_FIELDS) == -1)
- Py_FatalError("error resizing Python tuple");
retval = PyObject_CallObject(handler, t);
if (retval == NULL)
handler_call_die("trace_unhandled");
}
+ Py_DECREF(dict);
}
Py_DECREF(t);
@@ -548,12 +568,10 @@
}
fprintf(ofp, "def trace_unhandled(event_name, context, "
- "common_cpu, common_secs, common_nsecs,\n\t\t"
- "common_pid, common_comm):\n");
+ "event_fields_dict):\n");
- fprintf(ofp, "\t\tprint_header(event_name, common_cpu, "
- "common_secs, common_nsecs,\n\t\tcommon_pid, "
- "common_comm)\n\n");
+ fprintf(ofp, "\t\tprint ' '.join(['%%s=%%s'%%(k,str(v))"
+ "for k,v in sorted(event_fields_dict.items())])\n\n");
fprintf(ofp, "def print_header("
"event_name, cpu, secs, nsecs, pid, comm):\n"
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 8f83a18..c422cd6 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -90,6 +90,7 @@
memcpy(self->filename, filename, len);
self->threads = RB_ROOT;
+ INIT_LIST_HEAD(&self->dead_threads);
self->hists_tree = RB_ROOT;
self->last_match = NULL;
self->mmap_window = 32;
@@ -131,6 +132,16 @@
free(self);
}
+void perf_session__remove_thread(struct perf_session *self, struct thread *th)
+{
+ rb_erase(&th->rb_node, &self->threads);
+ /*
+ * We may have references to this thread, for instance in some hist_entry
+ * instances, so just move them to a separate list.
+ */
+ list_add_tail(&th->node, &self->dead_threads);
+}
+
static bool symbol__match_parent_regex(struct symbol *sym)
{
if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 55c6881..9fa0fc2 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -26,6 +26,7 @@
unsigned long size;
unsigned long mmap_window;
struct rb_root threads;
+ struct list_head dead_threads;
struct thread *last_match;
struct machine host_machine;
struct rb_root machines;
@@ -99,6 +100,7 @@
int do_read(int fd, void *buf, size_t size);
void perf_session__update_sample_type(struct perf_session *self);
+void perf_session__remove_thread(struct perf_session *self, struct thread *th);
static inline
struct machine *perf_session__find_host_machine(struct perf_session *self)
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 7fd6b15..b63e571 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1745,7 +1745,12 @@
if (symbol_conf.vmlinux_name != NULL) {
err = dso__load_vmlinux(self, map,
symbol_conf.vmlinux_name, filter);
- goto out_try_fixup;
+ if (err > 0) {
+ dso__set_long_name(self,
+ strdup(symbol_conf.vmlinux_name));
+ goto out_fixup;
+ }
+ return err;
}
if (vmlinux_path != NULL) {
@@ -1806,7 +1811,6 @@
pr_debug("Using %s for symbols\n", kallsyms_filename);
free(kallsyms_allocated_filename);
-out_try_fixup:
if (err > 0) {
out_fixup:
if (kallsyms_filename != NULL)
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 1dfd9ff..ee6bbcf 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -6,7 +6,10 @@
#include "symbol.h"
struct thread {
- struct rb_node rb_node;
+ union {
+ struct rb_node rb_node;
+ struct list_head node;
+ };
struct map_groups mg;
pid_t pid;
char shortname[3];
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index 7c79c1d..3500dee 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -192,12 +192,13 @@
int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
{
- u32 old_irr = ioapic->irr;
+ u32 old_irr;
u32 mask = 1 << irq;
union kvm_ioapic_redirect_entry entry;
int ret = 1;
spin_lock(&ioapic->lock);
+ old_irr = ioapic->irr;
if (irq >= 0 && irq < IOAPIC_NUM_PINS) {
entry = ioapic->redirtbl[irq];
level ^= entry.fields.polarity;
diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c
index d2f06be..96048ee 100644
--- a/virt/kvm/iommu.c
+++ b/virt/kvm/iommu.c
@@ -271,7 +271,7 @@
pfn = phys >> PAGE_SHIFT;
/* Unmap address from IO address space */
- order = iommu_unmap(domain, gfn_to_gpa(gfn), PAGE_SIZE);
+ order = iommu_unmap(domain, gfn_to_gpa(gfn), 0);
unmap_pages = 1ULL << order;
/* Unpin all pages we just unmapped to not leak any memory */