Intel HD Graphics: Difference between revisions

→‎See also: update PRM link
[unchecked revision][unchecked revision]
No edit summary
(→‎See also: update PRM link)
 
(8 intermediate revisions by 3 users not shown)
Line 7:
== Experimenting with the device ==
 
There are various tools available to study the behavior of the graphics device for simpler tasks in order to gain an understanding of how something is done. One way to do so is to use Intel's graphics debugging utilities (The intel-gpu-tools package), which allow reading and writing to the device registers from the terminal. This can be very useful, for instance, this method proved invaluable when studying the GMBUS. The same can be done using GRUB2’s built in terminal by obtaining the MMIO base address using lspci and then using the read/write commands (read_byte/read_word/read_dword and write_byte/write_word/write_dword) to perform the associated operation on the desired register.
 
 
== Register Locations and Definitions ==
Line 18 ⟶ 17:
 
Some additional reading is highly recommended before tackling graphics/display drivers which will help clarify a lot of the designs and terminology used in the official PRMs. Understanding the following is recommended:
* EDID
* I2C
* DisplayPort
* Intel Integrated graphics Programming Reference Manuals (PRMs)
* OpenGL 4.0+/Vulkan/DirectX 9+: This is only really necessary if you intend to implement 3d acceleration. Understanding how the graphics pipeline functions and is structured at a higher level will help with understanding the hardware level structure exposed the graphics chipset.
 
 
Line 46 ⟶ 45:
== GMBUS registers and the EDID ==
 
The GMBUS or Graphics Management Bus is an i2cI2C compatible protocol used to communicate with the attached displays to obtain their information such as the EDID. At the moment it is unclear if thisThis method cancannot be used to read the EDID of a [[DisplayPort]] device, as they utilize I2C overinstead the DisplayPort AUX channelCH forshould thisbe kind of communicationused.
 
To obtain the EDID for a device, we want to read 0x80 bytes from the I2C device index 0 of the desired device from an offset of 0x50.
Line 53 ⟶ 52:
 
 
void igfx_gmbus_reset(igfx_dev_state_t *driver)
== Display pipeline structure ==
{
igfx_write32(driver, driver->display_mmio_base + IGFX_GMBUS1, 0);
igfx_gmbus_enable_writeprot(driver);
igfx_gmbus_disable_writeprot(driver);
}
void igfx_gmbus_wait(igfx_dev_state_t *driver)
{
while (!(igfx_read32(driver, driver->display_mmio_base + IGFX_GMBUS2) & (1 << 11)))
;
}
void igfx_gmbus_stoptransaction(igfx_dev_state_t *driver)
{
igfx_write32(driver, driver->display_mmio_base + IGFX_GMBUS1, (1 << 30) | (1 << 27));
}
void igfx_gmbus_read(igfx_dev_state_t *driver, uint32_t disp_idx, uint8_t offset,
uint16_t sz, uint8_t *buf)
{
uint32_t gmbus0_val = 0;
uint32_t gmbus1_val = 0;
if (driver->device->arch == IGFX_CHERRYTRAIL)
{
if (disp_idx == 0)
gmbus0_val = 3;
}
gmbus1_val = (1 << 30) /*SW Ready*/ | (1 << 25) /*WAIT*/ |
(1 << 26) /*INDEX*/ | (sz & 511) << 16 | ((offset & 127) << 1) |
1 /*READ*/;
igfx_gmbus_reset(driver);
igfx_write32(driver, driver->display_mmio_base + IGFX_GMBUS0, gmbus0_val);
igfx_write32(driver, driver->display_mmio_base + IGFX_GMBUS1, gmbus1_val);
for (int i = 0; i < sz; i += 4)
{
igfx_gmbus_wait(driver);
uint32_t bytes = igfx_read32(driver, driver->display_mmio_base + IGFX_GMBUS3);
buf[i] = bytes & 0xFF;
if (sz > i + 1)
buf[i + 1] = (bytes >> 8) & 0xFF;
if (sz > i + 2)
buf[i + 2] = (bytes >> 16) & 0xFF;
if (sz > i + 3)
buf[i + 3] = (bytes >> 24) & 0xFF;
}
igfx_gmbus_stoptransaction(driver);
print_hexdump(buf, sz);
}
 
=== Getting the EDID from a [[DisplayPort]] device ===
 
To communicate with a [[DisplayPort]] device you'll need to use the following registers:
== Display Pipes ==
 
{| class="wikitable"
|-
! Register
! Description
|-
| DDI_AUX_CTL
| rowspan=2 | A register to initiate AUX CH requests
|-
| DP_AUX_CTL
|-
| DDI_AUX_DATA
| rowspan=2 | A set of 5 registers to send up to 20 bytes of data
|-
| DP_AUX_DATA
|-
| SRD_AUX_CTL
| A register that must be disabled if using the DDI_AUX registers
|-
|}
 
Refer to the Intel programming manuals for the register's addresses and potential errata.
== Display FDI ==
 
To send a request, first copy the AUX CH packet to the data registers starting with the high byte of the first register. Then initiate a request by setting the message length and the send_busy bit. Wait for either the done bit or any of the error bits to be set, then read the message length and the appropriate amount of data from the data registers.
 
Note that all the other bits in the CTL registers should be preserved, so load the registers before toggling any bits.
== Display planes ==
 
=== Display pipeline structure ===
 
 
=== Display Pipes ===
 
 
=== Display FDI ===
 
 
=== Display planes ===
 
Three types of display planes are available for each pipe, namely:
Line 75 ⟶ 162:
 
As the name implies, the cursor plane provides hardware accelerated cursor drawing. Similarly, the video/sprite plane provides a second source which can be drawn on top of the display plane, its purpose is to allow for efficient use of the video decoding hardware by allowing the decoded data to be directly drawn to the window.
 
 
== Simple mode set sequence ==
Line 81 ⟶ 167:
A simple mode set sequence can be used with the default/built-in display, assuming that the boot firmware has configured the display timings correctly. If not, it is necessary to perform a full mode set operation involving a display power cycle.
 
As this is going to rely on have displays already configured by the firmware, the first step is to figure out the mapping between ports and pipes and their status.
The steps are as follows:
 
This info is based on the intel_reg_dumper utility's output for integrated graphics for Haswell:
 
Ports:
There are 5 ports: A,B,C,D,E
These represent connections to displays.
The EDP port is always port A
The important registers here are:
PORT_CLK_SEL_[A-E]
DP_TP_CTL_[A-E]
DDI_BUF_CTL_A[A-E]
Pipes:
There are 3 general pipes A,B,C and 1 'specialized' EDP pipe that actually maps to Pipe A. Additionally, the EDP pipe (and DDI A) can only run in DP single stream (SST) mode.
Pipes handle display timings/resolution settings, with the following registers:
 
SFUSE_STRAP : This controls overall display capability (can disable all display output - forcing the use of external graphics), VGA port capability (can disable the physical VGA port) and the physical presence of ports on the device (regardless of if the port has something plugged in).
 
PIPE_DDI_FUNC_CTL_[A-C,EDP] : Used to control how the system 'talks' to the device (HDMI/DisplayPort SST/DisplayPort MST), bits per channel, VSync and HSync polarities (from EDID)
WM_PIPE_[A-C] : These control when the controller generates memory accesses for pixels, the values depend on the timing information as obtained from the EDID, the exact calculation process is described in the Display Watermark section of the PRMs.
WM_LP{1-3]: Configures the memory access timings for low power mode, the associated WM_LINETIME_[A-C] must be programmed before enabling one of these.
WM_LINETIME_[A-C]: Configures the line timings for low power mode based on the horizontal resolution
 
PIPE_SRCSZ_[A-C]: Contains the horizontal and vertical pixel width of the output.
PIPE_CONF_[A-C/EDP]: Enable/disable the pipe and some features
 
These registers are all based on the desired resolution, and are fairly well documented in the PRM, they rely on the EDID information.
HTOTAL_[A-C/EDP]
HBLANK_[A-C/EDP]
HSYNC_[A-C/EDP]
VTOTAL_[A-C/EDP]
VBLANK_[A-C/EDP]
VSYNC_[A-C/EDP]
VSYNCSHIFT_[A-C/EDP]
 
 
Refresh rate timing:
The calculation for these values is described in the Display chapter, section "Pipe M/N Values":
Used for normal power mode:
PIPE_DATA_M1
PIPE_DATA_N1
PIPE_LINK_M1
PIPE_LINK_N1
 
Used for low power mode:
PIPE_DATA_M2
PIPE_DATA_N2
PIPE_LINK_M2
PIPE_LINK_N2
 
Once the above are configured as desired, the panels may be configured and used. For display output, the Primary panel is most interesting, followed by the cursor panel if a hardware cursor is desired.
The EDP pipe uses Pipe A's panels.
 
The Primary panel has the following registers:
PRI_CTL_[A-C]: Enable/Disable the panel, gamma mode, pixel format, tiling, rotation
PRI_STRIDE_[A-C]: Configure the pixel stride when reading the framebuffer (in multiples of 64-bytes)
PRI_SURF_[A-C]: Configure the physical address of the framebuffer, this must be mapped via the global GTT
PRI_OFFSET_[A-C]: Configure the pixel offset from which to start reading
 
Thus, provided that the display has already been initialized, very dirty mode setting can be performed by directly updating the primary panel registers, then the horizontal and vertical TOTAL/BLANK/SYNC registers, followed by the M/N timings and then finally the WM timings. It may be possible to make the process cleaner by disabling and then re-enabling the pipe, but it is unconfirmed if that would restore the display without having to recallibrate. However, display callibration seems to be handled by the graphics chipset itself, so it may be relatively simple to just do modesetting properly (updates upcoming).
 
== Full mode set sequence ==
Line 90 ⟶ 237:
The steps are as follows:
 
=== Link Training Notes ===
DDI_BUF_TRANS must be configured with voltage swing information, as specified in the Display chapter, "DDI Buffer" section
 
- Set the number of enabled lanes via writes to AUX 0x101, and configure the lanes,
 
First step of training is to set training pattern 1 and try voltage settings from smallest to largest until clock recovery is achieved
- First set the sink device (via AUX channel/GMBUS) to start receiving training pattern 1 by performing a burst write to AUX 0x102-0x106, setting the lanes to expect training pattern 1 with the currently testing voltage level
- Set the integrated graphics (DDI_TP_CTL) to send training pattern 1
- Wait 500us
- Read offset 0x202 from the AUX channel to get the link status to determine if training was successful.
- If none of the voltage levels work, reduce the bitrate and try again
 
- For eDP, the voltage settings can be precallibrated, allowing skipping the clock recovery process, this is determined by AUX address 0x3 bit 6 (see section 3.5.1.3 of the DisplayPort 1.4 spec)
 
Second training step is to determine the pre-emphasis, it's very similar to the first step, but using training pattern 2. Clock recovery may be lost in this step, in which case the clock recovery training must be restarted.
Once pre-emphasis training is done, the link is ready.
DisplayPort 1.4 spec: [http://file.yizimg.com/383992/2014090921252964.pdf]
 
=== Graphics virtual memory configuration ===
 
== Graphics virtual memory configuration ==
 
=== The ring buffer ===
 
== The ring buffer ==
 
=== Blitter - Block Litigated Transfer engine ===
 
== Blitter - Block Litigated Transfer engine ==
 
=== 3D pipeline ===
 
== 3DSee pipelinealso ==
 
* [https://www.intel.com/content/www/us/en/docs/graphics-for-linux/developer-reference/1-0/overview.html Intel programming manuals] (PRMs) for Intel HD Graphics devices.
 
[[Category:Video]]
== Additional references ==
[[Category:GraphicsHardware]]
Anonymous user