Merge tag 'drm-misc-next-2024-02-29' of https://anongit.freedesktop.org/git/drm/drm-misc into drm-next
drm-misc-next for v6.9: UAPI Changes: Cross-subsystem Changes: backlight: - corgi: include backlight header fbdev: - Cleanup includes in public header file - fbtft: Include backlight header Core Changes: edid: - Remove built-in EDID data dp: - Avoid AUX transfers on powered-down displays - Add VSC SDP helpers modesetting: - Add sanity checks for polling - Cleanups scheduler: - Cleanups tests: - Add helpers for mode-setting tests Driver Changes: i915: - Use shared VSC SDP helper mgag200: - Work around PCI write bursts mxsfb: - Use managed mode config nouveau: - Include backlight header where necessary qiac: - Cleanups sun4: - HDMI: updates to atomic mode setting tegra: - Fix GEM refounting in error paths tidss: - Fix multi display - Fix initial Z position v3d: - Support display MMU page size Signed-off-by: Dave Airlie <airlied@redhat.com> From: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/20240229084806.GA21616@localhost.localdomain
This commit is contained in:
@@ -24,37 +24,4 @@ restrictions later on.
|
||||
As a remedy for such situations, the kernel configuration item
|
||||
CONFIG_DRM_LOAD_EDID_FIRMWARE was introduced. It allows to provide an
|
||||
individually prepared or corrected EDID data set in the /lib/firmware
|
||||
directory from where it is loaded via the firmware interface. The code
|
||||
(see drivers/gpu/drm/drm_edid_load.c) contains built-in data sets for
|
||||
commonly used screen resolutions (800x600, 1024x768, 1280x1024, 1600x1200,
|
||||
1680x1050, 1920x1080) as binary blobs, but the kernel source tree does
|
||||
not contain code to create these data. In order to elucidate the origin
|
||||
of the built-in binary EDID blobs and to facilitate the creation of
|
||||
individual data for a specific misbehaving monitor, commented sources
|
||||
and a Makefile environment are given here.
|
||||
|
||||
To create binary EDID and C source code files from the existing data
|
||||
material, simply type "make" in tools/edid/.
|
||||
|
||||
If you want to create your own EDID file, copy the file 1024x768.S,
|
||||
replace the settings with your own data and add a new target to the
|
||||
Makefile. Please note that the EDID data structure expects the timing
|
||||
values in a different way as compared to the standard X11 format.
|
||||
|
||||
X11:
|
||||
HTimings:
|
||||
hdisp hsyncstart hsyncend htotal
|
||||
VTimings:
|
||||
vdisp vsyncstart vsyncend vtotal
|
||||
|
||||
EDID::
|
||||
|
||||
#define XPIX hdisp
|
||||
#define XBLANK htotal-hdisp
|
||||
#define XOFFSET hsyncstart-hdisp
|
||||
#define XPULSE hsyncend-hsyncstart
|
||||
|
||||
#define YPIX vdisp
|
||||
#define YBLANK vtotal-vdisp
|
||||
#define YOFFSET vsyncstart-vdisp
|
||||
#define YPULSE vsyncend-vsyncstart
|
||||
directory from where it is loaded via the firmware interface.
|
||||
|
||||
@@ -1162,16 +1162,10 @@
|
||||
panels may send no or incorrect EDID data sets.
|
||||
This parameter allows to specify an EDID data sets
|
||||
in the /lib/firmware directory that are used instead.
|
||||
Generic built-in EDID data sets are used, if one of
|
||||
edid/1024x768.bin, edid/1280x1024.bin,
|
||||
edid/1680x1050.bin, or edid/1920x1080.bin is given
|
||||
and no file with the same name exists. Details and
|
||||
instructions how to build your own EDID data are
|
||||
available in Documentation/admin-guide/edid.rst. An EDID
|
||||
data set will only be used for a particular connector,
|
||||
if its name and a colon are prepended to the EDID
|
||||
name. Each connector may use a unique EDID data
|
||||
set by separating the files with a comma. An EDID
|
||||
An EDID data set will only be used for a particular
|
||||
connector, if its name and a colon are prepended to
|
||||
the EDID name. Each connector may use a unique EDID
|
||||
data set by separating the files with a comma. An EDID
|
||||
data set with no connector name will be used for
|
||||
any connectors not explicitly specified.
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ static unsigned int mhi_timeout_ms = 2000; /* 2 sec default */
|
||||
module_param(mhi_timeout_ms, uint, 0600);
|
||||
MODULE_PARM_DESC(mhi_timeout_ms, "MHI controller timeout value");
|
||||
|
||||
static struct mhi_channel_config aic100_channels[] = {
|
||||
static const struct mhi_channel_config aic100_channels[] = {
|
||||
{
|
||||
.name = "QAIC_LOOPBACK",
|
||||
.num = 0,
|
||||
|
||||
@@ -532,6 +532,15 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request,
|
||||
|
||||
mutex_lock(&aux->hw_mutex);
|
||||
|
||||
/*
|
||||
* If the device attached to the aux bus is powered down then there's
|
||||
* no reason to attempt a transfer. Error out immediately.
|
||||
*/
|
||||
if (aux->powered_down) {
|
||||
ret = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
* The specification doesn't give any recommendation on how often to
|
||||
* retry native transactions. We used to retry 7 times like for
|
||||
@@ -599,6 +608,29 @@ int drm_dp_dpcd_probe(struct drm_dp_aux *aux, unsigned int offset)
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dp_dpcd_probe);
|
||||
|
||||
/**
|
||||
* drm_dp_dpcd_set_powered() - Set whether the DP device is powered
|
||||
* @aux: DisplayPort AUX channel; for convenience it's OK to pass NULL here
|
||||
* and the function will be a no-op.
|
||||
* @powered: true if powered; false if not
|
||||
*
|
||||
* If the endpoint device on the DP AUX bus is known to be powered down
|
||||
* then this function can be called to make future transfers fail immediately
|
||||
* instead of needing to time out.
|
||||
*
|
||||
* If this function is never called then a device defaults to being powered.
|
||||
*/
|
||||
void drm_dp_dpcd_set_powered(struct drm_dp_aux *aux, bool powered)
|
||||
{
|
||||
if (!aux)
|
||||
return;
|
||||
|
||||
mutex_lock(&aux->hw_mutex);
|
||||
aux->powered_down = !powered;
|
||||
mutex_unlock(&aux->hw_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dp_dpcd_set_powered);
|
||||
|
||||
/**
|
||||
* drm_dp_dpcd_read() - read a series of bytes from the DPCD
|
||||
* @aux: DisplayPort AUX channel (SST or MST)
|
||||
@@ -1858,6 +1890,9 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
|
||||
struct drm_dp_aux_msg msg;
|
||||
int err = 0;
|
||||
|
||||
if (aux->powered_down)
|
||||
return -EBUSY;
|
||||
|
||||
dp_aux_i2c_transfer_size = clamp(dp_aux_i2c_transfer_size, 1, DP_AUX_MAX_PAYLOAD_BYTES);
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
@@ -2913,6 +2948,103 @@ void drm_dp_vsc_sdp_log(struct drm_printer *p, const struct drm_dp_vsc_sdp *vsc)
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dp_vsc_sdp_log);
|
||||
|
||||
/**
|
||||
* drm_dp_vsc_sdp_supported() - check if vsc sdp is supported
|
||||
* @aux: DisplayPort AUX channel
|
||||
* @dpcd: DisplayPort configuration data
|
||||
*
|
||||
* Returns true if vsc sdp is supported, else returns false
|
||||
*/
|
||||
bool drm_dp_vsc_sdp_supported(struct drm_dp_aux *aux, const u8 dpcd[DP_RECEIVER_CAP_SIZE])
|
||||
{
|
||||
u8 rx_feature;
|
||||
|
||||
if (dpcd[DP_DPCD_REV] < DP_DPCD_REV_13)
|
||||
return false;
|
||||
|
||||
if (drm_dp_dpcd_readb(aux, DP_DPRX_FEATURE_ENUMERATION_LIST, &rx_feature) != 1) {
|
||||
drm_dbg_dp(aux->drm_dev, "failed to read DP_DPRX_FEATURE_ENUMERATION_LIST\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return (rx_feature & DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dp_vsc_sdp_supported);
|
||||
|
||||
/**
|
||||
* drm_dp_vsc_sdp_pack() - pack a given vsc sdp into generic dp_sdp
|
||||
* @vsc: vsc sdp initialized according to its purpose as defined in
|
||||
* table 2-118 - table 2-120 in DP 1.4a specification
|
||||
* @sdp: valid handle to the generic dp_sdp which will be packed
|
||||
*
|
||||
* Returns length of sdp on success and error code on failure
|
||||
*/
|
||||
ssize_t drm_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc,
|
||||
struct dp_sdp *sdp)
|
||||
{
|
||||
size_t length = sizeof(struct dp_sdp);
|
||||
|
||||
memset(sdp, 0, sizeof(struct dp_sdp));
|
||||
|
||||
/*
|
||||
* Prepare VSC Header for SU as per DP 1.4a spec, Table 2-119
|
||||
* VSC SDP Header Bytes
|
||||
*/
|
||||
sdp->sdp_header.HB0 = 0; /* Secondary-Data Packet ID = 0 */
|
||||
sdp->sdp_header.HB1 = vsc->sdp_type; /* Secondary-data Packet Type */
|
||||
sdp->sdp_header.HB2 = vsc->revision; /* Revision Number */
|
||||
sdp->sdp_header.HB3 = vsc->length; /* Number of Valid Data Bytes */
|
||||
|
||||
if (vsc->revision == 0x6) {
|
||||
sdp->db[0] = 1;
|
||||
sdp->db[3] = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Revision 0x5 and revision 0x7 supports Pixel Encoding/Colorimetry
|
||||
* Format as per DP 1.4a spec and DP 2.0 respectively.
|
||||
*/
|
||||
if (!(vsc->revision == 0x5 || vsc->revision == 0x7))
|
||||
goto out;
|
||||
|
||||
/* VSC SDP Payload for DB16 through DB18 */
|
||||
/* Pixel Encoding and Colorimetry Formats */
|
||||
sdp->db[16] = (vsc->pixelformat & 0xf) << 4; /* DB16[7:4] */
|
||||
sdp->db[16] |= vsc->colorimetry & 0xf; /* DB16[3:0] */
|
||||
|
||||
switch (vsc->bpc) {
|
||||
case 6:
|
||||
/* 6bpc: 0x0 */
|
||||
break;
|
||||
case 8:
|
||||
sdp->db[17] = 0x1; /* DB17[3:0] */
|
||||
break;
|
||||
case 10:
|
||||
sdp->db[17] = 0x2;
|
||||
break;
|
||||
case 12:
|
||||
sdp->db[17] = 0x3;
|
||||
break;
|
||||
case 16:
|
||||
sdp->db[17] = 0x4;
|
||||
break;
|
||||
default:
|
||||
WARN(1, "Missing case %d\n", vsc->bpc);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Dynamic Range and Component Bit Depth */
|
||||
if (vsc->dynamic_range == DP_DYNAMIC_RANGE_CTA)
|
||||
sdp->db[17] |= 0x80; /* DB17[7] */
|
||||
|
||||
/* Content Type */
|
||||
sdp->db[18] = vsc->content_type & 0x7;
|
||||
|
||||
out:
|
||||
return length;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dp_vsc_sdp_pack);
|
||||
|
||||
/**
|
||||
* drm_dp_get_pcon_max_frl_bw() - maximum frl supported by PCON
|
||||
* @dpcd: DisplayPort configuration data
|
||||
|
||||
@@ -107,18 +107,6 @@ int drm_crtc_force_disable(struct drm_crtc *crtc)
|
||||
return drm_mode_set_config_internal(&set);
|
||||
}
|
||||
|
||||
static unsigned int drm_num_crtcs(struct drm_device *dev)
|
||||
{
|
||||
unsigned int num = 0;
|
||||
struct drm_crtc *tmp;
|
||||
|
||||
drm_for_each_crtc(tmp, dev) {
|
||||
num++;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
int drm_crtc_register_all(struct drm_device *dev)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
@@ -278,8 +266,7 @@ static int __drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *
|
||||
if (name) {
|
||||
crtc->name = kvasprintf(GFP_KERNEL, name, ap);
|
||||
} else {
|
||||
crtc->name = kasprintf(GFP_KERNEL, "crtc-%d",
|
||||
drm_num_crtcs(dev));
|
||||
crtc->name = kasprintf(GFP_KERNEL, "crtc-%d", config->num_crtc);
|
||||
}
|
||||
if (!crtc->name) {
|
||||
drm_mode_object_unregister(dev, &crtc->base);
|
||||
|
||||
@@ -20,162 +20,28 @@
|
||||
|
||||
static char edid_firmware[PATH_MAX];
|
||||
module_param_string(edid_firmware, edid_firmware, sizeof(edid_firmware), 0644);
|
||||
MODULE_PARM_DESC(edid_firmware, "Do not probe monitor, use specified EDID blob "
|
||||
"from built-in data or /lib/firmware instead. ");
|
||||
|
||||
#define GENERIC_EDIDS 6
|
||||
static const char * const generic_edid_name[GENERIC_EDIDS] = {
|
||||
"edid/800x600.bin",
|
||||
"edid/1024x768.bin",
|
||||
"edid/1280x1024.bin",
|
||||
"edid/1600x1200.bin",
|
||||
"edid/1680x1050.bin",
|
||||
"edid/1920x1080.bin",
|
||||
};
|
||||
|
||||
static const u8 generic_edid[GENERIC_EDIDS][128] = {
|
||||
{
|
||||
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
|
||||
0x31, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x05, 0x16, 0x01, 0x03, 0x6d, 0x1b, 0x14, 0x78,
|
||||
0xea, 0x5e, 0xc0, 0xa4, 0x59, 0x4a, 0x98, 0x25,
|
||||
0x20, 0x50, 0x54, 0x01, 0x00, 0x00, 0x45, 0x40,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xa0, 0x0f,
|
||||
0x20, 0x00, 0x31, 0x58, 0x1c, 0x20, 0x28, 0x80,
|
||||
0x14, 0x00, 0x15, 0xd0, 0x10, 0x00, 0x00, 0x1e,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x4c, 0x69, 0x6e,
|
||||
0x75, 0x78, 0x20, 0x23, 0x30, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x3b,
|
||||
0x3d, 0x24, 0x26, 0x05, 0x00, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc,
|
||||
0x00, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x20, 0x53,
|
||||
0x56, 0x47, 0x41, 0x0a, 0x20, 0x20, 0x00, 0xc2,
|
||||
},
|
||||
{
|
||||
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
|
||||
0x31, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x05, 0x16, 0x01, 0x03, 0x6d, 0x23, 0x1a, 0x78,
|
||||
0xea, 0x5e, 0xc0, 0xa4, 0x59, 0x4a, 0x98, 0x25,
|
||||
0x20, 0x50, 0x54, 0x00, 0x08, 0x00, 0x61, 0x40,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x64, 0x19,
|
||||
0x00, 0x40, 0x41, 0x00, 0x26, 0x30, 0x08, 0x90,
|
||||
0x36, 0x00, 0x63, 0x0a, 0x11, 0x00, 0x00, 0x18,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x4c, 0x69, 0x6e,
|
||||
0x75, 0x78, 0x20, 0x23, 0x30, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x3b,
|
||||
0x3d, 0x2f, 0x31, 0x07, 0x00, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc,
|
||||
0x00, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x20, 0x58,
|
||||
0x47, 0x41, 0x0a, 0x20, 0x20, 0x20, 0x00, 0x55,
|
||||
},
|
||||
{
|
||||
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
|
||||
0x31, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x05, 0x16, 0x01, 0x03, 0x6d, 0x2c, 0x23, 0x78,
|
||||
0xea, 0x5e, 0xc0, 0xa4, 0x59, 0x4a, 0x98, 0x25,
|
||||
0x20, 0x50, 0x54, 0x00, 0x00, 0x00, 0x81, 0x80,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x30, 0x2a,
|
||||
0x00, 0x98, 0x51, 0x00, 0x2a, 0x40, 0x30, 0x70,
|
||||
0x13, 0x00, 0xbc, 0x63, 0x11, 0x00, 0x00, 0x1e,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x4c, 0x69, 0x6e,
|
||||
0x75, 0x78, 0x20, 0x23, 0x30, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x3b,
|
||||
0x3d, 0x3e, 0x40, 0x0b, 0x00, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc,
|
||||
0x00, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x20, 0x53,
|
||||
0x58, 0x47, 0x41, 0x0a, 0x20, 0x20, 0x00, 0xa0,
|
||||
},
|
||||
{
|
||||
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
|
||||
0x31, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x05, 0x16, 0x01, 0x03, 0x6d, 0x37, 0x29, 0x78,
|
||||
0xea, 0x5e, 0xc0, 0xa4, 0x59, 0x4a, 0x98, 0x25,
|
||||
0x20, 0x50, 0x54, 0x00, 0x00, 0x00, 0xa9, 0x40,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x48, 0x3f,
|
||||
0x40, 0x30, 0x62, 0xb0, 0x32, 0x40, 0x40, 0xc0,
|
||||
0x13, 0x00, 0x2b, 0xa0, 0x21, 0x00, 0x00, 0x1e,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x4c, 0x69, 0x6e,
|
||||
0x75, 0x78, 0x20, 0x23, 0x30, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x3b,
|
||||
0x3d, 0x4a, 0x4c, 0x11, 0x00, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc,
|
||||
0x00, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x20, 0x55,
|
||||
0x58, 0x47, 0x41, 0x0a, 0x20, 0x20, 0x00, 0x9d,
|
||||
},
|
||||
{
|
||||
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
|
||||
0x31, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x05, 0x16, 0x01, 0x03, 0x6d, 0x2b, 0x1b, 0x78,
|
||||
0xea, 0x5e, 0xc0, 0xa4, 0x59, 0x4a, 0x98, 0x25,
|
||||
0x20, 0x50, 0x54, 0x00, 0x00, 0x00, 0xb3, 0x00,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x21, 0x39,
|
||||
0x90, 0x30, 0x62, 0x1a, 0x27, 0x40, 0x68, 0xb0,
|
||||
0x36, 0x00, 0xb5, 0x11, 0x11, 0x00, 0x00, 0x1e,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x4c, 0x69, 0x6e,
|
||||
0x75, 0x78, 0x20, 0x23, 0x30, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x3b,
|
||||
0x3d, 0x40, 0x42, 0x0f, 0x00, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc,
|
||||
0x00, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x20, 0x57,
|
||||
0x53, 0x58, 0x47, 0x41, 0x0a, 0x20, 0x00, 0x26,
|
||||
},
|
||||
{
|
||||
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
|
||||
0x31, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x05, 0x16, 0x01, 0x03, 0x6d, 0x32, 0x1c, 0x78,
|
||||
0xea, 0x5e, 0xc0, 0xa4, 0x59, 0x4a, 0x98, 0x25,
|
||||
0x20, 0x50, 0x54, 0x00, 0x00, 0x00, 0xd1, 0xc0,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a,
|
||||
0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
|
||||
0x45, 0x00, 0xf4, 0x19, 0x11, 0x00, 0x00, 0x1e,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x4c, 0x69, 0x6e,
|
||||
0x75, 0x78, 0x20, 0x23, 0x30, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x3b,
|
||||
0x3d, 0x42, 0x44, 0x0f, 0x00, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc,
|
||||
0x00, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x20, 0x46,
|
||||
0x48, 0x44, 0x0a, 0x20, 0x20, 0x20, 0x00, 0x05,
|
||||
},
|
||||
};
|
||||
MODULE_PARM_DESC(edid_firmware,
|
||||
"Do not probe monitor, use specified EDID blob from /lib/firmware instead.");
|
||||
|
||||
static const struct drm_edid *edid_load(struct drm_connector *connector, const char *name)
|
||||
{
|
||||
const struct firmware *fw = NULL;
|
||||
const u8 *fwdata;
|
||||
const struct drm_edid *drm_edid;
|
||||
int fwsize, builtin;
|
||||
int err;
|
||||
|
||||
builtin = match_string(generic_edid_name, GENERIC_EDIDS, name);
|
||||
if (builtin >= 0) {
|
||||
fwdata = generic_edid[builtin];
|
||||
fwsize = sizeof(generic_edid[builtin]);
|
||||
} else {
|
||||
int err;
|
||||
|
||||
err = request_firmware(&fw, name, connector->dev->dev);
|
||||
if (err) {
|
||||
drm_err(connector->dev,
|
||||
"[CONNECTOR:%d:%s] Requesting EDID firmware \"%s\" failed (err=%d)\n",
|
||||
connector->base.id, connector->name,
|
||||
name, err);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
fwdata = fw->data;
|
||||
fwsize = fw->size;
|
||||
err = request_firmware(&fw, name, connector->dev->dev);
|
||||
if (err) {
|
||||
drm_err(connector->dev,
|
||||
"[CONNECTOR:%d:%s] Requesting EDID firmware \"%s\" failed (err=%d)\n",
|
||||
connector->base.id, connector->name,
|
||||
name, err);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] Loaded %s firmware EDID \"%s\"\n",
|
||||
connector->base.id, connector->name,
|
||||
builtin >= 0 ? "built-in" : "external", name);
|
||||
drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] Loaded external firmware EDID \"%s\"\n",
|
||||
connector->base.id, connector->name, name);
|
||||
|
||||
drm_edid = drm_edid_alloc(fwdata, fwsize);
|
||||
drm_edid = drm_edid_alloc(fw->data, fw->size);
|
||||
if (!drm_edid_valid(drm_edid)) {
|
||||
drm_err(connector->dev, "Invalid firmware EDID \"%s\"\n", name);
|
||||
drm_edid_free(drm_edid);
|
||||
|
||||
@@ -193,13 +193,22 @@ int drm_mode_config_helper_suspend(struct drm_device *dev)
|
||||
|
||||
if (!dev)
|
||||
return 0;
|
||||
/*
|
||||
* Don't disable polling if it was never initialized
|
||||
*/
|
||||
if (dev->mode_config.poll_enabled)
|
||||
drm_kms_helper_poll_disable(dev);
|
||||
|
||||
drm_kms_helper_poll_disable(dev);
|
||||
drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 1);
|
||||
state = drm_atomic_helper_suspend(dev);
|
||||
if (IS_ERR(state)) {
|
||||
drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 0);
|
||||
drm_kms_helper_poll_enable(dev);
|
||||
/*
|
||||
* Don't enable polling if it was never initialized
|
||||
*/
|
||||
if (dev->mode_config.poll_enabled)
|
||||
drm_kms_helper_poll_enable(dev);
|
||||
|
||||
return PTR_ERR(state);
|
||||
}
|
||||
|
||||
@@ -239,7 +248,11 @@ int drm_mode_config_helper_resume(struct drm_device *dev)
|
||||
dev->mode_config.suspend_state = NULL;
|
||||
|
||||
drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 0);
|
||||
drm_kms_helper_poll_enable(dev);
|
||||
/*
|
||||
* Don't enable polling if it is not initialized
|
||||
*/
|
||||
if (dev->mode_config.poll_enabled)
|
||||
drm_kms_helper_poll_enable(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -293,14 +293,17 @@ static void reschedule_output_poll_work(struct drm_device *dev)
|
||||
* Drivers can call this helper from their device resume implementation. It is
|
||||
* not an error to call this even when output polling isn't enabled.
|
||||
*
|
||||
* If device polling was never initialized before, this call will trigger a
|
||||
* warning and return.
|
||||
*
|
||||
* Note that calls to enable and disable polling must be strictly ordered, which
|
||||
* is automatically the case when they're only call from suspend/resume
|
||||
* callbacks.
|
||||
*/
|
||||
void drm_kms_helper_poll_enable(struct drm_device *dev)
|
||||
{
|
||||
if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll ||
|
||||
dev->mode_config.poll_running)
|
||||
if (drm_WARN_ON_ONCE(dev, !dev->mode_config.poll_enabled) ||
|
||||
!drm_kms_helper_poll || dev->mode_config.poll_running)
|
||||
return;
|
||||
|
||||
if (drm_kms_helper_enable_hpd(dev) ||
|
||||
@@ -619,8 +622,12 @@ retry:
|
||||
0);
|
||||
}
|
||||
|
||||
/* Re-enable polling in case the global poll config changed. */
|
||||
drm_kms_helper_poll_enable(dev);
|
||||
/*
|
||||
* Re-enable polling in case the global poll config changed but polling
|
||||
* is still initialized.
|
||||
*/
|
||||
if (dev->mode_config.poll_enabled)
|
||||
drm_kms_helper_poll_enable(dev);
|
||||
|
||||
if (connector->status == connector_status_disconnected) {
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n",
|
||||
@@ -871,12 +878,18 @@ EXPORT_SYMBOL(drm_kms_helper_is_poll_worker);
|
||||
* not an error to call this even when output polling isn't enabled or already
|
||||
* disabled. Polling is re-enabled by calling drm_kms_helper_poll_enable().
|
||||
*
|
||||
* If however, the polling was never initialized, this call will trigger a
|
||||
* warning and return
|
||||
*
|
||||
* Note that calls to enable and disable polling must be strictly ordered, which
|
||||
* is automatically the case when they're only call from suspend/resume
|
||||
* callbacks.
|
||||
*/
|
||||
void drm_kms_helper_poll_disable(struct drm_device *dev)
|
||||
{
|
||||
if (drm_WARN_ON(dev, !dev->mode_config.poll_enabled))
|
||||
return;
|
||||
|
||||
if (dev->mode_config.poll_running)
|
||||
drm_kms_helper_disable_hpd(dev);
|
||||
|
||||
|
||||
@@ -4127,73 +4127,6 @@ intel_dp_needs_vsc_sdp(const struct intel_crtc_state *crtc_state,
|
||||
return false;
|
||||
}
|
||||
|
||||
static ssize_t intel_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc,
|
||||
struct dp_sdp *sdp, size_t size)
|
||||
{
|
||||
size_t length = sizeof(struct dp_sdp);
|
||||
|
||||
if (size < length)
|
||||
return -ENOSPC;
|
||||
|
||||
memset(sdp, 0, size);
|
||||
|
||||
/*
|
||||
* Prepare VSC Header for SU as per DP 1.4a spec, Table 2-119
|
||||
* VSC SDP Header Bytes
|
||||
*/
|
||||
sdp->sdp_header.HB0 = 0; /* Secondary-Data Packet ID = 0 */
|
||||
sdp->sdp_header.HB1 = vsc->sdp_type; /* Secondary-data Packet Type */
|
||||
sdp->sdp_header.HB2 = vsc->revision; /* Revision Number */
|
||||
sdp->sdp_header.HB3 = vsc->length; /* Number of Valid Data Bytes */
|
||||
|
||||
if (vsc->revision == 0x6) {
|
||||
sdp->db[0] = 1;
|
||||
sdp->db[3] = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Revision 0x5 and revision 0x7 supports Pixel Encoding/Colorimetry
|
||||
* Format as per DP 1.4a spec and DP 2.0 respectively.
|
||||
*/
|
||||
if (!(vsc->revision == 0x5 || vsc->revision == 0x7))
|
||||
goto out;
|
||||
|
||||
/* VSC SDP Payload for DB16 through DB18 */
|
||||
/* Pixel Encoding and Colorimetry Formats */
|
||||
sdp->db[16] = (vsc->pixelformat & 0xf) << 4; /* DB16[7:4] */
|
||||
sdp->db[16] |= vsc->colorimetry & 0xf; /* DB16[3:0] */
|
||||
|
||||
switch (vsc->bpc) {
|
||||
case 6:
|
||||
/* 6bpc: 0x0 */
|
||||
break;
|
||||
case 8:
|
||||
sdp->db[17] = 0x1; /* DB17[3:0] */
|
||||
break;
|
||||
case 10:
|
||||
sdp->db[17] = 0x2;
|
||||
break;
|
||||
case 12:
|
||||
sdp->db[17] = 0x3;
|
||||
break;
|
||||
case 16:
|
||||
sdp->db[17] = 0x4;
|
||||
break;
|
||||
default:
|
||||
MISSING_CASE(vsc->bpc);
|
||||
break;
|
||||
}
|
||||
/* Dynamic Range and Component Bit Depth */
|
||||
if (vsc->dynamic_range == DP_DYNAMIC_RANGE_CTA)
|
||||
sdp->db[17] |= 0x80; /* DB17[7] */
|
||||
|
||||
/* Content Type */
|
||||
sdp->db[18] = vsc->content_type & 0x7;
|
||||
|
||||
out:
|
||||
return length;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
intel_dp_hdr_metadata_infoframe_sdp_pack(struct drm_i915_private *i915,
|
||||
const struct hdmi_drm_infoframe *drm_infoframe,
|
||||
@@ -4286,8 +4219,7 @@ static void intel_write_dp_sdp(struct intel_encoder *encoder,
|
||||
|
||||
switch (type) {
|
||||
case DP_SDP_VSC:
|
||||
len = intel_dp_vsc_sdp_pack(&crtc_state->infoframes.vsc, &sdp,
|
||||
sizeof(sdp));
|
||||
len = drm_dp_vsc_sdp_pack(&crtc_state->infoframes.vsc, &sdp);
|
||||
break;
|
||||
case HDMI_PACKET_TYPE_GAMUT_METADATA:
|
||||
len = intel_dp_hdr_metadata_infoframe_sdp_pack(dev_priv,
|
||||
|
||||
@@ -11,3 +11,15 @@ config DRM_MGAG200
|
||||
MGA G200 desktop chips and the server variants. It requires 0.3.0
|
||||
of the modesetting userspace driver, and a version of mga driver
|
||||
that will fail on KMS enabled devices.
|
||||
|
||||
config DRM_MGAG200_IOBURST_WORKAROUND
|
||||
bool "Disable buffer caching"
|
||||
depends on DRM_MGAG200 && PREEMPT_RT && X86
|
||||
help
|
||||
Enable a workaround to avoid I/O bursts within the mgag200 driver at
|
||||
the expense of overall display performance.
|
||||
It restores the <v5.10 behavior, by mapping the framebuffer in system
|
||||
RAM as Write-Combining, and flushing the cache after each write.
|
||||
This is only useful on x86_64 if you want to run processes with
|
||||
deterministic latency.
|
||||
If unsure, say N.
|
||||
|
||||
@@ -84,6 +84,20 @@ resource_size_t mgag200_probe_vram(void __iomem *mem, resource_size_t size)
|
||||
return offset - 65536;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DRM_MGAG200_IOBURST_WORKAROUND)
|
||||
static struct drm_gem_object *mgag200_create_object(struct drm_device *dev, size_t size)
|
||||
{
|
||||
struct drm_gem_shmem_object *shmem;
|
||||
|
||||
shmem = kzalloc(sizeof(*shmem), GFP_KERNEL);
|
||||
if (!shmem)
|
||||
return NULL;
|
||||
|
||||
shmem->map_wc = true;
|
||||
return &shmem->base;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* DRM driver
|
||||
*/
|
||||
@@ -99,6 +113,9 @@ static const struct drm_driver mgag200_driver = {
|
||||
.major = DRIVER_MAJOR,
|
||||
.minor = DRIVER_MINOR,
|
||||
.patchlevel = DRIVER_PATCHLEVEL,
|
||||
#if defined(CONFIG_DRM_MGAG200_IOBURST_WORKAROUND)
|
||||
.gem_create_object = mgag200_create_object,
|
||||
#endif
|
||||
DRM_GEM_SHMEM_DRIVER_OPS,
|
||||
};
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_cache.h>
|
||||
#include <drm/drm_damage_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_format_helper.h>
|
||||
@@ -436,6 +437,13 @@ static void mgag200_handle_damage(struct mga_device *mdev, const struct iosys_ma
|
||||
|
||||
iosys_map_incr(&dst, drm_fb_clip_offset(fb->pitches[0], fb->format, clip));
|
||||
drm_fb_memcpy(&dst, fb->pitches, vmap, fb, clip);
|
||||
|
||||
/* Flushing the cache greatly improves latency on x86_64 */
|
||||
#if defined(CONFIG_DRM_MGAG200_IOBURST_WORKAROUND)
|
||||
if (!vmap->is_iomem)
|
||||
drm_clflush_virt_range(vmap->vaddr + clip->y1 * fb->pitches[0],
|
||||
drm_rect_height(clip) * fb->pitches[0]);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -167,7 +167,11 @@ static int lcdif_load(struct drm_device *drm)
|
||||
return ret;
|
||||
|
||||
/* Modeset init */
|
||||
drm_mode_config_init(drm);
|
||||
ret = drmm_mode_config_init(drm);
|
||||
if (ret) {
|
||||
dev_err(drm->dev, "Failed to initialize mode config\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = lcdif_kms_init(lcdif);
|
||||
if (ret < 0) {
|
||||
@@ -227,7 +231,6 @@ static void lcdif_unload(struct drm_device *drm)
|
||||
drm_crtc_vblank_off(&lcdif->crtc);
|
||||
|
||||
drm_kms_helper_poll_fini(drm);
|
||||
drm_mode_config_cleanup(drm);
|
||||
|
||||
pm_runtime_put_sync(drm->dev);
|
||||
pm_runtime_disable(drm->dev);
|
||||
|
||||
@@ -249,7 +249,11 @@ static int mxsfb_load(struct drm_device *drm,
|
||||
pm_runtime_enable(drm->dev);
|
||||
|
||||
/* Modeset init */
|
||||
drm_mode_config_init(drm);
|
||||
ret = drmm_mode_config_init(drm);
|
||||
if (ret) {
|
||||
dev_err(drm->dev, "Failed to initialize mode config\n");
|
||||
goto err_vblank;
|
||||
}
|
||||
|
||||
ret = mxsfb_kms_init(mxsfb);
|
||||
if (ret < 0) {
|
||||
@@ -312,7 +316,6 @@ err_vblank:
|
||||
static void mxsfb_unload(struct drm_device *drm)
|
||||
{
|
||||
drm_kms_helper_poll_fini(drm);
|
||||
drm_mode_config_cleanup(drm);
|
||||
|
||||
pm_runtime_get_sync(drm->dev);
|
||||
mxsfb_irq_uninstall(drm);
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "wndw.h"
|
||||
#include "handles.h"
|
||||
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/hdmi.h>
|
||||
#include <linux/component.h>
|
||||
|
||||
@@ -413,6 +413,7 @@ static int panel_edp_suspend(struct device *dev)
|
||||
{
|
||||
struct panel_edp *p = dev_get_drvdata(dev);
|
||||
|
||||
drm_dp_dpcd_set_powered(p->aux, false);
|
||||
gpiod_set_value_cansleep(p->enable_gpio, 0);
|
||||
regulator_disable(p->supply);
|
||||
p->unprepared_time = ktime_get_boottime();
|
||||
@@ -469,6 +470,7 @@ static int panel_edp_prepare_once(struct panel_edp *p)
|
||||
}
|
||||
|
||||
gpiod_set_value_cansleep(p->enable_gpio, 1);
|
||||
drm_dp_dpcd_set_powered(p->aux, true);
|
||||
|
||||
p->powered_on_time = ktime_get_boottime();
|
||||
|
||||
@@ -507,6 +509,7 @@ static int panel_edp_prepare_once(struct panel_edp *p)
|
||||
return 0;
|
||||
|
||||
error:
|
||||
drm_dp_dpcd_set_powered(p->aux, false);
|
||||
gpiod_set_value_cansleep(p->enable_gpio, 0);
|
||||
regulator_disable(p->supply);
|
||||
p->unprepared_time = ktime_get_boottime();
|
||||
|
||||
@@ -72,6 +72,7 @@ static int atana33xc20_suspend(struct device *dev)
|
||||
if (p->el3_was_on)
|
||||
atana33xc20_wait(p->el_on3_off_time, 150);
|
||||
|
||||
drm_dp_dpcd_set_powered(p->aux, false);
|
||||
ret = regulator_disable(p->supply);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -93,6 +94,7 @@ static int atana33xc20_resume(struct device *dev)
|
||||
ret = regulator_enable(p->supply);
|
||||
if (ret)
|
||||
return ret;
|
||||
drm_dp_dpcd_set_powered(p->aux, true);
|
||||
p->powered_on_time = ktime_get_boottime();
|
||||
|
||||
if (p->no_hpd) {
|
||||
|
||||
@@ -33,9 +33,7 @@ static struct kmem_cache *sched_fence_slab;
|
||||
|
||||
static int __init drm_sched_fence_slab_init(void)
|
||||
{
|
||||
sched_fence_slab = kmem_cache_create(
|
||||
"drm_sched_fence", sizeof(struct drm_sched_fence), 0,
|
||||
SLAB_HWCACHE_ALIGN, NULL);
|
||||
sched_fence_slab = KMEM_CACHE(drm_sched_fence, SLAB_HWCACHE_ALIGN);
|
||||
if (!sched_fence_slab)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
@@ -30,19 +30,11 @@
|
||||
#include "sun4i_drv.h"
|
||||
#include "sun4i_hdmi.h"
|
||||
|
||||
static inline struct sun4i_hdmi *
|
||||
drm_encoder_to_sun4i_hdmi(struct drm_encoder *encoder)
|
||||
{
|
||||
return container_of(encoder, struct sun4i_hdmi,
|
||||
encoder);
|
||||
}
|
||||
#define drm_encoder_to_sun4i_hdmi(e) \
|
||||
container_of_const(e, struct sun4i_hdmi, encoder)
|
||||
|
||||
static inline struct sun4i_hdmi *
|
||||
drm_connector_to_sun4i_hdmi(struct drm_connector *connector)
|
||||
{
|
||||
return container_of(connector, struct sun4i_hdmi,
|
||||
connector);
|
||||
}
|
||||
#define drm_connector_to_sun4i_hdmi(c) \
|
||||
container_of_const(c, struct sun4i_hdmi, connector)
|
||||
|
||||
static int sun4i_hdmi_setup_avi_infoframes(struct sun4i_hdmi *hdmi,
|
||||
struct drm_display_mode *mode)
|
||||
@@ -70,19 +62,8 @@ static int sun4i_hdmi_setup_avi_infoframes(struct sun4i_hdmi *hdmi,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sun4i_hdmi_atomic_check(struct drm_encoder *encoder,
|
||||
struct drm_crtc_state *crtc_state,
|
||||
struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct drm_display_mode *mode = &crtc_state->mode;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sun4i_hdmi_disable(struct drm_encoder *encoder)
|
||||
static void sun4i_hdmi_disable(struct drm_encoder *encoder,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
|
||||
u32 val;
|
||||
@@ -96,37 +77,17 @@ static void sun4i_hdmi_disable(struct drm_encoder *encoder)
|
||||
clk_disable_unprepare(hdmi->tmds_clk);
|
||||
}
|
||||
|
||||
static void sun4i_hdmi_enable(struct drm_encoder *encoder)
|
||||
static void sun4i_hdmi_enable(struct drm_encoder *encoder,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
|
||||
struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
|
||||
struct drm_display_info *display = &hdmi->connector.display_info;
|
||||
unsigned int x, y;
|
||||
u32 val = 0;
|
||||
|
||||
DRM_DEBUG_DRIVER("Enabling the HDMI Output\n");
|
||||
|
||||
clk_prepare_enable(hdmi->tmds_clk);
|
||||
|
||||
sun4i_hdmi_setup_avi_infoframes(hdmi, mode);
|
||||
val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI);
|
||||
val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END);
|
||||
writel(val, hdmi->base + SUN4I_HDMI_PKT_CTRL_REG(0));
|
||||
|
||||
val = SUN4I_HDMI_VID_CTRL_ENABLE;
|
||||
if (display->is_hdmi)
|
||||
val |= SUN4I_HDMI_VID_CTRL_HDMI_MODE;
|
||||
|
||||
writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
|
||||
}
|
||||
|
||||
static void sun4i_hdmi_mode_set(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
|
||||
unsigned int x, y;
|
||||
u32 val;
|
||||
|
||||
clk_set_rate(hdmi->mod_clk, mode->crtc_clock * 1000);
|
||||
clk_set_rate(hdmi->tmds_clk, mode->crtc_clock * 1000);
|
||||
|
||||
@@ -178,35 +139,77 @@ static void sun4i_hdmi_mode_set(struct drm_encoder *encoder,
|
||||
val |= SUN4I_HDMI_VID_TIMING_POL_VSYNC;
|
||||
|
||||
writel(val, hdmi->base + SUN4I_HDMI_VID_TIMING_POL_REG);
|
||||
}
|
||||
|
||||
static enum drm_mode_status sun4i_hdmi_mode_valid(struct drm_encoder *encoder,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
|
||||
unsigned long rate = mode->clock * 1000;
|
||||
unsigned long diff = rate / 200; /* +-0.5% allowed by HDMI spec */
|
||||
long rounded_rate;
|
||||
clk_prepare_enable(hdmi->tmds_clk);
|
||||
|
||||
/* 165 MHz is the typical max pixelclock frequency for HDMI <= 1.2 */
|
||||
if (rate > 165000000)
|
||||
return MODE_CLOCK_HIGH;
|
||||
rounded_rate = clk_round_rate(hdmi->tmds_clk, rate);
|
||||
if (rounded_rate > 0 &&
|
||||
max_t(unsigned long, rounded_rate, rate) -
|
||||
min_t(unsigned long, rounded_rate, rate) < diff)
|
||||
return MODE_OK;
|
||||
return MODE_NOCLOCK;
|
||||
sun4i_hdmi_setup_avi_infoframes(hdmi, mode);
|
||||
val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI);
|
||||
val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END);
|
||||
writel(val, hdmi->base + SUN4I_HDMI_PKT_CTRL_REG(0));
|
||||
|
||||
val = SUN4I_HDMI_VID_CTRL_ENABLE;
|
||||
if (display->is_hdmi)
|
||||
val |= SUN4I_HDMI_VID_CTRL_HDMI_MODE;
|
||||
|
||||
writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
|
||||
}
|
||||
|
||||
static const struct drm_encoder_helper_funcs sun4i_hdmi_helper_funcs = {
|
||||
.atomic_check = sun4i_hdmi_atomic_check,
|
||||
.disable = sun4i_hdmi_disable,
|
||||
.enable = sun4i_hdmi_enable,
|
||||
.mode_set = sun4i_hdmi_mode_set,
|
||||
.mode_valid = sun4i_hdmi_mode_valid,
|
||||
.atomic_disable = sun4i_hdmi_disable,
|
||||
.atomic_enable = sun4i_hdmi_enable,
|
||||
};
|
||||
|
||||
static enum drm_mode_status
|
||||
sun4i_hdmi_connector_clock_valid(const struct drm_connector *connector,
|
||||
const struct drm_display_mode *mode,
|
||||
unsigned long long clock)
|
||||
{
|
||||
const struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector);
|
||||
unsigned long diff = clock / 200; /* +-0.5% allowed by HDMI spec */
|
||||
long rounded_rate;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
|
||||
return MODE_BAD;
|
||||
|
||||
/* 165 MHz is the typical max pixelclock frequency for HDMI <= 1.2 */
|
||||
if (clock > 165000000)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
rounded_rate = clk_round_rate(hdmi->tmds_clk, clock);
|
||||
if (rounded_rate > 0 &&
|
||||
max_t(unsigned long, rounded_rate, clock) -
|
||||
min_t(unsigned long, rounded_rate, clock) < diff)
|
||||
return MODE_OK;
|
||||
|
||||
return MODE_NOCLOCK;
|
||||
}
|
||||
|
||||
static int sun4i_hdmi_connector_atomic_check(struct drm_connector *connector,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_connector_state *conn_state =
|
||||
drm_atomic_get_new_connector_state(state, connector);
|
||||
struct drm_crtc *crtc = conn_state->crtc;
|
||||
struct drm_crtc_state *crtc_state = crtc->state;
|
||||
struct drm_display_mode *mode = &crtc_state->adjusted_mode;
|
||||
enum drm_mode_status status;
|
||||
|
||||
status = sun4i_hdmi_connector_clock_valid(connector, mode,
|
||||
mode->clock * 1000);
|
||||
if (status != MODE_OK)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum drm_mode_status
|
||||
sun4i_hdmi_connector_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
return sun4i_hdmi_connector_clock_valid(connector, mode,
|
||||
mode->clock * 1000);
|
||||
}
|
||||
|
||||
static int sun4i_hdmi_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector);
|
||||
@@ -251,6 +254,8 @@ static struct i2c_adapter *sun4i_hdmi_get_ddc(struct device *dev)
|
||||
}
|
||||
|
||||
static const struct drm_connector_helper_funcs sun4i_hdmi_connector_helper_funcs = {
|
||||
.atomic_check = sun4i_hdmi_connector_atomic_check,
|
||||
.mode_valid = sun4i_hdmi_connector_mode_valid,
|
||||
.get_modes = sun4i_hdmi_get_modes,
|
||||
};
|
||||
|
||||
|
||||
@@ -159,6 +159,7 @@ struct drm_framebuffer *tegra_fb_create(struct drm_device *drm,
|
||||
|
||||
if (gem->size < size) {
|
||||
err = -EINVAL;
|
||||
drm_gem_object_put(gem);
|
||||
goto unreference;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,10 +3,175 @@
|
||||
* Kunit test for drm_modes functions
|
||||
*/
|
||||
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#include <drm/drm_atomic_state_helper.h>
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_kunit_helpers.h>
|
||||
|
||||
#include <kunit/test.h>
|
||||
|
||||
struct drm_connector_init_priv {
|
||||
struct drm_device drm;
|
||||
struct drm_connector connector;
|
||||
struct i2c_adapter ddc;
|
||||
};
|
||||
|
||||
static const struct drm_connector_funcs dummy_funcs = {
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
|
||||
.reset = drm_atomic_helper_connector_reset,
|
||||
};
|
||||
|
||||
static int dummy_ddc_xfer(struct i2c_adapter *adapter,
|
||||
struct i2c_msg *msgs, int num)
|
||||
{
|
||||
return num;
|
||||
}
|
||||
|
||||
static u32 dummy_ddc_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
|
||||
}
|
||||
|
||||
static const struct i2c_algorithm dummy_ddc_algorithm = {
|
||||
.master_xfer = dummy_ddc_xfer,
|
||||
.functionality = dummy_ddc_func,
|
||||
};
|
||||
|
||||
static void i2c_del_adapter_wrapper(void *ptr)
|
||||
{
|
||||
struct i2c_adapter *adap = ptr;
|
||||
|
||||
i2c_del_adapter(adap);
|
||||
}
|
||||
|
||||
static int drm_test_connector_init(struct kunit *test)
|
||||
{
|
||||
struct drm_connector_init_priv *priv;
|
||||
struct device *dev;
|
||||
int ret;
|
||||
|
||||
dev = drm_kunit_helper_alloc_device(test);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
|
||||
|
||||
priv = drm_kunit_helper_alloc_drm_device(test, dev,
|
||||
struct drm_connector_init_priv, drm,
|
||||
DRIVER_MODESET | DRIVER_ATOMIC);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
|
||||
|
||||
strscpy(priv->ddc.name, "dummy-connector-ddc", sizeof(priv->ddc.name));
|
||||
priv->ddc.owner = THIS_MODULE;
|
||||
priv->ddc.algo = &dummy_ddc_algorithm;
|
||||
priv->ddc.dev.parent = dev;
|
||||
|
||||
ret = i2c_add_adapter(&priv->ddc);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
ret = kunit_add_action_or_reset(test, i2c_del_adapter_wrapper, &priv->ddc);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
test->priv = priv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that the registration of a bog standard connector works as
|
||||
* expected and doesn't report any error.
|
||||
*/
|
||||
static void drm_test_drmm_connector_init(struct kunit *test)
|
||||
{
|
||||
struct drm_connector_init_priv *priv = test->priv;
|
||||
int ret;
|
||||
|
||||
ret = drmm_connector_init(&priv->drm, &priv->connector,
|
||||
&dummy_funcs,
|
||||
DRM_MODE_CONNECTOR_HDMIA,
|
||||
&priv->ddc);
|
||||
KUNIT_EXPECT_EQ(test, ret, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that the registration of a connector without a DDC adapter
|
||||
* doesn't report any error.
|
||||
*/
|
||||
static void drm_test_drmm_connector_init_null_ddc(struct kunit *test)
|
||||
{
|
||||
struct drm_connector_init_priv *priv = test->priv;
|
||||
int ret;
|
||||
|
||||
ret = drmm_connector_init(&priv->drm, &priv->connector,
|
||||
&dummy_funcs,
|
||||
DRM_MODE_CONNECTOR_HDMIA,
|
||||
NULL);
|
||||
KUNIT_EXPECT_EQ(test, ret, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that the registration of a connector succeeds for all possible
|
||||
* connector types.
|
||||
*/
|
||||
static void drm_test_drmm_connector_init_type_valid(struct kunit *test)
|
||||
{
|
||||
struct drm_connector_init_priv *priv = test->priv;
|
||||
unsigned int connector_type = *(unsigned int *)test->param_value;
|
||||
int ret;
|
||||
|
||||
ret = drmm_connector_init(&priv->drm, &priv->connector,
|
||||
&dummy_funcs,
|
||||
connector_type,
|
||||
&priv->ddc);
|
||||
KUNIT_EXPECT_EQ(test, ret, 0);
|
||||
}
|
||||
|
||||
static const unsigned int drm_connector_init_type_valid_tests[] = {
|
||||
DRM_MODE_CONNECTOR_Unknown,
|
||||
DRM_MODE_CONNECTOR_VGA,
|
||||
DRM_MODE_CONNECTOR_DVII,
|
||||
DRM_MODE_CONNECTOR_DVID,
|
||||
DRM_MODE_CONNECTOR_DVIA,
|
||||
DRM_MODE_CONNECTOR_Composite,
|
||||
DRM_MODE_CONNECTOR_SVIDEO,
|
||||
DRM_MODE_CONNECTOR_LVDS,
|
||||
DRM_MODE_CONNECTOR_Component,
|
||||
DRM_MODE_CONNECTOR_9PinDIN,
|
||||
DRM_MODE_CONNECTOR_DisplayPort,
|
||||
DRM_MODE_CONNECTOR_HDMIA,
|
||||
DRM_MODE_CONNECTOR_HDMIB,
|
||||
DRM_MODE_CONNECTOR_TV,
|
||||
DRM_MODE_CONNECTOR_eDP,
|
||||
DRM_MODE_CONNECTOR_VIRTUAL,
|
||||
DRM_MODE_CONNECTOR_DSI,
|
||||
DRM_MODE_CONNECTOR_DPI,
|
||||
DRM_MODE_CONNECTOR_WRITEBACK,
|
||||
DRM_MODE_CONNECTOR_SPI,
|
||||
DRM_MODE_CONNECTOR_USB,
|
||||
};
|
||||
|
||||
static void drm_connector_init_type_desc(const unsigned int *type, char *desc)
|
||||
{
|
||||
sprintf(desc, "%s", drm_get_connector_type_name(*type));
|
||||
}
|
||||
|
||||
KUNIT_ARRAY_PARAM(drm_connector_init_type_valid,
|
||||
drm_connector_init_type_valid_tests,
|
||||
drm_connector_init_type_desc);
|
||||
|
||||
static struct kunit_case drmm_connector_init_tests[] = {
|
||||
KUNIT_CASE(drm_test_drmm_connector_init),
|
||||
KUNIT_CASE(drm_test_drmm_connector_init_null_ddc),
|
||||
KUNIT_CASE_PARAM(drm_test_drmm_connector_init_type_valid,
|
||||
drm_connector_init_type_valid_gen_params),
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct kunit_suite drmm_connector_init_test_suite = {
|
||||
.name = "drmm_connector_init",
|
||||
.init = drm_test_connector_init,
|
||||
.test_cases = drmm_connector_init_tests,
|
||||
};
|
||||
|
||||
struct drm_get_tv_mode_from_name_test {
|
||||
const char *name;
|
||||
enum drm_connector_tv_mode expected_mode;
|
||||
@@ -70,7 +235,10 @@ static struct kunit_suite drm_get_tv_mode_from_name_test_suite = {
|
||||
.test_cases = drm_get_tv_mode_from_name_tests,
|
||||
};
|
||||
|
||||
kunit_test_suite(drm_get_tv_mode_from_name_test_suite);
|
||||
kunit_test_suites(
|
||||
&drmm_connector_init_test_suite,
|
||||
&drm_get_tv_mode_from_name_test_suite
|
||||
);
|
||||
|
||||
MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_kunit_helpers.h>
|
||||
#include <drm/drm_managed.h>
|
||||
|
||||
@@ -14,6 +16,8 @@
|
||||
#define KUNIT_DEVICE_NAME "drm-kunit-mock-device"
|
||||
|
||||
static const struct drm_mode_config_funcs drm_mode_config_funcs = {
|
||||
.atomic_check = drm_atomic_helper_check,
|
||||
.atomic_commit = drm_atomic_helper_commit,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -161,5 +165,151 @@ drm_kunit_helper_atomic_state_alloc(struct kunit *test,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_kunit_helper_atomic_state_alloc);
|
||||
|
||||
static const uint32_t default_plane_formats[] = {
|
||||
DRM_FORMAT_XRGB8888,
|
||||
};
|
||||
|
||||
static const uint64_t default_plane_modifiers[] = {
|
||||
DRM_FORMAT_MOD_LINEAR,
|
||||
DRM_FORMAT_MOD_INVALID
|
||||
};
|
||||
|
||||
static const struct drm_plane_helper_funcs default_plane_helper_funcs = {
|
||||
};
|
||||
|
||||
static const struct drm_plane_funcs default_plane_funcs = {
|
||||
.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
|
||||
.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
|
||||
.reset = drm_atomic_helper_plane_reset,
|
||||
};
|
||||
|
||||
/**
|
||||
* drm_kunit_helper_create_primary_plane - Creates a mock primary plane for a KUnit test
|
||||
* @test: The test context object
|
||||
* @drm: The device to alloc the plane for
|
||||
* @funcs: Callbacks for the new plane. Optional.
|
||||
* @helper_funcs: Helpers callbacks for the new plane. Optional.
|
||||
* @formats: array of supported formats (DRM_FORMAT\_\*). Optional.
|
||||
* @num_formats: number of elements in @formats
|
||||
* @modifiers: array of struct drm_format modifiers terminated by
|
||||
* DRM_FORMAT_MOD_INVALID. Optional.
|
||||
*
|
||||
* This allocates and initializes a mock struct &drm_plane meant to be
|
||||
* part of a mock device for a KUnit test.
|
||||
*
|
||||
* Resources will be cleaned up automatically.
|
||||
*
|
||||
* @funcs will default to the default helpers implementations.
|
||||
* @helper_funcs will default to an empty implementation. @formats will
|
||||
* default to XRGB8888 only. @modifiers will default to a linear
|
||||
* modifier only.
|
||||
*
|
||||
* Returns:
|
||||
* A pointer to the new plane, or an ERR_PTR() otherwise.
|
||||
*/
|
||||
struct drm_plane *
|
||||
drm_kunit_helper_create_primary_plane(struct kunit *test,
|
||||
struct drm_device *drm,
|
||||
const struct drm_plane_funcs *funcs,
|
||||
const struct drm_plane_helper_funcs *helper_funcs,
|
||||
const uint32_t *formats,
|
||||
unsigned int num_formats,
|
||||
const uint64_t *modifiers)
|
||||
{
|
||||
struct drm_plane *plane;
|
||||
|
||||
if (!funcs)
|
||||
funcs = &default_plane_funcs;
|
||||
|
||||
if (!helper_funcs)
|
||||
helper_funcs = &default_plane_helper_funcs;
|
||||
|
||||
if (!formats || !num_formats) {
|
||||
formats = default_plane_formats;
|
||||
num_formats = ARRAY_SIZE(default_plane_formats);
|
||||
}
|
||||
|
||||
if (!modifiers)
|
||||
modifiers = default_plane_modifiers;
|
||||
|
||||
plane = __drmm_universal_plane_alloc(drm,
|
||||
sizeof(struct drm_plane), 0,
|
||||
0,
|
||||
funcs,
|
||||
formats,
|
||||
num_formats,
|
||||
default_plane_modifiers,
|
||||
DRM_PLANE_TYPE_PRIMARY,
|
||||
NULL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane);
|
||||
|
||||
drm_plane_helper_add(plane, helper_funcs);
|
||||
|
||||
return plane;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_kunit_helper_create_primary_plane);
|
||||
|
||||
static const struct drm_crtc_helper_funcs default_crtc_helper_funcs = {
|
||||
};
|
||||
|
||||
static const struct drm_crtc_funcs default_crtc_funcs = {
|
||||
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
|
||||
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
|
||||
.reset = drm_atomic_helper_crtc_reset,
|
||||
};
|
||||
|
||||
/**
|
||||
* drm_kunit_helper_create_crtc - Creates a mock CRTC for a KUnit test
|
||||
* @test: The test context object
|
||||
* @drm: The device to alloc the plane for
|
||||
* @primary: Primary plane for CRTC
|
||||
* @cursor: Cursor plane for CRTC. Optional.
|
||||
* @funcs: Callbacks for the new plane. Optional.
|
||||
* @helper_funcs: Helpers callbacks for the new plane. Optional.
|
||||
*
|
||||
* This allocates and initializes a mock struct &drm_crtc meant to be
|
||||
* part of a mock device for a KUnit test.
|
||||
*
|
||||
* Resources will be cleaned up automatically.
|
||||
*
|
||||
* @funcs will default to the default helpers implementations.
|
||||
* @helper_funcs will default to an empty implementation.
|
||||
*
|
||||
* Returns:
|
||||
* A pointer to the new CRTC, or an ERR_PTR() otherwise.
|
||||
*/
|
||||
struct drm_crtc *
|
||||
drm_kunit_helper_create_crtc(struct kunit *test,
|
||||
struct drm_device *drm,
|
||||
struct drm_plane *primary,
|
||||
struct drm_plane *cursor,
|
||||
const struct drm_crtc_funcs *funcs,
|
||||
const struct drm_crtc_helper_funcs *helper_funcs)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
int ret;
|
||||
|
||||
if (!funcs)
|
||||
funcs = &default_crtc_funcs;
|
||||
|
||||
if (!helper_funcs)
|
||||
helper_funcs = &default_crtc_helper_funcs;
|
||||
|
||||
crtc = drmm_kzalloc(drm, sizeof(*crtc), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, crtc);
|
||||
|
||||
ret = drmm_crtc_init_with_planes(drm, crtc,
|
||||
primary,
|
||||
cursor,
|
||||
funcs,
|
||||
NULL);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
drm_crtc_helper_add(crtc, helper_funcs);
|
||||
|
||||
return crtc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_kunit_helper_create_crtc);
|
||||
|
||||
MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -265,6 +265,16 @@ static void tidss_crtc_atomic_disable(struct drm_crtc *crtc,
|
||||
|
||||
reinit_completion(&tcrtc->framedone_completion);
|
||||
|
||||
/*
|
||||
* If a layer is left enabled when the videoport is disabled, and the
|
||||
* vid pipeline that was used for the layer is taken into use on
|
||||
* another videoport, the DSS will report sync lost issues. Disable all
|
||||
* the layers here as a work-around.
|
||||
*/
|
||||
for (u32 layer = 0; layer < tidss->feat->num_planes; layer++)
|
||||
dispc_ovr_enable_layer(tidss->dispc, tcrtc->hw_videoport, layer,
|
||||
false);
|
||||
|
||||
dispc_vp_disable(tidss->dispc, tcrtc->hw_videoport);
|
||||
|
||||
if (!wait_for_completion_timeout(&tcrtc->framedone_completion,
|
||||
|
||||
@@ -213,7 +213,7 @@ struct tidss_plane *tidss_plane_create(struct tidss_device *tidss,
|
||||
|
||||
drm_plane_helper_add(&tplane->plane, &tidss_plane_helper_funcs);
|
||||
|
||||
drm_plane_create_zpos_property(&tplane->plane, hw_plane_id, 0,
|
||||
drm_plane_create_zpos_property(&tplane->plane, tidss->num_planes, 0,
|
||||
num_planes - 1);
|
||||
|
||||
ret = drm_plane_create_color_properties(&tplane->plane,
|
||||
|
||||
@@ -40,7 +40,7 @@ void v3d_free_object(struct drm_gem_object *obj)
|
||||
|
||||
mutex_lock(&v3d->bo_lock);
|
||||
v3d->bo_stats.num_allocated--;
|
||||
v3d->bo_stats.pages_allocated -= obj->size >> PAGE_SHIFT;
|
||||
v3d->bo_stats.pages_allocated -= obj->size >> V3D_MMU_PAGE_SHIFT;
|
||||
mutex_unlock(&v3d->bo_lock);
|
||||
|
||||
spin_lock(&v3d->mm_lock);
|
||||
@@ -109,8 +109,8 @@ v3d_bo_create_finish(struct drm_gem_object *obj)
|
||||
* lifetime of the BO.
|
||||
*/
|
||||
ret = drm_mm_insert_node_generic(&v3d->mm, &bo->node,
|
||||
obj->size >> PAGE_SHIFT,
|
||||
GMP_GRANULARITY >> PAGE_SHIFT, 0, 0);
|
||||
obj->size >> V3D_MMU_PAGE_SHIFT,
|
||||
GMP_GRANULARITY >> V3D_MMU_PAGE_SHIFT, 0, 0);
|
||||
spin_unlock(&v3d->mm_lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -118,7 +118,7 @@ v3d_bo_create_finish(struct drm_gem_object *obj)
|
||||
/* Track stats for /debug/dri/n/bo_stats. */
|
||||
mutex_lock(&v3d->bo_lock);
|
||||
v3d->bo_stats.num_allocated++;
|
||||
v3d->bo_stats.pages_allocated += obj->size >> PAGE_SHIFT;
|
||||
v3d->bo_stats.pages_allocated += obj->size >> V3D_MMU_PAGE_SHIFT;
|
||||
mutex_unlock(&v3d->bo_lock);
|
||||
|
||||
v3d_mmu_insert_ptes(bo);
|
||||
@@ -201,7 +201,7 @@ int v3d_create_bo_ioctl(struct drm_device *dev, void *data,
|
||||
if (IS_ERR(bo))
|
||||
return PTR_ERR(bo);
|
||||
|
||||
args->offset = bo->node.start << PAGE_SHIFT;
|
||||
args->offset = bo->node.start << V3D_MMU_PAGE_SHIFT;
|
||||
|
||||
ret = drm_gem_handle_create(file_priv, &bo->base.base, &args->handle);
|
||||
drm_gem_object_put(&bo->base.base);
|
||||
@@ -246,7 +246,7 @@ int v3d_get_bo_offset_ioctl(struct drm_device *dev, void *data,
|
||||
}
|
||||
bo = to_v3d_bo(gem_obj);
|
||||
|
||||
args->offset = bo->node.start << PAGE_SHIFT;
|
||||
args->offset = bo->node.start << V3D_MMU_PAGE_SHIFT;
|
||||
|
||||
drm_gem_object_put(gem_obj);
|
||||
return 0;
|
||||
|
||||
@@ -219,7 +219,7 @@ static int v3d_debugfs_bo_stats(struct seq_file *m, void *unused)
|
||||
seq_printf(m, "allocated bos: %d\n",
|
||||
v3d->bo_stats.num_allocated);
|
||||
seq_printf(m, "allocated bo size (kb): %ld\n",
|
||||
(long)v3d->bo_stats.pages_allocated << (PAGE_SHIFT - 10));
|
||||
(long)v3d->bo_stats.pages_allocated << (V3D_MMU_PAGE_SHIFT - 10));
|
||||
mutex_unlock(&v3d->bo_lock);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -19,6 +19,8 @@ struct reset_control;
|
||||
|
||||
#define GMP_GRANULARITY (128 * 1024)
|
||||
|
||||
#define V3D_MMU_PAGE_SHIFT 12
|
||||
|
||||
#define V3D_MAX_QUEUES (V3D_CPU + 1)
|
||||
|
||||
static inline char *v3d_queue_to_string(enum v3d_queue queue)
|
||||
|
||||
@@ -70,7 +70,7 @@ v3d_overflow_mem_work(struct work_struct *work)
|
||||
list_add_tail(&bo->unref_head, &v3d->bin_job->render->unref_list);
|
||||
spin_unlock_irqrestore(&v3d->job_lock, irqflags);
|
||||
|
||||
V3D_CORE_WRITE(0, V3D_PTB_BPOA, bo->node.start << PAGE_SHIFT);
|
||||
V3D_CORE_WRITE(0, V3D_PTB_BPOA, bo->node.start << V3D_MMU_PAGE_SHIFT);
|
||||
V3D_CORE_WRITE(0, V3D_PTB_BPOS, obj->size);
|
||||
|
||||
out:
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
#include "v3d_drv.h"
|
||||
#include "v3d_regs.h"
|
||||
|
||||
#define V3D_MMU_PAGE_SHIFT 12
|
||||
|
||||
/* Note: All PTEs for the 1MB superpage must be filled with the
|
||||
* superpage bit set.
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
* by Eric Miao <eric.miao@marvell.com>
|
||||
*/
|
||||
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
@@ -100,6 +100,8 @@ struct drm_dp_vsc_sdp {
|
||||
|
||||
void drm_dp_vsc_sdp_log(struct drm_printer *p, const struct drm_dp_vsc_sdp *vsc);
|
||||
|
||||
bool drm_dp_vsc_sdp_supported(struct drm_dp_aux *aux, const u8 dpcd[DP_RECEIVER_CAP_SIZE]);
|
||||
|
||||
int drm_dp_psr_setup_time(const u8 psr_cap[EDP_PSR_RECEIVER_CAP_SIZE]);
|
||||
|
||||
static inline int
|
||||
@@ -462,9 +464,15 @@ struct drm_dp_aux {
|
||||
* @is_remote: Is this AUX CH actually using sideband messaging.
|
||||
*/
|
||||
bool is_remote;
|
||||
|
||||
/**
|
||||
* @powered_down: If true then the remote endpoint is powered down.
|
||||
*/
|
||||
bool powered_down;
|
||||
};
|
||||
|
||||
int drm_dp_dpcd_probe(struct drm_dp_aux *aux, unsigned int offset);
|
||||
void drm_dp_dpcd_set_powered(struct drm_dp_aux *aux, bool powered);
|
||||
ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset,
|
||||
void *buffer, size_t size);
|
||||
ssize_t drm_dp_dpcd_write(struct drm_dp_aux *aux, unsigned int offset,
|
||||
@@ -813,4 +821,6 @@ int drm_dp_bw_overhead(int lane_count, int hactive,
|
||||
int drm_dp_bw_channel_coding_efficiency(bool is_uhbr);
|
||||
int drm_dp_max_dprx_data_rate(int max_link_rate, int max_lanes);
|
||||
|
||||
ssize_t drm_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc, struct dp_sdp *sdp);
|
||||
|
||||
#endif /* _DRM_DP_HELPER_H_ */
|
||||
|
||||
@@ -3,11 +3,17 @@
|
||||
#ifndef DRM_KUNIT_HELPERS_H_
|
||||
#define DRM_KUNIT_HELPERS_H_
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
|
||||
#include <linux/device.h>
|
||||
|
||||
#include <kunit/test.h>
|
||||
|
||||
struct drm_crtc_funcs;
|
||||
struct drm_crtc_helper_funcs;
|
||||
struct drm_device;
|
||||
struct drm_plane_funcs;
|
||||
struct drm_plane_helper_funcs;
|
||||
struct kunit;
|
||||
|
||||
struct device *drm_kunit_helper_alloc_device(struct kunit *test);
|
||||
@@ -97,4 +103,21 @@ drm_kunit_helper_atomic_state_alloc(struct kunit *test,
|
||||
struct drm_device *drm,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
|
||||
struct drm_plane *
|
||||
drm_kunit_helper_create_primary_plane(struct kunit *test,
|
||||
struct drm_device *drm,
|
||||
const struct drm_plane_funcs *funcs,
|
||||
const struct drm_plane_helper_funcs *helper_funcs,
|
||||
const uint32_t *formats,
|
||||
unsigned int num_formats,
|
||||
const uint64_t *modifiers);
|
||||
|
||||
struct drm_crtc *
|
||||
drm_kunit_helper_create_crtc(struct kunit *test,
|
||||
struct drm_device *drm,
|
||||
struct drm_plane *primary,
|
||||
struct drm_plane *cursor,
|
||||
const struct drm_crtc_funcs *funcs,
|
||||
const struct drm_crtc_helper_funcs *helper_funcs);
|
||||
|
||||
#endif // DRM_KUNIT_HELPERS_H_
|
||||
|
||||
@@ -2,28 +2,30 @@
|
||||
#ifndef _LINUX_FB_H
|
||||
#define _LINUX_FB_H
|
||||
|
||||
#include <linux/refcount.h>
|
||||
#include <linux/kgdb.h>
|
||||
#include <uapi/linux/fb.h>
|
||||
|
||||
#define FBIO_CURSOR _IOWR('F', 0x08, struct fb_cursor_user)
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/refcount.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <asm/fb.h>
|
||||
|
||||
struct vm_area_struct;
|
||||
struct fb_info;
|
||||
struct backlight_device;
|
||||
struct device;
|
||||
struct file;
|
||||
struct videomode;
|
||||
struct device_node;
|
||||
struct fb_info;
|
||||
struct file;
|
||||
struct i2c_adapter;
|
||||
struct inode;
|
||||
struct module;
|
||||
struct notifier_block;
|
||||
struct page;
|
||||
struct videomode;
|
||||
struct vm_area_struct;
|
||||
|
||||
/* Definitions below are used in the parsed monitor specs */
|
||||
#define FB_DPMS_ACTIVE_OFF 1
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
1024x768.S: EDID data set for standard 1024x768 60 Hz monitor
|
||||
|
||||
Copyright (C) 2011 Carsten Emde <C.Emde@osadl.org>
|
||||
|
||||
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/* EDID */
|
||||
#define VERSION 1
|
||||
#define REVISION 3
|
||||
|
||||
/* Display */
|
||||
#define CLOCK 65000 /* kHz */
|
||||
#define XPIX 1024
|
||||
#define YPIX 768
|
||||
#define XY_RATIO XY_RATIO_4_3
|
||||
#define XBLANK 320
|
||||
#define YBLANK 38
|
||||
#define XOFFSET 8
|
||||
#define XPULSE 144
|
||||
#define YOFFSET 3
|
||||
#define YPULSE 6
|
||||
#define DPI 72
|
||||
#define VFREQ 60 /* Hz */
|
||||
#define TIMING_NAME "Linux XGA"
|
||||
#define ESTABLISHED_TIMING2_BITS 0x08 /* Bit 3 -> 1024x768 @60 Hz */
|
||||
#define HSYNC_POL 0
|
||||
#define VSYNC_POL 0
|
||||
|
||||
#include "edid.S"
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
1280x1024.S: EDID data set for standard 1280x1024 60 Hz monitor
|
||||
|
||||
Copyright (C) 2011 Carsten Emde <C.Emde@osadl.org>
|
||||
|
||||
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/* EDID */
|
||||
#define VERSION 1
|
||||
#define REVISION 3
|
||||
|
||||
/* Display */
|
||||
#define CLOCK 108000 /* kHz */
|
||||
#define XPIX 1280
|
||||
#define YPIX 1024
|
||||
#define XY_RATIO XY_RATIO_5_4
|
||||
#define XBLANK 408
|
||||
#define YBLANK 42
|
||||
#define XOFFSET 48
|
||||
#define XPULSE 112
|
||||
#define YOFFSET 1
|
||||
#define YPULSE 3
|
||||
#define DPI 72
|
||||
#define VFREQ 60 /* Hz */
|
||||
#define TIMING_NAME "Linux SXGA"
|
||||
/* No ESTABLISHED_TIMINGx_BITS */
|
||||
#define HSYNC_POL 1
|
||||
#define VSYNC_POL 1
|
||||
|
||||
#include "edid.S"
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
1600x1200.S: EDID data set for standard 1600x1200 60 Hz monitor
|
||||
|
||||
Copyright (C) 2013 Carsten Emde <C.Emde@osadl.org>
|
||||
|
||||
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/* EDID */
|
||||
#define VERSION 1
|
||||
#define REVISION 3
|
||||
|
||||
/* Display */
|
||||
#define CLOCK 162000 /* kHz */
|
||||
#define XPIX 1600
|
||||
#define YPIX 1200
|
||||
#define XY_RATIO XY_RATIO_4_3
|
||||
#define XBLANK 560
|
||||
#define YBLANK 50
|
||||
#define XOFFSET 64
|
||||
#define XPULSE 192
|
||||
#define YOFFSET 1
|
||||
#define YPULSE 3
|
||||
#define DPI 72
|
||||
#define VFREQ 60 /* Hz */
|
||||
#define TIMING_NAME "Linux UXGA"
|
||||
/* No ESTABLISHED_TIMINGx_BITS */
|
||||
#define HSYNC_POL 1
|
||||
#define VSYNC_POL 1
|
||||
|
||||
#include "edid.S"
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
1680x1050.S: EDID data set for standard 1680x1050 60 Hz monitor
|
||||
|
||||
Copyright (C) 2012 Carsten Emde <C.Emde@osadl.org>
|
||||
|
||||
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/* EDID */
|
||||
#define VERSION 1
|
||||
#define REVISION 3
|
||||
|
||||
/* Display */
|
||||
#define CLOCK 146250 /* kHz */
|
||||
#define XPIX 1680
|
||||
#define YPIX 1050
|
||||
#define XY_RATIO XY_RATIO_16_10
|
||||
#define XBLANK 560
|
||||
#define YBLANK 39
|
||||
#define XOFFSET 104
|
||||
#define XPULSE 176
|
||||
#define YOFFSET 3
|
||||
#define YPULSE 6
|
||||
#define DPI 96
|
||||
#define VFREQ 60 /* Hz */
|
||||
#define TIMING_NAME "Linux WSXGA"
|
||||
/* No ESTABLISHED_TIMINGx_BITS */
|
||||
#define HSYNC_POL 1
|
||||
#define VSYNC_POL 1
|
||||
|
||||
#include "edid.S"
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
1920x1080.S: EDID data set for standard 1920x1080 60 Hz monitor
|
||||
|
||||
Copyright (C) 2012 Carsten Emde <C.Emde@osadl.org>
|
||||
|
||||
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/* EDID */
|
||||
#define VERSION 1
|
||||
#define REVISION 3
|
||||
|
||||
/* Display */
|
||||
#define CLOCK 148500 /* kHz */
|
||||
#define XPIX 1920
|
||||
#define YPIX 1080
|
||||
#define XY_RATIO XY_RATIO_16_9
|
||||
#define XBLANK 280
|
||||
#define YBLANK 45
|
||||
#define XOFFSET 88
|
||||
#define XPULSE 44
|
||||
#define YOFFSET 4
|
||||
#define YPULSE 5
|
||||
#define DPI 96
|
||||
#define VFREQ 60 /* Hz */
|
||||
#define TIMING_NAME "Linux FHD"
|
||||
/* No ESTABLISHED_TIMINGx_BITS */
|
||||
#define HSYNC_POL 1
|
||||
#define VSYNC_POL 1
|
||||
|
||||
#include "edid.S"
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
800x600.S: EDID data set for standard 800x600 60 Hz monitor
|
||||
|
||||
Copyright (C) 2011 Carsten Emde <C.Emde@osadl.org>
|
||||
Copyright (C) 2014 Linaro Limited
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/* EDID */
|
||||
#define VERSION 1
|
||||
#define REVISION 3
|
||||
|
||||
/* Display */
|
||||
#define CLOCK 40000 /* kHz */
|
||||
#define XPIX 800
|
||||
#define YPIX 600
|
||||
#define XY_RATIO XY_RATIO_4_3
|
||||
#define XBLANK 256
|
||||
#define YBLANK 28
|
||||
#define XOFFSET 40
|
||||
#define XPULSE 128
|
||||
#define YOFFSET 1
|
||||
#define YPULSE 4
|
||||
#define DPI 72
|
||||
#define VFREQ 60 /* Hz */
|
||||
#define TIMING_NAME "Linux SVGA"
|
||||
#define ESTABLISHED_TIMING1_BITS 0x01 /* Bit 0: 800x600 @ 60Hz */
|
||||
#define HSYNC_POL 1
|
||||
#define VSYNC_POL 1
|
||||
|
||||
#include "edid.S"
|
||||
@@ -1,37 +0,0 @@
|
||||
|
||||
SOURCES := $(wildcard [0-9]*x[0-9]*.S)
|
||||
|
||||
BIN := $(patsubst %.S, %.bin, $(SOURCES))
|
||||
|
||||
IHEX := $(patsubst %.S, %.bin.ihex, $(SOURCES))
|
||||
|
||||
CODE := $(patsubst %.S, %.c, $(SOURCES))
|
||||
|
||||
all: $(BIN) $(IHEX) $(CODE)
|
||||
|
||||
clean:
|
||||
@rm -f *.o *.bin.ihex *.bin *.c
|
||||
|
||||
%.o: %.S
|
||||
@cc -c $^
|
||||
|
||||
%.bin.nocrc: %.o
|
||||
@objcopy -Obinary $^ $@
|
||||
|
||||
%.crc: %.bin.nocrc
|
||||
@list=$$(for i in `seq 1 127`; do head -c$$i $^ | tail -c1 \
|
||||
| hexdump -v -e '/1 "%02X+"'; done); \
|
||||
echo "ibase=16;100-($${list%?})%100" | bc >$@
|
||||
|
||||
%.p: %.crc %.S
|
||||
@cc -c -DCRC="$$(cat $*.crc)" -o $@ $*.S
|
||||
|
||||
%.bin: %.p
|
||||
@objcopy -Obinary $^ $@
|
||||
|
||||
%.bin.ihex: %.p
|
||||
@objcopy -Oihex $^ $@
|
||||
@dos2unix $@ 2>/dev/null
|
||||
|
||||
%.c: %.bin
|
||||
@echo "{" >$@; hexdump -f hex $^ >>$@; echo "};" >>$@
|
||||
@@ -1,274 +0,0 @@
|
||||
/*
|
||||
edid.S: EDID data template
|
||||
|
||||
Copyright (C) 2012 Carsten Emde <C.Emde@osadl.org>
|
||||
|
||||
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
/* Manufacturer */
|
||||
#define MFG_LNX1 'L'
|
||||
#define MFG_LNX2 'N'
|
||||
#define MFG_LNX3 'X'
|
||||
#define SERIAL 0
|
||||
#define YEAR 2012
|
||||
#define WEEK 5
|
||||
|
||||
/* EDID 1.3 standard definitions */
|
||||
#define XY_RATIO_16_10 0b00
|
||||
#define XY_RATIO_4_3 0b01
|
||||
#define XY_RATIO_5_4 0b10
|
||||
#define XY_RATIO_16_9 0b11
|
||||
|
||||
/* Provide defaults for the timing bits */
|
||||
#ifndef ESTABLISHED_TIMING1_BITS
|
||||
#define ESTABLISHED_TIMING1_BITS 0x00
|
||||
#endif
|
||||
#ifndef ESTABLISHED_TIMING2_BITS
|
||||
#define ESTABLISHED_TIMING2_BITS 0x00
|
||||
#endif
|
||||
#ifndef ESTABLISHED_TIMING3_BITS
|
||||
#define ESTABLISHED_TIMING3_BITS 0x00
|
||||
#endif
|
||||
|
||||
#define mfgname2id(v1,v2,v3) \
|
||||
((((v1-'@')&0x1f)<<10)+(((v2-'@')&0x1f)<<5)+((v3-'@')&0x1f))
|
||||
#define swap16(v1) ((v1>>8)+((v1&0xff)<<8))
|
||||
#define lsbs2(v1,v2) (((v1&0x0f)<<4)+(v2&0x0f))
|
||||
#define msbs2(v1,v2) ((((v1>>8)&0x0f)<<4)+((v2>>8)&0x0f))
|
||||
#define msbs4(v1,v2,v3,v4) \
|
||||
((((v1>>8)&0x03)<<6)+(((v2>>8)&0x03)<<4)+\
|
||||
(((v3>>4)&0x03)<<2)+((v4>>4)&0x03))
|
||||
#define pixdpi2mm(pix,dpi) ((pix*25)/dpi)
|
||||
#define xsize pixdpi2mm(XPIX,DPI)
|
||||
#define ysize pixdpi2mm(YPIX,DPI)
|
||||
|
||||
.data
|
||||
|
||||
/* Fixed header pattern */
|
||||
header: .byte 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00
|
||||
|
||||
mfg_id: .hword swap16(mfgname2id(MFG_LNX1, MFG_LNX2, MFG_LNX3))
|
||||
|
||||
prod_code: .hword 0
|
||||
|
||||
/* Serial number. 32 bits, little endian. */
|
||||
serial_number: .long SERIAL
|
||||
|
||||
/* Week of manufacture */
|
||||
week: .byte WEEK
|
||||
|
||||
/* Year of manufacture, less 1990. (1990-2245)
|
||||
If week=255, it is the model year instead */
|
||||
year: .byte YEAR-1990
|
||||
|
||||
version: .byte VERSION /* EDID version, usually 1 (for 1.3) */
|
||||
revision: .byte REVISION /* EDID revision, usually 3 (for 1.3) */
|
||||
|
||||
/* If Bit 7=1 Digital input. If set, the following bit definitions apply:
|
||||
Bits 6-1 Reserved, must be 0
|
||||
Bit 0 Signal is compatible with VESA DFP 1.x TMDS CRGB,
|
||||
1 pixel per clock, up to 8 bits per color, MSB aligned,
|
||||
If Bit 7=0 Analog input. If clear, the following bit definitions apply:
|
||||
Bits 6-5 Video white and sync levels, relative to blank
|
||||
00=+0.7/-0.3 V; 01=+0.714/-0.286 V;
|
||||
10=+1.0/-0.4 V; 11=+0.7/0 V
|
||||
Bit 4 Blank-to-black setup (pedestal) expected
|
||||
Bit 3 Separate sync supported
|
||||
Bit 2 Composite sync (on HSync) supported
|
||||
Bit 1 Sync on green supported
|
||||
Bit 0 VSync pulse must be serrated when somposite or
|
||||
sync-on-green is used. */
|
||||
video_parms: .byte 0x6d
|
||||
|
||||
/* Maximum horizontal image size, in centimetres
|
||||
(max 292 cm/115 in at 16:9 aspect ratio) */
|
||||
max_hor_size: .byte xsize/10
|
||||
|
||||
/* Maximum vertical image size, in centimetres.
|
||||
If either byte is 0, undefined (e.g. projector) */
|
||||
max_vert_size: .byte ysize/10
|
||||
|
||||
/* Display gamma, minus 1, times 100 (range 1.00-3.5 */
|
||||
gamma: .byte 120
|
||||
|
||||
/* Bit 7 DPMS standby supported
|
||||
Bit 6 DPMS suspend supported
|
||||
Bit 5 DPMS active-off supported
|
||||
Bits 4-3 Display type: 00=monochrome; 01=RGB colour;
|
||||
10=non-RGB multicolour; 11=undefined
|
||||
Bit 2 Standard sRGB colour space. Bytes 25-34 must contain
|
||||
sRGB standard values.
|
||||
Bit 1 Preferred timing mode specified in descriptor block 1.
|
||||
Bit 0 GTF supported with default parameter values. */
|
||||
dsp_features: .byte 0xea
|
||||
|
||||
/* Chromaticity coordinates. */
|
||||
/* Red and green least-significant bits
|
||||
Bits 7-6 Red x value least-significant 2 bits
|
||||
Bits 5-4 Red y value least-significant 2 bits
|
||||
Bits 3-2 Green x value lst-significant 2 bits
|
||||
Bits 1-0 Green y value least-significant 2 bits */
|
||||
red_green_lsb: .byte 0x5e
|
||||
|
||||
/* Blue and white least-significant 2 bits */
|
||||
blue_white_lsb: .byte 0xc0
|
||||
|
||||
/* Red x value most significant 8 bits.
|
||||
0-255 encodes 0-0.996 (255/256); 0-0.999 (1023/1024) with lsbits */
|
||||
red_x_msb: .byte 0xa4
|
||||
|
||||
/* Red y value most significant 8 bits */
|
||||
red_y_msb: .byte 0x59
|
||||
|
||||
/* Green x and y value most significant 8 bits */
|
||||
green_x_y_msb: .byte 0x4a,0x98
|
||||
|
||||
/* Blue x and y value most significant 8 bits */
|
||||
blue_x_y_msb: .byte 0x25,0x20
|
||||
|
||||
/* Default white point x and y value most significant 8 bits */
|
||||
white_x_y_msb: .byte 0x50,0x54
|
||||
|
||||
/* Established timings */
|
||||
/* Bit 7 720x400 @ 70 Hz
|
||||
Bit 6 720x400 @ 88 Hz
|
||||
Bit 5 640x480 @ 60 Hz
|
||||
Bit 4 640x480 @ 67 Hz
|
||||
Bit 3 640x480 @ 72 Hz
|
||||
Bit 2 640x480 @ 75 Hz
|
||||
Bit 1 800x600 @ 56 Hz
|
||||
Bit 0 800x600 @ 60 Hz */
|
||||
estbl_timing1: .byte ESTABLISHED_TIMING1_BITS
|
||||
|
||||
/* Bit 7 800x600 @ 72 Hz
|
||||
Bit 6 800x600 @ 75 Hz
|
||||
Bit 5 832x624 @ 75 Hz
|
||||
Bit 4 1024x768 @ 87 Hz, interlaced (1024x768)
|
||||
Bit 3 1024x768 @ 60 Hz
|
||||
Bit 2 1024x768 @ 72 Hz
|
||||
Bit 1 1024x768 @ 75 Hz
|
||||
Bit 0 1280x1024 @ 75 Hz */
|
||||
estbl_timing2: .byte ESTABLISHED_TIMING2_BITS
|
||||
|
||||
/* Bit 7 1152x870 @ 75 Hz (Apple Macintosh II)
|
||||
Bits 6-0 Other manufacturer-specific display mod */
|
||||
estbl_timing3: .byte ESTABLISHED_TIMING3_BITS
|
||||
|
||||
/* Standard timing */
|
||||
/* X resolution, less 31, divided by 8 (256-2288 pixels) */
|
||||
std_xres: .byte (XPIX/8)-31
|
||||
/* Y resolution, X:Y pixel ratio
|
||||
Bits 7-6 X:Y pixel ratio: 00=16:10; 01=4:3; 10=5:4; 11=16:9.
|
||||
Bits 5-0 Vertical frequency, less 60 (60-123 Hz) */
|
||||
std_vres: .byte (XY_RATIO<<6)+VFREQ-60
|
||||
.fill 7,2,0x0101 /* Unused */
|
||||
|
||||
descriptor1:
|
||||
/* Pixel clock in 10 kHz units. (0.-655.35 MHz, little-endian) */
|
||||
clock: .hword CLOCK/10
|
||||
|
||||
/* Horizontal active pixels 8 lsbits (0-4095) */
|
||||
x_act_lsb: .byte XPIX&0xff
|
||||
/* Horizontal blanking pixels 8 lsbits (0-4095)
|
||||
End of active to start of next active. */
|
||||
x_blk_lsb: .byte XBLANK&0xff
|
||||
/* Bits 7-4 Horizontal active pixels 4 msbits
|
||||
Bits 3-0 Horizontal blanking pixels 4 msbits */
|
||||
x_msbs: .byte msbs2(XPIX,XBLANK)
|
||||
|
||||
/* Vertical active lines 8 lsbits (0-4095) */
|
||||
y_act_lsb: .byte YPIX&0xff
|
||||
/* Vertical blanking lines 8 lsbits (0-4095) */
|
||||
y_blk_lsb: .byte YBLANK&0xff
|
||||
/* Bits 7-4 Vertical active lines 4 msbits
|
||||
Bits 3-0 Vertical blanking lines 4 msbits */
|
||||
y_msbs: .byte msbs2(YPIX,YBLANK)
|
||||
|
||||
/* Horizontal sync offset pixels 8 lsbits (0-1023) From blanking start */
|
||||
x_snc_off_lsb: .byte XOFFSET&0xff
|
||||
/* Horizontal sync pulse width pixels 8 lsbits (0-1023) */
|
||||
x_snc_pls_lsb: .byte XPULSE&0xff
|
||||
/* Bits 7-4 Vertical sync offset lines 4 lsbits (0-63)
|
||||
Bits 3-0 Vertical sync pulse width lines 4 lsbits (0-63) */
|
||||
y_snc_lsb: .byte lsbs2(YOFFSET, YPULSE)
|
||||
/* Bits 7-6 Horizontal sync offset pixels 2 msbits
|
||||
Bits 5-4 Horizontal sync pulse width pixels 2 msbits
|
||||
Bits 3-2 Vertical sync offset lines 2 msbits
|
||||
Bits 1-0 Vertical sync pulse width lines 2 msbits */
|
||||
xy_snc_msbs: .byte msbs4(XOFFSET,XPULSE,YOFFSET,YPULSE)
|
||||
|
||||
/* Horizontal display size, mm, 8 lsbits (0-4095 mm, 161 in) */
|
||||
x_dsp_size: .byte xsize&0xff
|
||||
|
||||
/* Vertical display size, mm, 8 lsbits (0-4095 mm, 161 in) */
|
||||
y_dsp_size: .byte ysize&0xff
|
||||
|
||||
/* Bits 7-4 Horizontal display size, mm, 4 msbits
|
||||
Bits 3-0 Vertical display size, mm, 4 msbits */
|
||||
dsp_size_mbsb: .byte msbs2(xsize,ysize)
|
||||
|
||||
/* Horizontal border pixels (each side; total is twice this) */
|
||||
x_border: .byte 0
|
||||
/* Vertical border lines (each side; total is twice this) */
|
||||
y_border: .byte 0
|
||||
|
||||
/* Bit 7 Interlaced
|
||||
Bits 6-5 Stereo mode: 00=No stereo; other values depend on bit 0:
|
||||
Bit 0=0: 01=Field sequential, sync=1 during right; 10=similar,
|
||||
sync=1 during left; 11=4-way interleaved stereo
|
||||
Bit 0=1 2-way interleaved stereo: 01=Right image on even lines;
|
||||
10=Left image on even lines; 11=side-by-side
|
||||
Bits 4-3 Sync type: 00=Analog composite; 01=Bipolar analog composite;
|
||||
10=Digital composite (on HSync); 11=Digital separate
|
||||
Bit 2 If digital separate: Vertical sync polarity (1=positive)
|
||||
Other types: VSync serrated (HSync during VSync)
|
||||
Bit 1 If analog sync: Sync on all 3 RGB lines (else green only)
|
||||
Digital: HSync polarity (1=positive)
|
||||
Bit 0 2-way line-interleaved stereo, if bits 4-3 are not 00. */
|
||||
features: .byte 0x18+(VSYNC_POL<<2)+(HSYNC_POL<<1)
|
||||
|
||||
descriptor2: .byte 0,0 /* Not a detailed timing descriptor */
|
||||
.byte 0 /* Must be zero */
|
||||
.byte 0xff /* Descriptor is monitor serial number (text) */
|
||||
.byte 0 /* Must be zero */
|
||||
start1: .ascii "Linux #0"
|
||||
end1: .byte 0x0a /* End marker */
|
||||
.fill 12-(end1-start1), 1, 0x20 /* Padded spaces */
|
||||
descriptor3: .byte 0,0 /* Not a detailed timing descriptor */
|
||||
.byte 0 /* Must be zero */
|
||||
.byte 0xfd /* Descriptor is monitor range limits */
|
||||
.byte 0 /* Must be zero */
|
||||
start2: .byte VFREQ-1 /* Minimum vertical field rate (1-255 Hz) */
|
||||
.byte VFREQ+1 /* Maximum vertical field rate (1-255 Hz) */
|
||||
.byte (CLOCK/(XPIX+XBLANK))-1 /* Minimum horizontal line rate
|
||||
(1-255 kHz) */
|
||||
.byte (CLOCK/(XPIX+XBLANK))+1 /* Maximum horizontal line rate
|
||||
(1-255 kHz) */
|
||||
.byte (CLOCK/10000)+1 /* Maximum pixel clock rate, rounded up
|
||||
to 10 MHz multiple (10-2550 MHz) */
|
||||
.byte 0 /* No extended timing information type */
|
||||
end2: .byte 0x0a /* End marker */
|
||||
.fill 12-(end2-start2), 1, 0x20 /* Padded spaces */
|
||||
descriptor4: .byte 0,0 /* Not a detailed timing descriptor */
|
||||
.byte 0 /* Must be zero */
|
||||
.byte 0xfc /* Descriptor is text */
|
||||
.byte 0 /* Must be zero */
|
||||
start3: .ascii TIMING_NAME
|
||||
end3: .byte 0x0a /* End marker */
|
||||
.fill 12-(end3-start3), 1, 0x20 /* Padded spaces */
|
||||
extensions: .byte 0 /* Number of extensions to follow */
|
||||
checksum: .byte CRC /* Sum of all bytes must be 0 */
|
||||
@@ -1 +0,0 @@
|
||||
"\t" 8/1 "0x%02x, " "\n"
|
||||
Reference in New Issue
Block a user