DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
/*
|
2011-09-22 12:30:16 -07:00
|
|
|
* Copyright © 2006 Intel Corporation
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Eric Anholt <eric@anholt.net>
|
|
|
|
*
|
|
|
|
*/
|
2015-12-14 12:50:46 +02:00
|
|
|
|
2024-08-27 13:45:21 +03:00
|
|
|
#include <linux/debugfs.h>
|
2024-02-28 13:32:32 -08:00
|
|
|
#include <linux/firmware.h>
|
|
|
|
|
2022-04-21 09:31:02 +02:00
|
|
|
#include <drm/display/drm_dp_helper.h>
|
2022-04-21 09:31:05 +02:00
|
|
|
#include <drm/display/drm_dsc_helper.h>
|
2023-01-04 17:32:58 +02:00
|
|
|
#include <drm/drm_edid.h>
|
2024-08-05 18:07:50 +03:00
|
|
|
#include <drm/drm_fixed.h>
|
2019-06-13 11:44:15 +03:00
|
|
|
|
2024-09-23 18:24:53 +03:00
|
|
|
#include "soc/intel_rom.h"
|
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
#include "i915_drv.h"
|
2023-01-04 17:32:58 +02:00
|
|
|
#include "intel_display.h"
|
2025-05-22 12:48:43 +03:00
|
|
|
#include "intel_display_core.h"
|
2025-03-20 17:03:56 +02:00
|
|
|
#include "intel_display_rpm.h"
|
2023-01-04 17:32:58 +02:00
|
|
|
#include "intel_display_types.h"
|
|
|
|
#include "intel_gmbus.h"
|
2016-03-16 12:43:35 +02:00
|
|
|
|
|
|
|
#define _INTEL_BIOS_PRIVATE
|
|
|
|
#include "intel_vbt_defs.h"
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
|
2015-12-21 15:10:52 +02:00
|
|
|
/**
|
|
|
|
* DOC: Video BIOS Table (VBT)
|
|
|
|
*
|
|
|
|
* The Video BIOS Table, or VBT, provides platform and board specific
|
|
|
|
* configuration information to the driver that is not discoverable or available
|
|
|
|
* through other means. The configuration is mostly related to display
|
|
|
|
* hardware. The VBT is available via the ACPI OpRegion or, on older systems, in
|
|
|
|
* the PCI ROM.
|
|
|
|
*
|
|
|
|
* The VBT consists of a VBT Header (defined as &struct vbt_header), a BDB
|
|
|
|
* Header (&struct bdb_header), and a number of BIOS Data Blocks (BDB) that
|
|
|
|
* contain the actual configuration information. The VBT Header, and thus the
|
|
|
|
* VBT, begins with "$VBT" signature. The VBT Header contains the offset of the
|
|
|
|
* BDB Header. The data blocks are concatenated after the BDB Header. The data
|
|
|
|
* blocks have a 1-byte Block ID, 2-byte Block Size, and Block Size bytes of
|
|
|
|
* data. (Block 53, the MIPI Sequence Block is an exception.)
|
|
|
|
*
|
|
|
|
* The driver parses the VBT during load. The relevant information is stored in
|
|
|
|
* driver private data for ease of use, and the actual VBT is not read after
|
|
|
|
* that.
|
|
|
|
*/
|
|
|
|
|
2019-11-08 17:39:49 +02:00
|
|
|
/* Wrapper for VBT child device config */
|
2021-03-17 18:36:47 +02:00
|
|
|
struct intel_bios_encoder_data {
|
2024-08-09 17:27:06 +03:00
|
|
|
struct intel_display *display;
|
2021-03-17 18:36:48 +02:00
|
|
|
|
2019-11-08 17:39:49 +02:00
|
|
|
struct child_device_config child;
|
2019-12-10 12:50:46 +02:00
|
|
|
struct dsc_compression_parameters_entry *dsc;
|
2019-11-08 17:39:49 +02:00
|
|
|
struct list_head node;
|
|
|
|
};
|
|
|
|
|
2024-07-11 05:27:31 +00:00
|
|
|
#define TARGET_ADDR1 0x70
|
|
|
|
#define TARGET_ADDR2 0x72
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
|
2015-12-21 15:10:55 +02:00
|
|
|
/* Get BDB block size given a pointer to Block ID. */
|
|
|
|
static u32 _get_blocksize(const u8 *block_base)
|
|
|
|
{
|
|
|
|
/* The MIPI Sequence Block v3+ has a separate size field. */
|
|
|
|
if (*block_base == BDB_MIPI_SEQUENCE && *(block_base + 3) >= 3)
|
|
|
|
return *((const u32 *)(block_base + 4));
|
|
|
|
else
|
|
|
|
return *((const u16 *)(block_base + 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get BDB block size give a pointer to data after Block ID and Block Size. */
|
|
|
|
static u32 get_blocksize(const void *block_data)
|
|
|
|
{
|
|
|
|
return _get_blocksize(block_data - 3);
|
|
|
|
}
|
|
|
|
|
2015-04-15 15:18:28 +03:00
|
|
|
static const void *
|
2022-04-06 16:38:17 +03:00
|
|
|
find_raw_section(const void *_bdb, enum bdb_block_id section_id)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
{
|
2015-04-15 15:18:28 +03:00
|
|
|
const struct bdb_header *bdb = _bdb;
|
|
|
|
const u8 *base = _bdb;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
int index = 0;
|
2015-09-17 16:42:07 +03:00
|
|
|
u32 total, current_size;
|
2019-05-31 16:15:03 +03:00
|
|
|
enum bdb_block_id current_id;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
|
|
|
|
/* skip to first section */
|
|
|
|
index += bdb->header_size;
|
|
|
|
total = bdb->bdb_size;
|
|
|
|
|
|
|
|
/* walk the sections looking for section_id */
|
2014-04-18 18:04:23 -03:00
|
|
|
while (index + 3 < total) {
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
current_id = *(base + index);
|
2015-12-21 15:10:55 +02:00
|
|
|
current_size = _get_blocksize(base + index);
|
|
|
|
index += 3;
|
2015-09-17 16:42:07 +03:00
|
|
|
|
2014-04-18 18:04:23 -03:00
|
|
|
if (index + current_size > total)
|
|
|
|
return NULL;
|
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
if (current_id == section_id)
|
|
|
|
return base + index;
|
2014-04-18 18:04:23 -03:00
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
index += current_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2022-04-06 16:38:17 +03:00
|
|
|
/*
|
|
|
|
* Offset from the start of BDB to the start of the
|
|
|
|
* block data (just past the block header).
|
|
|
|
*/
|
2022-05-19 17:00:10 +03:00
|
|
|
static u32 raw_block_offset(const void *bdb, enum bdb_block_id section_id)
|
2022-04-06 16:38:17 +03:00
|
|
|
{
|
|
|
|
const void *block;
|
|
|
|
|
|
|
|
block = find_raw_section(bdb, section_id);
|
|
|
|
if (!block)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return block - bdb;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct bdb_block_entry {
|
|
|
|
struct list_head node;
|
|
|
|
enum bdb_block_id section_id;
|
|
|
|
u8 data[];
|
|
|
|
};
|
|
|
|
|
|
|
|
static const void *
|
2024-08-09 17:27:06 +03:00
|
|
|
bdb_find_section(struct intel_display *display,
|
2023-03-15 14:19:24 +02:00
|
|
|
enum bdb_block_id section_id)
|
2022-04-06 16:38:17 +03:00
|
|
|
{
|
|
|
|
struct bdb_block_entry *entry;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
list_for_each_entry(entry, &display->vbt.bdb_blocks, node) {
|
2022-04-06 16:38:17 +03:00
|
|
|
if (entry->section_id == section_id)
|
|
|
|
return entry->data + 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct {
|
|
|
|
enum bdb_block_id section_id;
|
|
|
|
size_t min_size;
|
|
|
|
} bdb_blocks[] = {
|
|
|
|
{ .section_id = BDB_GENERAL_FEATURES,
|
|
|
|
.min_size = sizeof(struct bdb_general_features), },
|
|
|
|
{ .section_id = BDB_GENERAL_DEFINITIONS,
|
|
|
|
.min_size = sizeof(struct bdb_general_definitions), },
|
|
|
|
{ .section_id = BDB_PSR,
|
|
|
|
.min_size = sizeof(struct bdb_psr), },
|
|
|
|
{ .section_id = BDB_DRIVER_FEATURES,
|
|
|
|
.min_size = sizeof(struct bdb_driver_features), },
|
|
|
|
{ .section_id = BDB_SDVO_LVDS_OPTIONS,
|
|
|
|
.min_size = sizeof(struct bdb_sdvo_lvds_options), },
|
2024-05-03 15:24:19 +03:00
|
|
|
{ .section_id = BDB_SDVO_LVDS_DTD,
|
|
|
|
.min_size = sizeof(struct bdb_sdvo_lvds_dtd), },
|
2022-04-06 16:38:17 +03:00
|
|
|
{ .section_id = BDB_EDP,
|
|
|
|
.min_size = sizeof(struct bdb_edp), },
|
2024-05-03 15:24:18 +03:00
|
|
|
{ .section_id = BDB_LFP_OPTIONS,
|
|
|
|
.min_size = sizeof(struct bdb_lfp_options), },
|
2022-05-04 18:04:34 +03:00
|
|
|
/*
|
2024-05-03 15:24:18 +03:00
|
|
|
* BDB_LFP_DATA depends on BDB_LFP_DATA_PTRS,
|
2022-05-04 18:04:34 +03:00
|
|
|
* so keep the two ordered.
|
|
|
|
*/
|
2024-05-03 15:24:18 +03:00
|
|
|
{ .section_id = BDB_LFP_DATA_PTRS,
|
|
|
|
.min_size = sizeof(struct bdb_lfp_data_ptrs), },
|
|
|
|
{ .section_id = BDB_LFP_DATA,
|
2022-05-04 18:04:34 +03:00
|
|
|
.min_size = 0, /* special case */ },
|
2024-05-03 15:24:18 +03:00
|
|
|
{ .section_id = BDB_LFP_BACKLIGHT,
|
|
|
|
.min_size = sizeof(struct bdb_lfp_backlight), },
|
2022-04-06 16:38:17 +03:00
|
|
|
{ .section_id = BDB_LFP_POWER,
|
|
|
|
.min_size = sizeof(struct bdb_lfp_power), },
|
|
|
|
{ .section_id = BDB_MIPI_CONFIG,
|
|
|
|
.min_size = sizeof(struct bdb_mipi_config), },
|
|
|
|
{ .section_id = BDB_MIPI_SEQUENCE,
|
|
|
|
.min_size = sizeof(struct bdb_mipi_sequence) },
|
|
|
|
{ .section_id = BDB_COMPRESSION_PARAMETERS,
|
|
|
|
.min_size = sizeof(struct bdb_compression_parameters), },
|
|
|
|
{ .section_id = BDB_GENERIC_DTD,
|
|
|
|
.min_size = sizeof(struct bdb_generic_dtd), },
|
|
|
|
};
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
static size_t lfp_data_min_size(struct intel_display *display)
|
2022-05-04 18:04:34 +03:00
|
|
|
{
|
2024-05-03 15:24:18 +03:00
|
|
|
const struct bdb_lfp_data_ptrs *ptrs;
|
2022-05-04 18:04:34 +03:00
|
|
|
size_t size;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
ptrs = bdb_find_section(display, BDB_LFP_DATA_PTRS);
|
2022-05-04 18:04:34 +03:00
|
|
|
if (!ptrs)
|
|
|
|
return 0;
|
|
|
|
|
2024-05-03 15:24:18 +03:00
|
|
|
size = sizeof(struct bdb_lfp_data);
|
2022-05-04 18:04:34 +03:00
|
|
|
if (ptrs->panel_name.table_size)
|
|
|
|
size = max(size, ptrs->panel_name.offset +
|
2024-05-03 15:24:18 +03:00
|
|
|
sizeof(struct bdb_lfp_data_tail));
|
2022-05-04 18:04:34 +03:00
|
|
|
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2022-04-05 20:33:52 +03:00
|
|
|
static bool validate_lfp_data_ptrs(const void *bdb,
|
2024-05-03 15:24:18 +03:00
|
|
|
const struct bdb_lfp_data_ptrs *ptrs)
|
2022-04-05 20:33:52 +03:00
|
|
|
{
|
2022-04-05 20:33:54 +03:00
|
|
|
int fp_timing_size, dvo_timing_size, panel_pnp_id_size, panel_name_size;
|
2022-04-05 20:33:52 +03:00
|
|
|
int data_block_size, lfp_data_size;
|
2022-08-18 22:22:22 +03:00
|
|
|
const void *data_block;
|
2022-04-05 20:33:52 +03:00
|
|
|
int i;
|
|
|
|
|
2024-05-03 15:24:18 +03:00
|
|
|
data_block = find_raw_section(bdb, BDB_LFP_DATA);
|
2022-08-18 22:22:22 +03:00
|
|
|
if (!data_block)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
data_block_size = get_blocksize(data_block);
|
2022-04-05 20:33:52 +03:00
|
|
|
if (data_block_size == 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/* always 3 indicating the presence of fp_timing+dvo_timing+panel_pnp_id */
|
2024-05-03 15:24:18 +03:00
|
|
|
if (ptrs->num_entries != 3)
|
2022-04-05 20:33:52 +03:00
|
|
|
return false;
|
|
|
|
|
|
|
|
fp_timing_size = ptrs->ptr[0].fp_timing.table_size;
|
|
|
|
dvo_timing_size = ptrs->ptr[0].dvo_timing.table_size;
|
|
|
|
panel_pnp_id_size = ptrs->ptr[0].panel_pnp_id.table_size;
|
2022-04-05 20:33:54 +03:00
|
|
|
panel_name_size = ptrs->panel_name.table_size;
|
2022-04-05 20:33:52 +03:00
|
|
|
|
|
|
|
/* fp_timing has variable size */
|
|
|
|
if (fp_timing_size < 32 ||
|
2024-05-03 15:24:17 +03:00
|
|
|
dvo_timing_size != sizeof(struct bdb_edid_dtd) ||
|
|
|
|
panel_pnp_id_size != sizeof(struct bdb_edid_pnp_id))
|
2022-04-05 20:33:52 +03:00
|
|
|
return false;
|
|
|
|
|
2022-04-05 20:33:54 +03:00
|
|
|
/* panel_name is not present in old VBTs */
|
|
|
|
if (panel_name_size != 0 &&
|
2024-05-03 15:24:17 +03:00
|
|
|
panel_name_size != sizeof(struct bdb_edid_product_name))
|
2022-04-05 20:33:54 +03:00
|
|
|
return false;
|
|
|
|
|
2022-04-05 20:33:52 +03:00
|
|
|
lfp_data_size = ptrs->ptr[1].fp_timing.offset - ptrs->ptr[0].fp_timing.offset;
|
|
|
|
if (16 * lfp_data_size > data_block_size)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/* make sure the table entries have uniform size */
|
|
|
|
for (i = 1; i < 16; i++) {
|
|
|
|
if (ptrs->ptr[i].fp_timing.table_size != fp_timing_size ||
|
|
|
|
ptrs->ptr[i].dvo_timing.table_size != dvo_timing_size ||
|
|
|
|
ptrs->ptr[i].panel_pnp_id.table_size != panel_pnp_id_size)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (ptrs->ptr[i].fp_timing.offset - ptrs->ptr[i-1].fp_timing.offset != lfp_data_size ||
|
|
|
|
ptrs->ptr[i].dvo_timing.offset - ptrs->ptr[i-1].dvo_timing.offset != lfp_data_size ||
|
|
|
|
ptrs->ptr[i].panel_pnp_id.offset - ptrs->ptr[i-1].panel_pnp_id.offset != lfp_data_size)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-08-18 22:22:22 +03:00
|
|
|
/*
|
|
|
|
* Except for vlv/chv machines all real VBTs seem to have 6
|
|
|
|
* unaccounted bytes in the fp_timing table. And it doesn't
|
|
|
|
* appear to be a really intentional hole as the fp_timing
|
|
|
|
* 0xffff terminator is always within those 6 missing bytes.
|
|
|
|
*/
|
|
|
|
if (fp_timing_size + 6 + dvo_timing_size + panel_pnp_id_size == lfp_data_size)
|
|
|
|
fp_timing_size += 6;
|
|
|
|
|
|
|
|
if (fp_timing_size + dvo_timing_size + panel_pnp_id_size != lfp_data_size)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (ptrs->ptr[0].fp_timing.offset + fp_timing_size != ptrs->ptr[0].dvo_timing.offset ||
|
|
|
|
ptrs->ptr[0].dvo_timing.offset + dvo_timing_size != ptrs->ptr[0].panel_pnp_id.offset ||
|
|
|
|
ptrs->ptr[0].panel_pnp_id.offset + panel_pnp_id_size != lfp_data_size)
|
|
|
|
return false;
|
|
|
|
|
2022-04-05 20:33:52 +03:00
|
|
|
/* make sure the tables fit inside the data block */
|
|
|
|
for (i = 0; i < 16; i++) {
|
|
|
|
if (ptrs->ptr[i].fp_timing.offset + fp_timing_size > data_block_size ||
|
|
|
|
ptrs->ptr[i].dvo_timing.offset + dvo_timing_size > data_block_size ||
|
|
|
|
ptrs->ptr[i].panel_pnp_id.offset + panel_pnp_id_size > data_block_size)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-04-05 20:33:54 +03:00
|
|
|
if (ptrs->panel_name.offset + 16 * panel_name_size > data_block_size)
|
|
|
|
return false;
|
|
|
|
|
2022-08-18 22:22:22 +03:00
|
|
|
/* make sure fp_timing terminators are present at expected locations */
|
|
|
|
for (i = 0; i < 16; i++) {
|
|
|
|
const u16 *t = data_block + ptrs->ptr[i].fp_timing.offset +
|
|
|
|
fp_timing_size - 2;
|
|
|
|
|
|
|
|
if (*t != 0xffff)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-04-05 20:33:52 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-04-05 20:33:51 +03:00
|
|
|
/* make the data table offsets relative to the data block */
|
|
|
|
static bool fixup_lfp_data_ptrs(const void *bdb, void *ptrs_block)
|
|
|
|
{
|
2024-05-03 15:24:18 +03:00
|
|
|
struct bdb_lfp_data_ptrs *ptrs = ptrs_block;
|
2022-04-05 20:33:51 +03:00
|
|
|
u32 offset;
|
|
|
|
int i;
|
|
|
|
|
2024-05-03 15:24:18 +03:00
|
|
|
offset = raw_block_offset(bdb, BDB_LFP_DATA);
|
2022-04-05 20:33:51 +03:00
|
|
|
|
|
|
|
for (i = 0; i < 16; i++) {
|
|
|
|
if (ptrs->ptr[i].fp_timing.offset < offset ||
|
|
|
|
ptrs->ptr[i].dvo_timing.offset < offset ||
|
|
|
|
ptrs->ptr[i].panel_pnp_id.offset < offset)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
ptrs->ptr[i].fp_timing.offset -= offset;
|
|
|
|
ptrs->ptr[i].dvo_timing.offset -= offset;
|
|
|
|
ptrs->ptr[i].panel_pnp_id.offset -= offset;
|
|
|
|
}
|
|
|
|
|
2022-04-05 20:33:54 +03:00
|
|
|
if (ptrs->panel_name.table_size) {
|
|
|
|
if (ptrs->panel_name.offset < offset)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
ptrs->panel_name.offset -= offset;
|
|
|
|
}
|
|
|
|
|
2022-04-05 20:33:52 +03:00
|
|
|
return validate_lfp_data_ptrs(bdb, ptrs);
|
2022-04-05 20:33:51 +03:00
|
|
|
}
|
|
|
|
|
2024-05-03 15:24:18 +03:00
|
|
|
static int make_lfp_data_ptr(struct lfp_data_ptr_table *table,
|
2022-05-04 18:04:33 +03:00
|
|
|
int table_size, int total_size)
|
|
|
|
{
|
|
|
|
if (total_size < table_size)
|
|
|
|
return total_size;
|
|
|
|
|
|
|
|
table->table_size = table_size;
|
|
|
|
table->offset = total_size - table_size;
|
|
|
|
|
|
|
|
return total_size - table_size;
|
|
|
|
}
|
|
|
|
|
2024-05-03 15:24:18 +03:00
|
|
|
static void next_lfp_data_ptr(struct lfp_data_ptr_table *next,
|
|
|
|
const struct lfp_data_ptr_table *prev,
|
2022-05-04 18:04:33 +03:00
|
|
|
int size)
|
|
|
|
{
|
|
|
|
next->table_size = prev->table_size;
|
|
|
|
next->offset = prev->offset + size;
|
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
static void *generate_lfp_data_ptrs(struct intel_display *display,
|
2022-05-04 18:04:33 +03:00
|
|
|
const void *bdb)
|
|
|
|
{
|
2022-08-18 22:22:23 +03:00
|
|
|
int i, size, table_size, block_size, offset, fp_timing_size;
|
2024-05-03 15:24:18 +03:00
|
|
|
struct bdb_lfp_data_ptrs *ptrs;
|
2022-08-18 22:22:23 +03:00
|
|
|
const void *block;
|
2022-05-04 18:04:33 +03:00
|
|
|
void *ptrs_block;
|
|
|
|
|
2022-08-18 22:22:23 +03:00
|
|
|
/*
|
|
|
|
* The hardcoded fp_timing_size is only valid for
|
|
|
|
* modernish VBTs. All older VBTs definitely should
|
|
|
|
* include block 41 and thus we don't need to
|
|
|
|
* generate one.
|
|
|
|
*/
|
2024-08-09 17:27:06 +03:00
|
|
|
if (display->vbt.version < 155)
|
2022-08-18 22:22:23 +03:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
fp_timing_size = 38;
|
|
|
|
|
2024-05-03 15:24:18 +03:00
|
|
|
block = find_raw_section(bdb, BDB_LFP_DATA);
|
2022-05-04 18:04:33 +03:00
|
|
|
if (!block)
|
|
|
|
return NULL;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm, "Generating LFP data table pointers\n");
|
2022-05-04 18:04:33 +03:00
|
|
|
|
|
|
|
block_size = get_blocksize(block);
|
|
|
|
|
2024-05-03 15:24:17 +03:00
|
|
|
size = fp_timing_size + sizeof(struct bdb_edid_dtd) +
|
|
|
|
sizeof(struct bdb_edid_pnp_id);
|
2022-05-04 18:04:33 +03:00
|
|
|
if (size * 16 > block_size)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
ptrs_block = kzalloc(sizeof(*ptrs) + 3, GFP_KERNEL);
|
|
|
|
if (!ptrs_block)
|
|
|
|
return NULL;
|
|
|
|
|
2024-05-03 15:24:18 +03:00
|
|
|
*(u8 *)(ptrs_block + 0) = BDB_LFP_DATA_PTRS;
|
2022-05-04 18:04:33 +03:00
|
|
|
*(u16 *)(ptrs_block + 1) = sizeof(*ptrs);
|
|
|
|
ptrs = ptrs_block + 3;
|
|
|
|
|
2024-05-03 15:24:17 +03:00
|
|
|
table_size = sizeof(struct bdb_edid_pnp_id);
|
2022-05-04 18:04:33 +03:00
|
|
|
size = make_lfp_data_ptr(&ptrs->ptr[0].panel_pnp_id, table_size, size);
|
|
|
|
|
2024-05-03 15:24:17 +03:00
|
|
|
table_size = sizeof(struct bdb_edid_dtd);
|
2022-05-04 18:04:33 +03:00
|
|
|
size = make_lfp_data_ptr(&ptrs->ptr[0].dvo_timing, table_size, size);
|
|
|
|
|
2022-08-18 22:22:23 +03:00
|
|
|
table_size = fp_timing_size;
|
2022-05-04 18:04:33 +03:00
|
|
|
size = make_lfp_data_ptr(&ptrs->ptr[0].fp_timing, table_size, size);
|
|
|
|
|
|
|
|
if (ptrs->ptr[0].fp_timing.table_size)
|
2024-05-03 15:24:18 +03:00
|
|
|
ptrs->num_entries++;
|
2022-05-04 18:04:33 +03:00
|
|
|
if (ptrs->ptr[0].dvo_timing.table_size)
|
2024-05-03 15:24:18 +03:00
|
|
|
ptrs->num_entries++;
|
2022-05-04 18:04:33 +03:00
|
|
|
if (ptrs->ptr[0].panel_pnp_id.table_size)
|
2024-05-03 15:24:18 +03:00
|
|
|
ptrs->num_entries++;
|
2022-05-04 18:04:33 +03:00
|
|
|
|
2024-05-03 15:24:18 +03:00
|
|
|
if (size != 0 || ptrs->num_entries != 3) {
|
2022-11-25 14:34:28 +08:00
|
|
|
kfree(ptrs_block);
|
2022-05-04 18:04:33 +03:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2024-05-03 15:24:17 +03:00
|
|
|
size = fp_timing_size + sizeof(struct bdb_edid_dtd) +
|
|
|
|
sizeof(struct bdb_edid_pnp_id);
|
2022-05-04 18:04:33 +03:00
|
|
|
for (i = 1; i < 16; i++) {
|
|
|
|
next_lfp_data_ptr(&ptrs->ptr[i].fp_timing, &ptrs->ptr[i-1].fp_timing, size);
|
|
|
|
next_lfp_data_ptr(&ptrs->ptr[i].dvo_timing, &ptrs->ptr[i-1].dvo_timing, size);
|
|
|
|
next_lfp_data_ptr(&ptrs->ptr[i].panel_pnp_id, &ptrs->ptr[i-1].panel_pnp_id, size);
|
|
|
|
}
|
|
|
|
|
2024-05-03 15:24:17 +03:00
|
|
|
table_size = sizeof(struct bdb_edid_product_name);
|
2022-05-04 18:04:33 +03:00
|
|
|
|
|
|
|
if (16 * (size + table_size) <= block_size) {
|
|
|
|
ptrs->panel_name.table_size = table_size;
|
|
|
|
ptrs->panel_name.offset = size * 16;
|
|
|
|
}
|
|
|
|
|
|
|
|
offset = block - bdb;
|
|
|
|
|
|
|
|
for (i = 0; i < 16; i++) {
|
|
|
|
ptrs->ptr[i].fp_timing.offset += offset;
|
|
|
|
ptrs->ptr[i].dvo_timing.offset += offset;
|
|
|
|
ptrs->ptr[i].panel_pnp_id.offset += offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ptrs->panel_name.table_size)
|
|
|
|
ptrs->panel_name.offset += offset;
|
|
|
|
|
|
|
|
return ptrs_block;
|
|
|
|
}
|
|
|
|
|
2022-04-06 16:38:17 +03:00
|
|
|
static void
|
2024-08-09 17:27:06 +03:00
|
|
|
init_bdb_block(struct intel_display *display,
|
2022-04-06 16:38:17 +03:00
|
|
|
const void *bdb, enum bdb_block_id section_id,
|
|
|
|
size_t min_size)
|
|
|
|
{
|
|
|
|
struct bdb_block_entry *entry;
|
2022-05-04 18:04:33 +03:00
|
|
|
void *temp_block = NULL;
|
2022-04-06 16:38:17 +03:00
|
|
|
const void *block;
|
|
|
|
size_t block_size;
|
|
|
|
|
|
|
|
block = find_raw_section(bdb, section_id);
|
2022-05-04 18:04:33 +03:00
|
|
|
|
|
|
|
/* Modern VBTs lack the LFP data table pointers block, make one up */
|
2024-05-03 15:24:18 +03:00
|
|
|
if (!block && section_id == BDB_LFP_DATA_PTRS) {
|
2024-08-09 17:27:06 +03:00
|
|
|
temp_block = generate_lfp_data_ptrs(display, bdb);
|
2022-05-04 18:04:33 +03:00
|
|
|
if (temp_block)
|
|
|
|
block = temp_block + 3;
|
|
|
|
}
|
2022-04-06 16:38:17 +03:00
|
|
|
if (!block)
|
|
|
|
return;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_WARN(display->drm, min_size == 0,
|
2022-04-06 16:38:17 +03:00
|
|
|
"Block %d min_size is zero\n", section_id);
|
|
|
|
|
|
|
|
block_size = get_blocksize(block);
|
|
|
|
|
2022-08-29 16:58:34 +03:00
|
|
|
/*
|
|
|
|
* Version number and new block size are considered
|
|
|
|
* part of the header for MIPI sequenece block v3+.
|
|
|
|
*/
|
|
|
|
if (section_id == BDB_MIPI_SEQUENCE && *(const u8 *)block >= 3)
|
|
|
|
block_size += 5;
|
|
|
|
|
2022-04-06 16:38:17 +03:00
|
|
|
entry = kzalloc(struct_size(entry, data, max(min_size, block_size) + 3),
|
|
|
|
GFP_KERNEL);
|
2022-05-04 18:04:33 +03:00
|
|
|
if (!entry) {
|
|
|
|
kfree(temp_block);
|
2022-04-06 16:38:17 +03:00
|
|
|
return;
|
2022-05-04 18:04:33 +03:00
|
|
|
}
|
2022-04-06 16:38:17 +03:00
|
|
|
|
|
|
|
entry->section_id = section_id;
|
|
|
|
memcpy(entry->data, block - 3, block_size + 3);
|
|
|
|
|
2022-05-04 18:04:33 +03:00
|
|
|
kfree(temp_block);
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
|
|
|
"Found BDB block %d (size %zu, min size %zu)\n",
|
2022-04-06 16:38:17 +03:00
|
|
|
section_id, block_size, min_size);
|
|
|
|
|
2024-05-03 15:24:18 +03:00
|
|
|
if (section_id == BDB_LFP_DATA_PTRS &&
|
2022-04-05 20:33:51 +03:00
|
|
|
!fixup_lfp_data_ptrs(bdb, entry->data + 3)) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_err(display->drm,
|
|
|
|
"VBT has malformed LFP data table pointers\n");
|
2022-04-05 20:33:51 +03:00
|
|
|
kfree(entry);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
list_add_tail(&entry->node, &display->vbt.bdb_blocks);
|
2022-04-06 16:38:17 +03:00
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
static void init_bdb_blocks(struct intel_display *display,
|
2022-04-06 16:38:17 +03:00
|
|
|
const void *bdb)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(bdb_blocks); i++) {
|
|
|
|
enum bdb_block_id section_id = bdb_blocks[i].section_id;
|
|
|
|
size_t min_size = bdb_blocks[i].min_size;
|
|
|
|
|
2024-05-03 15:24:18 +03:00
|
|
|
if (section_id == BDB_LFP_DATA)
|
2024-08-09 17:27:06 +03:00
|
|
|
min_size = lfp_data_min_size(display);
|
2022-05-04 18:04:34 +03:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
init_bdb_block(display, bdb, section_id, min_size);
|
2022-04-06 16:38:17 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
static void
|
2024-08-09 17:27:06 +03:00
|
|
|
fill_detail_timing_data(struct intel_display *display,
|
2023-09-21 00:19:34 +03:00
|
|
|
struct drm_display_mode *panel_fixed_mode,
|
2024-05-03 15:24:17 +03:00
|
|
|
const struct bdb_edid_dtd *dvo_timing)
|
2009-05-13 11:19:55 +08:00
|
|
|
{
|
|
|
|
panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) |
|
|
|
|
dvo_timing->hactive_lo;
|
|
|
|
panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay +
|
|
|
|
((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo);
|
|
|
|
panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start +
|
2016-12-22 13:23:13 -05:00
|
|
|
((dvo_timing->hsync_pulse_width_hi << 8) |
|
|
|
|
dvo_timing->hsync_pulse_width_lo);
|
2009-05-13 11:19:55 +08:00
|
|
|
panel_fixed_mode->htotal = panel_fixed_mode->hdisplay +
|
|
|
|
((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo);
|
|
|
|
|
|
|
|
panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) |
|
|
|
|
dvo_timing->vactive_lo;
|
|
|
|
panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay +
|
2016-12-22 13:23:13 -05:00
|
|
|
((dvo_timing->vsync_off_hi << 4) | dvo_timing->vsync_off_lo);
|
2009-05-13 11:19:55 +08:00
|
|
|
panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start +
|
2016-12-22 13:23:13 -05:00
|
|
|
((dvo_timing->vsync_pulse_width_hi << 4) |
|
|
|
|
dvo_timing->vsync_pulse_width_lo);
|
2009-05-13 11:19:55 +08:00
|
|
|
panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay +
|
|
|
|
((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo);
|
|
|
|
panel_fixed_mode->clock = dvo_timing->clock * 10;
|
|
|
|
panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
|
|
|
|
|
2010-05-28 17:17:37 -04:00
|
|
|
if (dvo_timing->hsync_positive)
|
|
|
|
panel_fixed_mode->flags |= DRM_MODE_FLAG_PHSYNC;
|
|
|
|
else
|
|
|
|
panel_fixed_mode->flags |= DRM_MODE_FLAG_NHSYNC;
|
|
|
|
|
|
|
|
if (dvo_timing->vsync_positive)
|
|
|
|
panel_fixed_mode->flags |= DRM_MODE_FLAG_PVSYNC;
|
|
|
|
else
|
|
|
|
panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC;
|
|
|
|
|
2016-05-31 12:08:34 +03:00
|
|
|
panel_fixed_mode->width_mm = (dvo_timing->himage_hi << 8) |
|
|
|
|
dvo_timing->himage_lo;
|
|
|
|
panel_fixed_mode->height_mm = (dvo_timing->vimage_hi << 8) |
|
|
|
|
dvo_timing->vimage_lo;
|
|
|
|
|
2023-09-21 00:19:34 +03:00
|
|
|
/* Some VBTs have bogus h/vsync_end values */
|
|
|
|
if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm, "reducing hsync_end %d->%d\n",
|
2023-09-21 00:19:34 +03:00
|
|
|
panel_fixed_mode->hsync_end, panel_fixed_mode->htotal);
|
|
|
|
panel_fixed_mode->hsync_end = panel_fixed_mode->htotal;
|
|
|
|
}
|
|
|
|
if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm, "reducing vsync_end %d->%d\n",
|
2023-09-21 00:19:34 +03:00
|
|
|
panel_fixed_mode->vsync_end, panel_fixed_mode->vtotal);
|
|
|
|
panel_fixed_mode->vsync_end = panel_fixed_mode->vtotal;
|
|
|
|
}
|
2009-05-13 11:19:55 +08:00
|
|
|
|
|
|
|
drm_mode_set_name(panel_fixed_mode);
|
|
|
|
}
|
|
|
|
|
2024-05-03 15:24:17 +03:00
|
|
|
static const struct bdb_edid_dtd *
|
2024-05-03 15:24:18 +03:00
|
|
|
get_lfp_dvo_timing(const struct bdb_lfp_data *data,
|
|
|
|
const struct bdb_lfp_data_ptrs *ptrs,
|
|
|
|
int index)
|
2011-07-13 21:01:46 +01:00
|
|
|
{
|
2022-04-05 20:33:53 +03:00
|
|
|
return (const void *)data + ptrs->ptr[index].dvo_timing.offset;
|
2011-07-13 21:01:46 +01:00
|
|
|
}
|
|
|
|
|
2024-05-03 15:24:18 +03:00
|
|
|
static const struct fp_timing *
|
|
|
|
get_lfp_fp_timing(const struct bdb_lfp_data *data,
|
|
|
|
const struct bdb_lfp_data_ptrs *ptrs,
|
|
|
|
int index)
|
2012-03-20 13:07:05 +01:00
|
|
|
{
|
2022-04-05 20:33:53 +03:00
|
|
|
return (const void *)data + ptrs->ptr[index].fp_timing.offset;
|
2012-03-20 13:07:05 +01:00
|
|
|
}
|
|
|
|
|
2024-04-09 12:46:12 +03:00
|
|
|
static const struct drm_edid_product_id *
|
2024-05-03 15:24:18 +03:00
|
|
|
get_lfp_pnp_id(const struct bdb_lfp_data *data,
|
|
|
|
const struct bdb_lfp_data_ptrs *ptrs,
|
|
|
|
int index)
|
2022-05-10 13:42:40 +03:00
|
|
|
{
|
2024-04-09 12:46:11 +03:00
|
|
|
/* These two are supposed to have the same layout in memory. */
|
2024-05-03 15:24:17 +03:00
|
|
|
BUILD_BUG_ON(sizeof(struct bdb_edid_pnp_id) != sizeof(struct drm_edid_product_id));
|
2024-04-09 12:46:11 +03:00
|
|
|
|
2022-05-10 13:42:40 +03:00
|
|
|
return (const void *)data + ptrs->ptr[index].panel_pnp_id.offset;
|
|
|
|
}
|
|
|
|
|
2024-05-03 15:24:18 +03:00
|
|
|
static const struct bdb_lfp_data_tail *
|
|
|
|
get_lfp_data_tail(const struct bdb_lfp_data *data,
|
|
|
|
const struct bdb_lfp_data_ptrs *ptrs)
|
2022-05-04 18:04:34 +03:00
|
|
|
{
|
|
|
|
if (ptrs->panel_name.table_size)
|
|
|
|
return (const void *)data + ptrs->panel_name.offset;
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
static int opregion_get_panel_type(struct intel_display *display,
|
2022-06-20 12:21:38 +05:30
|
|
|
const struct intel_bios_encoder_data *devdata,
|
2023-01-25 13:10:50 +02:00
|
|
|
const struct drm_edid *drm_edid, bool use_fallback)
|
2022-05-04 18:04:38 +03:00
|
|
|
{
|
2024-08-09 17:27:05 +03:00
|
|
|
return intel_opregion_get_panel_type(display);
|
2022-05-04 18:04:38 +03:00
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
static int vbt_get_panel_type(struct intel_display *display,
|
2022-06-20 12:21:38 +05:30
|
|
|
const struct intel_bios_encoder_data *devdata,
|
2023-01-25 13:10:50 +02:00
|
|
|
const struct drm_edid *drm_edid, bool use_fallback)
|
2022-05-04 18:04:37 +03:00
|
|
|
{
|
2024-05-03 15:24:18 +03:00
|
|
|
const struct bdb_lfp_options *lfp_options;
|
2022-05-04 18:04:37 +03:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
lfp_options = bdb_find_section(display, BDB_LFP_OPTIONS);
|
2024-05-03 15:24:18 +03:00
|
|
|
if (!lfp_options)
|
2022-05-04 18:04:37 +03:00
|
|
|
return -1;
|
|
|
|
|
2024-05-03 15:24:18 +03:00
|
|
|
if (lfp_options->panel_type > 0xf &&
|
|
|
|
lfp_options->panel_type != 0xff) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm, "Invalid VBT panel type 0x%x\n",
|
2024-05-03 15:24:18 +03:00
|
|
|
lfp_options->panel_type);
|
2022-05-04 18:04:37 +03:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-06-20 12:21:38 +05:30
|
|
|
if (devdata && devdata->child.handle == DEVICE_HANDLE_LFP2)
|
2024-05-03 15:24:18 +03:00
|
|
|
return lfp_options->panel_type2;
|
2022-06-20 12:21:38 +05:30
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_WARN_ON(display->drm,
|
|
|
|
devdata && devdata->child.handle != DEVICE_HANDLE_LFP1);
|
2022-06-20 12:21:38 +05:30
|
|
|
|
2024-05-03 15:24:18 +03:00
|
|
|
return lfp_options->panel_type;
|
2022-05-04 18:04:37 +03:00
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
static int pnpid_get_panel_type(struct intel_display *display,
|
2022-06-20 12:21:38 +05:30
|
|
|
const struct intel_bios_encoder_data *devdata,
|
2023-01-25 13:10:50 +02:00
|
|
|
const struct drm_edid *drm_edid, bool use_fallback)
|
2022-05-10 13:42:40 +03:00
|
|
|
{
|
2024-05-03 15:24:18 +03:00
|
|
|
const struct bdb_lfp_data *data;
|
|
|
|
const struct bdb_lfp_data_ptrs *ptrs;
|
2024-04-09 12:46:11 +03:00
|
|
|
struct drm_edid_product_id product_id, product_id_nodate;
|
|
|
|
struct drm_printer p;
|
2022-05-10 13:42:40 +03:00
|
|
|
int i, best = -1;
|
|
|
|
|
2024-04-09 12:46:11 +03:00
|
|
|
if (!drm_edid)
|
2022-05-10 13:42:40 +03:00
|
|
|
return -1;
|
|
|
|
|
2024-04-09 12:46:11 +03:00
|
|
|
drm_edid_get_product_id(drm_edid, &product_id);
|
2022-05-10 13:42:40 +03:00
|
|
|
|
2024-04-09 12:46:11 +03:00
|
|
|
product_id_nodate = product_id;
|
|
|
|
product_id_nodate.week_of_manufacture = 0;
|
|
|
|
product_id_nodate.year_of_manufacture = 0;
|
2022-05-10 13:42:40 +03:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
p = drm_dbg_printer(display->drm, DRM_UT_KMS, "EDID");
|
2024-04-09 12:46:11 +03:00
|
|
|
drm_edid_print_product_id(&p, &product_id, true);
|
2022-05-10 13:42:42 +03:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
ptrs = bdb_find_section(display, BDB_LFP_DATA_PTRS);
|
2022-05-10 13:42:40 +03:00
|
|
|
if (!ptrs)
|
|
|
|
return -1;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
data = bdb_find_section(display, BDB_LFP_DATA);
|
2022-05-10 13:42:40 +03:00
|
|
|
if (!data)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (i = 0; i < 16; i++) {
|
2024-04-09 12:46:12 +03:00
|
|
|
const struct drm_edid_product_id *vbt_id =
|
2024-05-03 15:24:18 +03:00
|
|
|
get_lfp_pnp_id(data, ptrs, i);
|
2022-05-10 13:42:40 +03:00
|
|
|
|
|
|
|
/* full match? */
|
2024-04-09 12:46:11 +03:00
|
|
|
if (!memcmp(vbt_id, &product_id, sizeof(*vbt_id)))
|
2022-05-10 13:42:40 +03:00
|
|
|
return i;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Accept a match w/o date if no full match is found,
|
|
|
|
* and the VBT entry does not specify a date.
|
|
|
|
*/
|
|
|
|
if (best < 0 &&
|
2024-04-09 12:46:11 +03:00
|
|
|
!memcmp(vbt_id, &product_id_nodate, sizeof(*vbt_id)))
|
2022-05-10 13:42:40 +03:00
|
|
|
best = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
return best;
|
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
static int fallback_get_panel_type(struct intel_display *display,
|
2022-06-20 12:21:38 +05:30
|
|
|
const struct intel_bios_encoder_data *devdata,
|
2023-01-25 13:10:50 +02:00
|
|
|
const struct drm_edid *drm_edid, bool use_fallback)
|
2022-05-04 18:04:38 +03:00
|
|
|
{
|
2022-11-25 19:31:49 +02:00
|
|
|
return use_fallback ? 0 : -1;
|
2022-05-04 18:04:38 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
enum panel_type {
|
|
|
|
PANEL_TYPE_OPREGION,
|
|
|
|
PANEL_TYPE_VBT,
|
2022-05-10 13:42:40 +03:00
|
|
|
PANEL_TYPE_PNPID,
|
2022-05-04 18:04:38 +03:00
|
|
|
PANEL_TYPE_FALLBACK,
|
|
|
|
};
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
static int get_panel_type(struct intel_display *display,
|
2022-06-20 12:21:38 +05:30
|
|
|
const struct intel_bios_encoder_data *devdata,
|
2023-01-25 13:10:50 +02:00
|
|
|
const struct drm_edid *drm_edid, bool use_fallback)
|
2022-05-04 18:04:37 +03:00
|
|
|
{
|
2022-05-04 18:04:38 +03:00
|
|
|
struct {
|
|
|
|
const char *name;
|
2024-08-09 17:27:06 +03:00
|
|
|
int (*get_panel_type)(struct intel_display *display,
|
2022-06-20 12:21:38 +05:30
|
|
|
const struct intel_bios_encoder_data *devdata,
|
2023-01-25 13:10:50 +02:00
|
|
|
const struct drm_edid *drm_edid, bool use_fallback);
|
2022-05-04 18:04:38 +03:00
|
|
|
int panel_type;
|
|
|
|
} panel_types[] = {
|
|
|
|
[PANEL_TYPE_OPREGION] = {
|
|
|
|
.name = "OpRegion",
|
|
|
|
.get_panel_type = opregion_get_panel_type,
|
|
|
|
},
|
|
|
|
[PANEL_TYPE_VBT] = {
|
|
|
|
.name = "VBT",
|
|
|
|
.get_panel_type = vbt_get_panel_type,
|
|
|
|
},
|
2022-05-10 13:42:40 +03:00
|
|
|
[PANEL_TYPE_PNPID] = {
|
|
|
|
.name = "PNPID",
|
|
|
|
.get_panel_type = pnpid_get_panel_type,
|
|
|
|
},
|
2022-05-04 18:04:38 +03:00
|
|
|
[PANEL_TYPE_FALLBACK] = {
|
|
|
|
.name = "fallback",
|
|
|
|
.get_panel_type = fallback_get_panel_type,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
int i;
|
2022-05-04 18:04:37 +03:00
|
|
|
|
2022-05-04 18:04:38 +03:00
|
|
|
for (i = 0; i < ARRAY_SIZE(panel_types); i++) {
|
2024-08-09 17:27:06 +03:00
|
|
|
panel_types[i].panel_type = panel_types[i].get_panel_type(display, devdata,
|
2023-01-25 13:10:50 +02:00
|
|
|
drm_edid, use_fallback);
|
2022-05-04 18:04:38 +03:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_WARN_ON(display->drm, panel_types[i].panel_type > 0xf &&
|
2022-05-10 13:42:40 +03:00
|
|
|
panel_types[i].panel_type != 0xff);
|
2022-05-04 18:04:37 +03:00
|
|
|
|
2022-05-04 18:04:38 +03:00
|
|
|
if (panel_types[i].panel_type >= 0)
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm, "Panel type (%s): %d\n",
|
2022-05-04 18:04:38 +03:00
|
|
|
panel_types[i].name, panel_types[i].panel_type);
|
2022-05-04 18:04:37 +03:00
|
|
|
}
|
|
|
|
|
2022-05-04 18:04:38 +03:00
|
|
|
if (panel_types[PANEL_TYPE_OPREGION].panel_type >= 0)
|
|
|
|
i = PANEL_TYPE_OPREGION;
|
2022-05-10 13:42:40 +03:00
|
|
|
else if (panel_types[PANEL_TYPE_VBT].panel_type == 0xff &&
|
|
|
|
panel_types[PANEL_TYPE_PNPID].panel_type >= 0)
|
|
|
|
i = PANEL_TYPE_PNPID;
|
|
|
|
else if (panel_types[PANEL_TYPE_VBT].panel_type != 0xff &&
|
|
|
|
panel_types[PANEL_TYPE_VBT].panel_type >= 0)
|
2022-05-04 18:04:38 +03:00
|
|
|
i = PANEL_TYPE_VBT;
|
|
|
|
else
|
|
|
|
i = PANEL_TYPE_FALLBACK;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm, "Selected panel type (%s): %d\n",
|
2022-05-04 18:04:38 +03:00
|
|
|
panel_types[i].name, panel_types[i].panel_type);
|
|
|
|
|
|
|
|
return panel_types[i].panel_type;
|
2022-05-04 18:04:37 +03:00
|
|
|
}
|
|
|
|
|
2022-06-15 18:14:45 +03:00
|
|
|
static unsigned int panel_bits(unsigned int value, int panel_type, int num_bits)
|
|
|
|
{
|
|
|
|
return (value >> (panel_type * num_bits)) & (BIT(num_bits) - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool panel_bool(unsigned int value, int panel_type)
|
|
|
|
{
|
|
|
|
return panel_bits(value, panel_type, 1);
|
|
|
|
}
|
|
|
|
|
2019-11-15 08:51:31 -08:00
|
|
|
/* Parse general panel options */
|
2009-05-13 11:19:55 +08:00
|
|
|
static void
|
2024-08-09 17:27:06 +03:00
|
|
|
parse_panel_options(struct intel_display *display,
|
2022-06-15 18:14:43 +03:00
|
|
|
struct intel_panel *panel)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
{
|
2024-05-03 15:24:18 +03:00
|
|
|
const struct bdb_lfp_options *lfp_options;
|
2022-06-15 18:14:43 +03:00
|
|
|
int panel_type = panel->vbt.panel_type;
|
2015-06-18 10:30:23 +02:00
|
|
|
int drrs_mode;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
lfp_options = bdb_find_section(display, BDB_LFP_OPTIONS);
|
2024-05-03 15:24:18 +03:00
|
|
|
if (!lfp_options)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
return;
|
|
|
|
|
2024-05-03 15:24:18 +03:00
|
|
|
panel->vbt.lvds_dither = lfp_options->pixel_dither;
|
2010-09-30 09:36:39 +01:00
|
|
|
|
2022-06-15 18:14:44 +03:00
|
|
|
/*
|
|
|
|
* Empirical evidence indicates the block size can be
|
|
|
|
* either 4,14,16,24+ bytes. For older VBTs no clear
|
|
|
|
* relationship between the block size vs. BDB version.
|
|
|
|
*/
|
2024-05-03 15:24:18 +03:00
|
|
|
if (get_blocksize(lfp_options) < 16)
|
2022-06-15 18:14:44 +03:00
|
|
|
return;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
|
2024-05-03 15:24:18 +03:00
|
|
|
drrs_mode = panel_bits(lfp_options->dps_panel_type_bits,
|
2022-06-15 18:14:45 +03:00
|
|
|
panel_type, 2);
|
2014-03-28 10:14:57 +05:30
|
|
|
/*
|
|
|
|
* VBT has static DRRS = 0 and seamless DRRS = 2.
|
|
|
|
* The below piece of code is required to adjust vbt.drrs_type
|
|
|
|
* to match the enum drrs_support_type.
|
|
|
|
*/
|
|
|
|
switch (drrs_mode) {
|
|
|
|
case 0:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.drrs_type = DRRS_TYPE_STATIC;
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm, "DRRS supported mode is static\n");
|
2014-03-28 10:14:57 +05:30
|
|
|
break;
|
|
|
|
case 2:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.drrs_type = DRRS_TYPE_SEAMLESS;
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"DRRS supported mode is seamless\n");
|
2014-03-28 10:14:57 +05:30
|
|
|
break;
|
|
|
|
default:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.drrs_type = DRRS_TYPE_NONE;
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"DRRS not supported (VBT input)\n");
|
2014-03-28 10:14:57 +05:30
|
|
|
break;
|
|
|
|
}
|
2019-11-15 08:51:31 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2024-08-09 17:27:06 +03:00
|
|
|
parse_lfp_panel_dtd(struct intel_display *display,
|
2022-05-10 13:42:39 +03:00
|
|
|
struct intel_panel *panel,
|
2024-05-03 15:24:18 +03:00
|
|
|
const struct bdb_lfp_data *lfp_data,
|
|
|
|
const struct bdb_lfp_data_ptrs *lfp_data_ptrs)
|
2019-11-15 08:51:31 -08:00
|
|
|
{
|
2024-05-03 15:24:17 +03:00
|
|
|
const struct bdb_edid_dtd *panel_dvo_timing;
|
2024-05-03 15:24:18 +03:00
|
|
|
const struct fp_timing *fp_timing;
|
2019-11-15 08:51:31 -08:00
|
|
|
struct drm_display_mode *panel_fixed_mode;
|
2022-05-10 13:42:39 +03:00
|
|
|
int panel_type = panel->vbt.panel_type;
|
2014-03-28 10:14:57 +05:30
|
|
|
|
2024-05-03 15:24:18 +03:00
|
|
|
panel_dvo_timing = get_lfp_dvo_timing(lfp_data,
|
|
|
|
lfp_data_ptrs,
|
|
|
|
panel_type);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
|
2009-03-24 12:23:04 -07:00
|
|
|
panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
|
2010-09-12 17:16:17 +01:00
|
|
|
if (!panel_fixed_mode)
|
|
|
|
return;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
fill_detail_timing_data(display, panel_fixed_mode, panel_dvo_timing);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
|
2024-05-03 15:24:18 +03:00
|
|
|
panel->vbt.lfp_vbt_mode = panel_fixed_mode;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
2022-03-23 20:29:28 +02:00
|
|
|
"Found panel mode in BIOS VBT legacy lfp table: " DRM_MODE_FMT "\n",
|
|
|
|
DRM_MODE_ARG(panel_fixed_mode));
|
2009-02-23 15:36:42 -08:00
|
|
|
|
2024-05-03 15:24:18 +03:00
|
|
|
fp_timing = get_lfp_fp_timing(lfp_data,
|
|
|
|
lfp_data_ptrs,
|
|
|
|
panel_type);
|
2022-04-05 20:33:53 +03:00
|
|
|
|
|
|
|
/* check the resolution, just to be sure */
|
|
|
|
if (fp_timing->x_res == panel_fixed_mode->hdisplay &&
|
|
|
|
fp_timing->y_res == panel_fixed_mode->vdisplay) {
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.bios_lvds_val = fp_timing->lvds_reg_val;
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
2022-04-05 20:33:53 +03:00
|
|
|
"VBT initial LVDS value %x\n",
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.bios_lvds_val);
|
2012-03-20 13:07:05 +01:00
|
|
|
}
|
2009-05-13 11:19:55 +08:00
|
|
|
}
|
|
|
|
|
2022-05-04 18:04:32 +03:00
|
|
|
static void
|
2024-08-09 17:27:06 +03:00
|
|
|
parse_lfp_data(struct intel_display *display,
|
2022-05-10 13:42:39 +03:00
|
|
|
struct intel_panel *panel)
|
2022-05-04 18:04:32 +03:00
|
|
|
{
|
2024-05-03 15:24:18 +03:00
|
|
|
const struct bdb_lfp_data *data;
|
|
|
|
const struct bdb_lfp_data_tail *tail;
|
|
|
|
const struct bdb_lfp_data_ptrs *ptrs;
|
2024-04-09 12:46:12 +03:00
|
|
|
const struct drm_edid_product_id *pnp_id;
|
2024-04-09 12:46:11 +03:00
|
|
|
struct drm_printer p;
|
2022-05-10 13:42:39 +03:00
|
|
|
int panel_type = panel->vbt.panel_type;
|
2022-05-04 18:04:32 +03:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
ptrs = bdb_find_section(display, BDB_LFP_DATA_PTRS);
|
2022-05-04 18:04:32 +03:00
|
|
|
if (!ptrs)
|
|
|
|
return;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
data = bdb_find_section(display, BDB_LFP_DATA);
|
2022-05-04 18:04:32 +03:00
|
|
|
if (!data)
|
|
|
|
return;
|
|
|
|
|
2024-05-03 15:24:18 +03:00
|
|
|
if (!panel->vbt.lfp_vbt_mode)
|
2024-08-09 17:27:06 +03:00
|
|
|
parse_lfp_panel_dtd(display, panel, data, ptrs);
|
2022-05-04 18:04:34 +03:00
|
|
|
|
2024-05-03 15:24:18 +03:00
|
|
|
pnp_id = get_lfp_pnp_id(data, ptrs, panel_type);
|
2024-04-09 12:46:11 +03:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
p = drm_dbg_printer(display->drm, DRM_UT_KMS, "Panel");
|
2024-04-09 12:46:12 +03:00
|
|
|
drm_edid_print_product_id(&p, pnp_id, false);
|
2022-05-10 13:42:42 +03:00
|
|
|
|
2022-05-04 18:04:34 +03:00
|
|
|
tail = get_lfp_data_tail(data, ptrs);
|
|
|
|
if (!tail)
|
|
|
|
return;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm, "Panel name: %.*s\n",
|
2022-05-10 13:42:42 +03:00
|
|
|
(int)sizeof(tail->panel_name[0].name),
|
|
|
|
tail->panel_name[panel_type].name);
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (display->vbt.version >= 188) {
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.seamless_drrs_min_refresh_rate =
|
2022-05-04 18:04:39 +03:00
|
|
|
tail->seamless_drrs_min_refresh_rate[panel_type];
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
2022-05-04 18:04:39 +03:00
|
|
|
"Seamless DRRS min refresh rate: %d Hz\n",
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.seamless_drrs_min_refresh_rate);
|
2022-05-04 18:04:39 +03:00
|
|
|
}
|
2022-05-04 18:04:32 +03:00
|
|
|
}
|
|
|
|
|
2019-11-15 08:51:32 -08:00
|
|
|
static void
|
2024-08-09 17:27:06 +03:00
|
|
|
parse_generic_dtd(struct intel_display *display,
|
2022-05-10 13:42:39 +03:00
|
|
|
struct intel_panel *panel)
|
2019-11-15 08:51:32 -08:00
|
|
|
{
|
|
|
|
const struct bdb_generic_dtd *generic_dtd;
|
|
|
|
const struct generic_dtd_entry *dtd;
|
|
|
|
struct drm_display_mode *panel_fixed_mode;
|
|
|
|
int num_dtd;
|
|
|
|
|
2022-05-04 18:04:32 +03:00
|
|
|
/*
|
|
|
|
* Older VBTs provided DTD information for internal displays through
|
|
|
|
* the "LFP panel tables" block (42). As of VBT revision 229 the
|
|
|
|
* DTD information should be provided via a newer "generic DTD"
|
|
|
|
* block (58). Just to be safe, we'll try the new generic DTD block
|
|
|
|
* first on VBT >= 229, but still fall back to trying the old LFP
|
|
|
|
* block if that fails.
|
|
|
|
*/
|
2024-08-09 17:27:06 +03:00
|
|
|
if (display->vbt.version < 229)
|
2022-05-04 18:04:32 +03:00
|
|
|
return;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
generic_dtd = bdb_find_section(display, BDB_GENERIC_DTD);
|
2019-11-15 08:51:32 -08:00
|
|
|
if (!generic_dtd)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (generic_dtd->gdtd_size < sizeof(struct generic_dtd_entry)) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_err(display->drm, "GDTD size %u is too small.\n",
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
generic_dtd->gdtd_size);
|
2019-11-15 08:51:32 -08:00
|
|
|
return;
|
|
|
|
} else if (generic_dtd->gdtd_size !=
|
|
|
|
sizeof(struct generic_dtd_entry)) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_err(display->drm, "Unexpected GDTD size %u\n",
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
generic_dtd->gdtd_size);
|
2019-11-15 08:51:32 -08:00
|
|
|
/* DTD has unknown fields, but keep going */
|
|
|
|
}
|
|
|
|
|
|
|
|
num_dtd = (get_blocksize(generic_dtd) -
|
|
|
|
sizeof(struct bdb_generic_dtd)) / generic_dtd->gdtd_size;
|
2022-05-10 13:42:39 +03:00
|
|
|
if (panel->vbt.panel_type >= num_dtd) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_err(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"Panel type %d not found in table of %d DTD's\n",
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.panel_type, num_dtd);
|
2019-11-15 08:51:32 -08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-05-10 13:42:39 +03:00
|
|
|
dtd = &generic_dtd->dtd[panel->vbt.panel_type];
|
2019-11-15 08:51:32 -08:00
|
|
|
|
|
|
|
panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
|
|
|
|
if (!panel_fixed_mode)
|
|
|
|
return;
|
|
|
|
|
|
|
|
panel_fixed_mode->hdisplay = dtd->hactive;
|
|
|
|
panel_fixed_mode->hsync_start =
|
|
|
|
panel_fixed_mode->hdisplay + dtd->hfront_porch;
|
|
|
|
panel_fixed_mode->hsync_end =
|
|
|
|
panel_fixed_mode->hsync_start + dtd->hsync;
|
2020-01-24 18:28:29 +05:30
|
|
|
panel_fixed_mode->htotal =
|
|
|
|
panel_fixed_mode->hdisplay + dtd->hblank;
|
2019-11-15 08:51:32 -08:00
|
|
|
|
|
|
|
panel_fixed_mode->vdisplay = dtd->vactive;
|
|
|
|
panel_fixed_mode->vsync_start =
|
|
|
|
panel_fixed_mode->vdisplay + dtd->vfront_porch;
|
|
|
|
panel_fixed_mode->vsync_end =
|
|
|
|
panel_fixed_mode->vsync_start + dtd->vsync;
|
2020-01-24 18:28:29 +05:30
|
|
|
panel_fixed_mode->vtotal =
|
|
|
|
panel_fixed_mode->vdisplay + dtd->vblank;
|
2019-11-15 08:51:32 -08:00
|
|
|
|
|
|
|
panel_fixed_mode->clock = dtd->pixel_clock;
|
|
|
|
panel_fixed_mode->width_mm = dtd->width_mm;
|
|
|
|
panel_fixed_mode->height_mm = dtd->height_mm;
|
|
|
|
|
|
|
|
panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
|
|
|
|
drm_mode_set_name(panel_fixed_mode);
|
|
|
|
|
|
|
|
if (dtd->hsync_positive_polarity)
|
|
|
|
panel_fixed_mode->flags |= DRM_MODE_FLAG_PHSYNC;
|
|
|
|
else
|
|
|
|
panel_fixed_mode->flags |= DRM_MODE_FLAG_NHSYNC;
|
|
|
|
|
|
|
|
if (dtd->vsync_positive_polarity)
|
|
|
|
panel_fixed_mode->flags |= DRM_MODE_FLAG_PVSYNC;
|
|
|
|
else
|
|
|
|
panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
2022-03-23 20:29:28 +02:00
|
|
|
"Found panel mode in BIOS VBT generic dtd table: " DRM_MODE_FMT "\n",
|
|
|
|
DRM_MODE_ARG(panel_fixed_mode));
|
2019-11-15 08:51:32 -08:00
|
|
|
|
2024-05-03 15:24:18 +03:00
|
|
|
panel->vbt.lfp_vbt_mode = panel_fixed_mode;
|
2019-11-15 08:51:32 -08:00
|
|
|
}
|
|
|
|
|
2013-12-14 20:38:29 -02:00
|
|
|
static void
|
2024-08-09 17:27:06 +03:00
|
|
|
parse_lfp_backlight(struct intel_display *display,
|
2022-05-10 13:42:39 +03:00
|
|
|
struct intel_panel *panel)
|
2013-12-14 20:38:29 -02:00
|
|
|
{
|
2024-05-03 15:24:18 +03:00
|
|
|
const struct bdb_lfp_backlight *backlight_data;
|
2019-05-31 16:14:58 +03:00
|
|
|
const struct lfp_backlight_data_entry *entry;
|
2022-05-10 13:42:39 +03:00
|
|
|
int panel_type = panel->vbt.panel_type;
|
2020-10-08 14:19:30 -07:00
|
|
|
u16 level;
|
2013-12-14 20:38:29 -02:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
backlight_data = bdb_find_section(display, BDB_LFP_BACKLIGHT);
|
2013-12-14 20:38:29 -02:00
|
|
|
if (!backlight_data)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (backlight_data->entry_size != sizeof(backlight_data->data[0])) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"Unsupported backlight data entry size %u\n",
|
|
|
|
backlight_data->entry_size);
|
2013-12-14 20:38:29 -02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
entry = &backlight_data->data[panel_type];
|
|
|
|
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.backlight.present = entry->type == BDB_BACKLIGHT_TYPE_PWM;
|
|
|
|
if (!panel->vbt.backlight.present) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"PWM backlight not present in VBT (type %u)\n",
|
|
|
|
entry->type);
|
2014-04-09 11:22:06 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.backlight.type = INTEL_BACKLIGHT_DISPLAY_DDI;
|
2023-02-07 13:16:26 +02:00
|
|
|
panel->vbt.backlight.controller = 0;
|
2024-08-09 17:27:06 +03:00
|
|
|
if (display->vbt.version >= 191) {
|
2024-02-21 18:06:24 -07:00
|
|
|
const struct lfp_backlight_control_method *method;
|
|
|
|
|
|
|
|
method = &backlight_data->backlight_control[panel_type];
|
|
|
|
panel->vbt.backlight.type = method->type;
|
|
|
|
panel->vbt.backlight.controller = method->controller;
|
2016-04-26 16:14:24 +03:00
|
|
|
}
|
|
|
|
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz;
|
|
|
|
panel->vbt.backlight.active_low_pwm = entry->active_low_pwm;
|
2020-10-08 14:19:30 -07:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (display->vbt.version >= 234) {
|
2020-10-08 14:19:30 -07:00
|
|
|
u16 min_level;
|
|
|
|
bool scale;
|
|
|
|
|
|
|
|
level = backlight_data->brightness_level[panel_type].level;
|
|
|
|
min_level = backlight_data->brightness_min_level[panel_type].level;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (display->vbt.version >= 236)
|
2020-10-08 14:19:30 -07:00
|
|
|
scale = backlight_data->brightness_precision_bits[panel_type] == 16;
|
|
|
|
else
|
|
|
|
scale = level > 255;
|
|
|
|
|
|
|
|
if (scale)
|
|
|
|
min_level = min_level / 255;
|
|
|
|
|
|
|
|
if (min_level > 255) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_warn(display->drm, "Brightness min level > 255\n");
|
2020-10-08 14:19:30 -07:00
|
|
|
level = 255;
|
|
|
|
}
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.backlight.min_brightness = min_level;
|
2021-09-08 19:56:06 +08:00
|
|
|
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.backlight.brightness_precision_bits =
|
2021-09-08 19:56:06 +08:00
|
|
|
backlight_data->brightness_precision_bits[panel_type];
|
2020-10-08 14:19:30 -07:00
|
|
|
} else {
|
|
|
|
level = backlight_data->level[panel_type];
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.backlight.min_brightness = entry->min_brightness;
|
2020-10-08 14:19:30 -07:00
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (display->vbt.version >= 239)
|
2023-02-20 18:47:18 +02:00
|
|
|
panel->vbt.backlight.hdr_dpcd_refresh_timeout =
|
|
|
|
DIV_ROUND_UP(backlight_data->hdr_dpcd_refresh_timeout[panel_type], 100);
|
|
|
|
else
|
|
|
|
panel->vbt.backlight.hdr_dpcd_refresh_timeout = 30;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"VBT backlight PWM modulation frequency %u Hz, "
|
|
|
|
"active %s, min brightness %u, level %u, controller %u\n",
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.backlight.pwm_freq_hz,
|
|
|
|
panel->vbt.backlight.active_low_pwm ? "low" : "high",
|
|
|
|
panel->vbt.backlight.min_brightness,
|
2020-10-08 14:19:30 -07:00
|
|
|
level,
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.backlight.controller);
|
2013-12-14 20:38:29 -02:00
|
|
|
}
|
|
|
|
|
2009-05-13 11:19:55 +08:00
|
|
|
static void
|
2024-08-09 17:27:06 +03:00
|
|
|
parse_sdvo_lvds_data(struct intel_display *display,
|
2024-05-03 15:24:19 +03:00
|
|
|
struct intel_panel *panel)
|
2009-05-13 11:19:55 +08:00
|
|
|
{
|
2024-05-03 15:24:19 +03:00
|
|
|
const struct bdb_sdvo_lvds_dtd *dtd;
|
2009-05-13 11:19:55 +08:00
|
|
|
struct drm_display_mode *panel_fixed_mode;
|
2011-01-29 16:50:25 +00:00
|
|
|
int index;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
index = display->params.vbt_sdvo_panel_type;
|
2012-03-01 06:44:35 +01:00
|
|
|
if (index == -2) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
2024-05-03 15:24:19 +03:00
|
|
|
"Ignore SDVO LVDS mode from BIOS VBT tables.\n");
|
2012-03-01 06:44:35 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-01-29 16:50:25 +00:00
|
|
|
if (index == -1) {
|
2015-04-15 15:18:28 +03:00
|
|
|
const struct bdb_sdvo_lvds_options *sdvo_lvds_options;
|
2011-01-29 16:50:25 +00:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
sdvo_lvds_options = bdb_find_section(display, BDB_SDVO_LVDS_OPTIONS);
|
2011-01-29 16:50:25 +00:00
|
|
|
if (!sdvo_lvds_options)
|
|
|
|
return;
|
|
|
|
|
|
|
|
index = sdvo_lvds_options->panel_type;
|
|
|
|
}
|
2009-05-13 11:19:55 +08:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
dtd = bdb_find_section(display, BDB_SDVO_LVDS_DTD);
|
2024-05-03 15:24:19 +03:00
|
|
|
if (!dtd)
|
2009-05-13 11:19:55 +08:00
|
|
|
return;
|
|
|
|
|
2024-05-28 14:29:00 +03:00
|
|
|
/*
|
|
|
|
* This should not happen, as long as the panel_type
|
|
|
|
* enumeration doesn't grow over 4 items. But if it does, it
|
|
|
|
* could lead to hard-to-detect bugs, so better double-check
|
|
|
|
* it here to be sure.
|
|
|
|
*/
|
|
|
|
if (index >= ARRAY_SIZE(dtd->dtd)) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_err(display->drm,
|
|
|
|
"index %d is larger than dtd->dtd[4] array\n",
|
2024-05-28 14:29:00 +03:00
|
|
|
index);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-03-24 12:23:04 -07:00
|
|
|
panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
|
2009-05-13 11:19:55 +08:00
|
|
|
if (!panel_fixed_mode)
|
|
|
|
return;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
fill_detail_timing_data(display, panel_fixed_mode, &dtd->dtd[index]);
|
2009-05-13 11:19:55 +08:00
|
|
|
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.sdvo_lvds_vbt_mode = panel_fixed_mode;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
2024-05-03 15:24:19 +03:00
|
|
|
"Found SDVO LVDS mode in BIOS VBT tables: " DRM_MODE_FMT "\n",
|
2022-03-23 20:29:28 +02:00
|
|
|
DRM_MODE_ARG(panel_fixed_mode));
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
static int intel_bios_ssc_frequency(struct intel_display *display,
|
2011-01-12 13:38:39 -08:00
|
|
|
bool alternate)
|
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
switch (DISPLAY_VER(display)) {
|
2011-01-12 13:38:39 -08:00
|
|
|
case 2:
|
2013-12-09 18:54:16 +02:00
|
|
|
return alternate ? 66667 : 48000;
|
2011-01-12 13:38:39 -08:00
|
|
|
case 3:
|
|
|
|
case 4:
|
2013-12-09 18:54:16 +02:00
|
|
|
return alternate ? 100000 : 96000;
|
2011-01-12 13:38:39 -08:00
|
|
|
default:
|
2013-12-09 18:54:16 +02:00
|
|
|
return alternate ? 100000 : 120000;
|
2011-01-12 13:38:39 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
static void
|
2024-08-09 17:27:06 +03:00
|
|
|
parse_general_features(struct intel_display *display)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
{
|
2015-04-15 15:18:28 +03:00
|
|
|
const struct bdb_general_features *general;
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
general = bdb_find_section(display, BDB_GENERAL_FEATURES);
|
2015-12-16 15:04:21 +02:00
|
|
|
if (!general)
|
|
|
|
return;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
display->vbt.int_tv_support = general->int_tv_support;
|
2015-12-16 15:04:21 +02:00
|
|
|
/* int_crt_support can't be trusted on earlier platforms */
|
2024-08-09 17:27:06 +03:00
|
|
|
if (display->vbt.version >= 155 &&
|
2024-10-28 21:48:44 +02:00
|
|
|
(HAS_DDI(display) || display->platform.valleyview))
|
2024-08-09 17:27:06 +03:00
|
|
|
display->vbt.int_crt_support = general->int_crt_support;
|
|
|
|
display->vbt.lvds_use_ssc = general->enable_ssc;
|
|
|
|
display->vbt.lvds_ssc_freq =
|
|
|
|
intel_bios_ssc_frequency(display, general->ssc_freq);
|
|
|
|
display->vbt.display_clock_mode = general->display_clock_mode;
|
|
|
|
display->vbt.fdi_rx_polarity_inverted = general->fdi_rx_polarity_inverted;
|
|
|
|
if (display->vbt.version >= 181) {
|
|
|
|
display->vbt.orientation = general->rotate_180 ?
|
2018-10-22 17:20:15 +03:00
|
|
|
DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP :
|
|
|
|
DRM_MODE_PANEL_ORIENTATION_NORMAL;
|
|
|
|
} else {
|
2024-08-09 17:27:06 +03:00
|
|
|
display->vbt.orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
|
2018-10-22 17:20:15 +03:00
|
|
|
}
|
2022-02-16 05:40:59 -08:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (display->vbt.version >= 249 && general->afc_startup_config) {
|
|
|
|
display->vbt.override_afc_startup = true;
|
|
|
|
display->vbt.override_afc_startup_val = general->afc_startup_config == 1 ? 0 : 7;
|
2022-02-16 05:40:59 -08:00
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d fdi_rx_polarity_inverted %d\n",
|
2024-08-09 17:27:06 +03:00
|
|
|
display->vbt.int_tv_support,
|
|
|
|
display->vbt.int_crt_support,
|
|
|
|
display->vbt.lvds_use_ssc,
|
|
|
|
display->vbt.lvds_ssc_freq,
|
|
|
|
display->vbt.display_clock_mode,
|
|
|
|
display->vbt.fdi_rx_polarity_inverted);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
}
|
|
|
|
|
2017-08-24 21:54:03 +03:00
|
|
|
static const struct child_device_config *
|
2017-08-24 21:54:08 +03:00
|
|
|
child_device_ptr(const struct bdb_general_definitions *defs, int i)
|
2015-03-25 18:45:58 +02:00
|
|
|
{
|
2017-08-24 21:54:08 +03:00
|
|
|
return (const void *) &defs->devices[i * defs->child_dev_size];
|
2015-03-25 18:45:58 +02:00
|
|
|
}
|
|
|
|
|
2009-05-31 17:17:17 +08:00
|
|
|
static void
|
2024-08-09 17:27:06 +03:00
|
|
|
parse_sdvo_device_mapping(struct intel_display *display)
|
2009-05-31 17:17:17 +08:00
|
|
|
{
|
2021-03-17 18:36:47 +02:00
|
|
|
const struct intel_bios_encoder_data *devdata;
|
2019-11-08 17:39:49 +02:00
|
|
|
int count = 0;
|
2015-08-18 14:28:55 +03:00
|
|
|
|
|
|
|
/*
|
2017-09-28 11:22:03 +03:00
|
|
|
* Only parse SDVO mappings on gens that could have SDVO. This isn't
|
|
|
|
* accurate and doesn't have to be, as long as it's not too strict.
|
2009-05-31 17:17:17 +08:00
|
|
|
*/
|
2024-08-09 17:27:06 +03:00
|
|
|
if (!IS_DISPLAY_VER(display, 3, 7)) {
|
|
|
|
drm_dbg_kms(display->drm, "Skipping SDVO device mapping\n");
|
2009-05-31 17:17:17 +08:00
|
|
|
return;
|
|
|
|
}
|
2017-09-28 11:22:03 +03:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
list_for_each_entry(devdata, &display->vbt.display_devices, node) {
|
2023-02-08 03:55:00 +02:00
|
|
|
const struct child_device_config *child = &devdata->child;
|
|
|
|
struct sdvo_device_mapping *mapping;
|
2017-09-28 11:22:03 +03:00
|
|
|
|
2024-07-11 05:27:31 +00:00
|
|
|
if (child->target_addr != TARGET_ADDR1 &&
|
|
|
|
child->target_addr != TARGET_ADDR2) {
|
2009-05-31 17:17:17 +08:00
|
|
|
/*
|
2024-07-11 05:27:31 +00:00
|
|
|
* If the target address is neither 0x70 nor 0x72,
|
2009-05-31 17:17:17 +08:00
|
|
|
* it is not a SDVO device. Skip it.
|
|
|
|
*/
|
|
|
|
continue;
|
|
|
|
}
|
2015-08-18 14:28:55 +03:00
|
|
|
if (child->dvo_port != DEVICE_PORT_DVOB &&
|
|
|
|
child->dvo_port != DEVICE_PORT_DVOC) {
|
2009-05-31 17:17:17 +08:00
|
|
|
/* skip the incorrect SDVO port */
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"Incorrect SDVO port. Skip it\n");
|
2009-05-31 17:17:17 +08:00
|
|
|
continue;
|
|
|
|
}
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
2024-07-11 05:27:31 +00:00
|
|
|
"the SDVO device with target addr %2x is found on"
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
" %s port\n",
|
2024-07-11 05:27:31 +00:00
|
|
|
child->target_addr,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
(child->dvo_port == DEVICE_PORT_DVOB) ?
|
|
|
|
"SDVOB" : "SDVOC");
|
2024-08-09 17:27:06 +03:00
|
|
|
mapping = &display->vbt.sdvo_mappings[child->dvo_port - 1];
|
2017-08-24 21:54:08 +03:00
|
|
|
if (!mapping->initialized) {
|
|
|
|
mapping->dvo_port = child->dvo_port;
|
2024-07-11 05:27:31 +00:00
|
|
|
mapping->target_addr = child->target_addr;
|
2017-08-24 21:54:08 +03:00
|
|
|
mapping->dvo_wiring = child->dvo_wiring;
|
|
|
|
mapping->ddc_pin = child->ddc_pin;
|
|
|
|
mapping->i2c_pin = child->i2c_pin;
|
|
|
|
mapping->initialized = 1;
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d\n",
|
2024-07-11 05:27:31 +00:00
|
|
|
mapping->dvo_port, mapping->target_addr,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
mapping->dvo_wiring, mapping->ddc_pin,
|
|
|
|
mapping->i2c_pin);
|
2009-05-31 17:17:17 +08:00
|
|
|
} else {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"Maybe one SDVO port is shared by "
|
|
|
|
"two SDVO device.\n");
|
2009-05-31 17:17:17 +08:00
|
|
|
}
|
2024-07-11 05:27:31 +00:00
|
|
|
if (child->target2_addr) {
|
2009-05-31 17:17:17 +08:00
|
|
|
/* Maybe this is a SDVO device with multiple inputs */
|
|
|
|
/* And the mapping info is not added */
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
2024-07-11 05:27:31 +00:00
|
|
|
"there exists the target2_addr. Maybe this"
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
" is a SDVO device with multiple inputs.\n");
|
2009-05-31 17:17:17 +08:00
|
|
|
}
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!count) {
|
|
|
|
/* No SDVO device info is found */
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"No SDVO device info is found in VBT\n");
|
2009-05-31 17:17:17 +08:00
|
|
|
}
|
|
|
|
}
|
2009-07-24 01:00:32 +08:00
|
|
|
|
|
|
|
static void
|
2024-08-09 17:27:06 +03:00
|
|
|
parse_driver_features(struct intel_display *display)
|
2009-07-24 01:00:32 +08:00
|
|
|
{
|
2015-04-15 15:18:28 +03:00
|
|
|
const struct bdb_driver_features *driver;
|
2009-07-24 01:00:32 +08:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
driver = bdb_find_section(display, BDB_DRIVER_FEATURES);
|
2009-08-17 13:31:43 -07:00
|
|
|
if (!driver)
|
|
|
|
return;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (DISPLAY_VER(display) >= 5) {
|
2018-05-18 18:01:38 +03:00
|
|
|
/*
|
|
|
|
* Note that we consider BDB_DRIVER_FEATURE_INT_SDVO_LVDS
|
|
|
|
* to mean "eDP". The VBT spec doesn't agree with that
|
|
|
|
* interpretation, but real world VBTs seem to.
|
|
|
|
*/
|
|
|
|
if (driver->lvds_config != BDB_DRIVER_FEATURE_INT_LVDS)
|
2024-08-09 17:27:06 +03:00
|
|
|
display->vbt.int_lvds_support = 0;
|
2018-05-18 18:01:38 +03:00
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* FIXME it's not clear which BDB version has the LVDS config
|
|
|
|
* bits defined. Revision history in the VBT spec says:
|
|
|
|
* "0.92 | Add two definitions for VBT value of LVDS Active
|
|
|
|
* Config (00b and 11b values defined) | 06/13/2005"
|
|
|
|
* but does not the specify the BDB version.
|
|
|
|
*
|
|
|
|
* So far version 134 (on i945gm) is the oldest VBT observed
|
|
|
|
* in the wild with the bits correctly populated. Version
|
|
|
|
* 108 (on i85x) does not have the bits correctly populated.
|
|
|
|
*/
|
2024-08-09 17:27:06 +03:00
|
|
|
if (display->vbt.version >= 134 &&
|
2018-05-18 18:01:38 +03:00
|
|
|
driver->lvds_config != BDB_DRIVER_FEATURE_INT_LVDS &&
|
|
|
|
driver->lvds_config != BDB_DRIVER_FEATURE_INT_SDVO_LVDS)
|
2024-08-09 17:27:06 +03:00
|
|
|
display->vbt.int_lvds_support = 0;
|
2018-05-18 18:01:38 +03:00
|
|
|
}
|
2022-05-10 13:42:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2024-08-09 17:27:06 +03:00
|
|
|
parse_panel_driver_features(struct intel_display *display,
|
2022-05-10 13:42:39 +03:00
|
|
|
struct intel_panel *panel)
|
2022-05-10 13:42:37 +03:00
|
|
|
{
|
|
|
|
const struct bdb_driver_features *driver;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
driver = bdb_find_section(display, BDB_DRIVER_FEATURES);
|
2022-05-10 13:42:37 +03:00
|
|
|
if (!driver)
|
|
|
|
return;
|
2009-08-17 13:31:43 -07:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (display->vbt.version < 228) {
|
|
|
|
drm_dbg_kms(display->drm, "DRRS State Enabled:%d\n",
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
driver->drrs_enabled);
|
2019-11-27 17:48:52 -08:00
|
|
|
/*
|
|
|
|
* If DRRS is not supported, drrs_type has to be set to 0.
|
|
|
|
* This is because, VBT is configured in such a way that
|
|
|
|
* static DRRS is 0 and DRRS not supported is represented by
|
|
|
|
* driver->drrs_enabled=false
|
|
|
|
*/
|
2022-05-31 22:18:44 +03:00
|
|
|
if (!driver->drrs_enabled && panel->vbt.drrs_type != DRRS_TYPE_NONE) {
|
|
|
|
/*
|
|
|
|
* FIXME Should DMRRS perhaps be treated as seamless
|
|
|
|
* but without the automatic downclocking?
|
|
|
|
*/
|
|
|
|
if (driver->dmrrs_enabled)
|
|
|
|
panel->vbt.drrs_type = DRRS_TYPE_STATIC;
|
|
|
|
else
|
|
|
|
panel->vbt.drrs_type = DRRS_TYPE_NONE;
|
|
|
|
}
|
2019-11-27 17:48:52 -08:00
|
|
|
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.psr.enable = driver->psr_enabled;
|
2019-11-27 17:48:52 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2024-08-09 17:27:06 +03:00
|
|
|
parse_power_conservation_features(struct intel_display *display,
|
2022-05-10 13:42:39 +03:00
|
|
|
struct intel_panel *panel)
|
2019-11-27 17:48:52 -08:00
|
|
|
{
|
|
|
|
const struct bdb_lfp_power *power;
|
2022-05-10 13:42:39 +03:00
|
|
|
u8 panel_type = panel->vbt.panel_type;
|
2019-11-27 17:48:52 -08:00
|
|
|
|
2022-05-31 22:18:39 +03:00
|
|
|
panel->vbt.vrr = true; /* matches Windows behaviour */
|
2019-11-27 17:48:52 -08:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (display->vbt.version < 228)
|
2019-11-27 17:48:52 -08:00
|
|
|
return;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
power = bdb_find_section(display, BDB_LFP_POWER);
|
2019-11-27 17:48:52 -08:00
|
|
|
if (!power)
|
|
|
|
return;
|
|
|
|
|
2022-06-15 18:14:45 +03:00
|
|
|
panel->vbt.psr.enable = panel_bool(power->psr, panel_type);
|
2019-11-27 17:48:52 -08:00
|
|
|
|
2014-03-28 10:14:57 +05:30
|
|
|
/*
|
|
|
|
* If DRRS is not supported, drrs_type has to be set to 0.
|
|
|
|
* This is because, VBT is configured in such a way that
|
|
|
|
* static DRRS is 0 and DRRS not supported is represented by
|
2019-11-27 17:48:52 -08:00
|
|
|
* power->drrs & BIT(panel_type)=false
|
2014-03-28 10:14:57 +05:30
|
|
|
*/
|
2022-06-15 18:14:45 +03:00
|
|
|
if (!panel_bool(power->drrs, panel_type) && panel->vbt.drrs_type != DRRS_TYPE_NONE) {
|
2022-05-31 22:18:44 +03:00
|
|
|
/*
|
|
|
|
* FIXME Should DMRRS perhaps be treated as seamless
|
|
|
|
* but without the automatic downclocking?
|
|
|
|
*/
|
2022-06-15 18:14:45 +03:00
|
|
|
if (panel_bool(power->dmrrs, panel_type))
|
2022-05-31 22:18:44 +03:00
|
|
|
panel->vbt.drrs_type = DRRS_TYPE_STATIC;
|
|
|
|
else
|
|
|
|
panel->vbt.drrs_type = DRRS_TYPE_NONE;
|
|
|
|
}
|
2020-07-08 13:55:10 -07:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (display->vbt.version >= 232)
|
2022-06-15 18:14:45 +03:00
|
|
|
panel->vbt.edp.hobl = panel_bool(power->hobl, panel_type);
|
2022-05-31 22:18:39 +03:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (display->vbt.version >= 233)
|
2022-06-15 18:14:45 +03:00
|
|
|
panel->vbt.vrr = panel_bool(power->vrr_feature_enabled,
|
|
|
|
panel_type);
|
2009-07-24 01:00:32 +08:00
|
|
|
}
|
|
|
|
|
2024-11-06 23:58:53 +02:00
|
|
|
static void vbt_edp_to_pps_delays(struct intel_pps_delays *pps,
|
|
|
|
const struct edp_power_seq *edp_pps)
|
|
|
|
{
|
2024-11-06 23:58:54 +02:00
|
|
|
pps->power_up = edp_pps->t1_t3;
|
|
|
|
pps->backlight_on = edp_pps->t8;
|
|
|
|
pps->backlight_off = edp_pps->t9;
|
|
|
|
pps->power_down = edp_pps->t10;
|
|
|
|
pps->power_cycle = edp_pps->t11_t12;
|
2024-11-06 23:58:53 +02:00
|
|
|
}
|
|
|
|
|
2010-01-13 11:19:52 +08:00
|
|
|
static void
|
2024-08-09 17:27:06 +03:00
|
|
|
parse_edp(struct intel_display *display,
|
2022-05-10 13:42:39 +03:00
|
|
|
struct intel_panel *panel)
|
2010-01-13 11:19:52 +08:00
|
|
|
{
|
2015-04-15 15:18:28 +03:00
|
|
|
const struct bdb_edp *edp;
|
2017-08-25 17:11:23 +03:00
|
|
|
const struct edp_fast_link_params *edp_link_params;
|
2022-05-10 13:42:39 +03:00
|
|
|
int panel_type = panel->vbt.panel_type;
|
2010-01-13 11:19:52 +08:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
edp = bdb_find_section(display, BDB_EDP);
|
2018-05-08 17:08:14 +03:00
|
|
|
if (!edp)
|
2010-01-13 11:19:52 +08:00
|
|
|
return;
|
|
|
|
|
2022-06-15 18:14:45 +03:00
|
|
|
switch (panel_bits(edp->color_depth, panel_type, 2)) {
|
2010-01-13 11:19:52 +08:00
|
|
|
case EDP_18BPP:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.edp.bpp = 18;
|
2010-01-13 11:19:52 +08:00
|
|
|
break;
|
|
|
|
case EDP_24BPP:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.edp.bpp = 24;
|
2010-01-13 11:19:52 +08:00
|
|
|
break;
|
|
|
|
case EDP_30BPP:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.edp.bpp = 30;
|
2010-01-13 11:19:52 +08:00
|
|
|
break;
|
|
|
|
}
|
2010-09-24 10:24:28 +01:00
|
|
|
|
2010-10-07 16:01:14 -07:00
|
|
|
/* Get the eDP sequencing and link info */
|
2017-08-25 17:11:23 +03:00
|
|
|
edp_link_params = &edp->fast_link_params[panel_type];
|
2010-09-24 10:24:28 +01:00
|
|
|
|
2024-11-06 23:58:53 +02:00
|
|
|
vbt_edp_to_pps_delays(&panel->vbt.edp.pps,
|
|
|
|
&edp->power_seqs[panel_type]);
|
2010-09-24 10:24:28 +01:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (display->vbt.version >= 224) {
|
2022-06-02 23:56:49 +03:00
|
|
|
panel->vbt.edp.rate =
|
|
|
|
edp->edp_fast_link_training_rate[panel_type] * 20;
|
|
|
|
} else {
|
|
|
|
switch (edp_link_params->rate) {
|
|
|
|
case EDP_RATE_1_62:
|
|
|
|
panel->vbt.edp.rate = 162000;
|
|
|
|
break;
|
|
|
|
case EDP_RATE_2_7:
|
|
|
|
panel->vbt.edp.rate = 270000;
|
|
|
|
break;
|
|
|
|
case EDP_RATE_5_4:
|
|
|
|
panel->vbt.edp.rate = 540000;
|
|
|
|
break;
|
|
|
|
default:
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
2022-06-02 23:56:49 +03:00
|
|
|
"VBT has unknown eDP link rate value %u\n",
|
|
|
|
edp_link_params->rate);
|
|
|
|
break;
|
|
|
|
}
|
2014-05-06 14:56:51 +03:00
|
|
|
}
|
|
|
|
|
2010-10-07 16:01:14 -07:00
|
|
|
switch (edp_link_params->lanes) {
|
2014-05-06 14:56:51 +03:00
|
|
|
case EDP_LANE_1:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.edp.lanes = 1;
|
2010-10-07 16:01:14 -07:00
|
|
|
break;
|
2014-05-06 14:56:51 +03:00
|
|
|
case EDP_LANE_2:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.edp.lanes = 2;
|
2010-10-07 16:01:14 -07:00
|
|
|
break;
|
2014-05-06 14:56:51 +03:00
|
|
|
case EDP_LANE_4:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.edp.lanes = 4;
|
2010-10-07 16:01:14 -07:00
|
|
|
break;
|
2014-05-06 14:56:51 +03:00
|
|
|
default:
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"VBT has unknown eDP lane count value %u\n",
|
|
|
|
edp_link_params->lanes);
|
2014-05-06 14:56:51 +03:00
|
|
|
break;
|
2010-10-07 16:01:14 -07:00
|
|
|
}
|
2014-05-06 14:56:51 +03:00
|
|
|
|
2010-10-07 16:01:14 -07:00
|
|
|
switch (edp_link_params->preemphasis) {
|
2014-05-06 14:56:51 +03:00
|
|
|
case EDP_PREEMPHASIS_NONE:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_0;
|
2010-10-07 16:01:14 -07:00
|
|
|
break;
|
2014-05-06 14:56:51 +03:00
|
|
|
case EDP_PREEMPHASIS_3_5dB:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_1;
|
2010-10-07 16:01:14 -07:00
|
|
|
break;
|
2014-05-06 14:56:51 +03:00
|
|
|
case EDP_PREEMPHASIS_6dB:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_2;
|
2010-10-07 16:01:14 -07:00
|
|
|
break;
|
2014-05-06 14:56:51 +03:00
|
|
|
case EDP_PREEMPHASIS_9_5dB:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_3;
|
2010-10-07 16:01:14 -07:00
|
|
|
break;
|
2014-05-06 14:56:51 +03:00
|
|
|
default:
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"VBT has unknown eDP pre-emphasis value %u\n",
|
|
|
|
edp_link_params->preemphasis);
|
2014-05-06 14:56:51 +03:00
|
|
|
break;
|
2010-10-07 16:01:14 -07:00
|
|
|
}
|
2014-05-06 14:56:51 +03:00
|
|
|
|
2010-10-07 16:01:14 -07:00
|
|
|
switch (edp_link_params->vswing) {
|
2014-05-06 14:56:51 +03:00
|
|
|
case EDP_VSWING_0_4V:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
|
2010-10-07 16:01:14 -07:00
|
|
|
break;
|
2014-05-06 14:56:51 +03:00
|
|
|
case EDP_VSWING_0_6V:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_1;
|
2010-10-07 16:01:14 -07:00
|
|
|
break;
|
2014-05-06 14:56:51 +03:00
|
|
|
case EDP_VSWING_0_8V:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
|
2010-10-07 16:01:14 -07:00
|
|
|
break;
|
2014-05-06 14:56:51 +03:00
|
|
|
case EDP_VSWING_1_2V:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
|
2010-10-07 16:01:14 -07:00
|
|
|
break;
|
2014-05-06 14:56:51 +03:00
|
|
|
default:
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"VBT has unknown eDP voltage swing value %u\n",
|
|
|
|
edp_link_params->vswing);
|
2014-05-06 14:56:51 +03:00
|
|
|
break;
|
2010-10-07 16:01:14 -07:00
|
|
|
}
|
2015-02-25 10:29:11 +05:30
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (display->vbt.version >= 173) {
|
2018-06-12 12:19:29 +03:00
|
|
|
u8 vswing;
|
2015-02-25 10:29:11 +05:30
|
|
|
|
2015-05-06 17:35:48 +05:30
|
|
|
/* Don't read from VBT if module parameter has valid value*/
|
2024-08-09 17:27:06 +03:00
|
|
|
if (display->params.edp_vswing) {
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.edp.low_vswing =
|
2024-08-09 17:27:06 +03:00
|
|
|
display->params.edp_vswing == 1;
|
2015-05-06 17:35:48 +05:30
|
|
|
} else {
|
|
|
|
vswing = (edp->edp_vswing_preemph >> (panel_type * 4)) & 0xF;
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.edp.low_vswing = vswing == 0;
|
2015-05-06 17:35:48 +05:30
|
|
|
}
|
2015-02-25 10:29:11 +05:30
|
|
|
}
|
2022-03-10 02:47:53 +02:00
|
|
|
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.edp.drrs_msa_timing_delay =
|
2022-06-15 18:14:45 +03:00
|
|
|
panel_bits(edp->sdrrs_msa_timing_delay, panel_type, 2);
|
2022-06-02 23:57:23 +03:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (display->vbt.version >= 244)
|
2022-06-02 23:57:23 +03:00
|
|
|
panel->vbt.edp.max_link_rate =
|
|
|
|
edp->edp_max_port_link_rate[panel_type] * 20;
|
2024-05-17 17:53:55 +03:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (display->vbt.version >= 251)
|
2024-05-17 17:53:55 +03:00
|
|
|
panel->vbt.edp.dsc_disable =
|
|
|
|
panel_bool(edp->edp_dsc_disable, panel_type);
|
2010-01-13 11:19:52 +08:00
|
|
|
}
|
|
|
|
|
2014-11-14 08:52:30 -08:00
|
|
|
static void
|
2024-08-09 17:27:06 +03:00
|
|
|
parse_psr(struct intel_display *display,
|
2022-05-10 13:42:39 +03:00
|
|
|
struct intel_panel *panel)
|
2014-11-14 08:52:30 -08:00
|
|
|
{
|
2015-04-15 15:18:28 +03:00
|
|
|
const struct bdb_psr *psr;
|
|
|
|
const struct psr_table *psr_table;
|
2022-05-10 13:42:39 +03:00
|
|
|
int panel_type = panel->vbt.panel_type;
|
2014-11-14 08:52:30 -08:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
psr = bdb_find_section(display, BDB_PSR);
|
2014-11-14 08:52:30 -08:00
|
|
|
if (!psr) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm, "No PSR BDB found.\n");
|
2014-11-14 08:52:30 -08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
psr_table = &psr->psr_table[panel_type];
|
|
|
|
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.psr.full_link = psr_table->full_link;
|
|
|
|
panel->vbt.psr.require_aux_wakeup = psr_table->require_aux_to_wakeup;
|
2014-11-14 08:52:30 -08:00
|
|
|
|
|
|
|
/* Allowed VBT values goes from 0 to 15 */
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.psr.idle_frames = psr_table->idle_frames < 0 ? 0 :
|
2014-11-14 08:52:30 -08:00
|
|
|
psr_table->idle_frames > 15 ? 15 : psr_table->idle_frames;
|
|
|
|
|
2018-05-22 14:57:23 +05:30
|
|
|
/*
|
|
|
|
* New psr options 0=500us, 1=100us, 2=2500us, 3=0us
|
|
|
|
* Old decimal value is wake up time in multiples of 100 us.
|
|
|
|
*/
|
2024-08-09 17:27:06 +03:00
|
|
|
if (display->vbt.version >= 205 &&
|
2024-10-28 21:48:44 +02:00
|
|
|
(DISPLAY_VER(display) >= 9 && !display->platform.broxton)) {
|
2018-05-22 14:57:23 +05:30
|
|
|
switch (psr_table->tp1_wakeup_time) {
|
|
|
|
case 0:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.psr.tp1_wakeup_time_us = 500;
|
2018-05-22 14:57:23 +05:30
|
|
|
break;
|
|
|
|
case 1:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.psr.tp1_wakeup_time_us = 100;
|
2018-05-22 14:57:23 +05:30
|
|
|
break;
|
|
|
|
case 3:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.psr.tp1_wakeup_time_us = 0;
|
2018-05-22 14:57:23 +05:30
|
|
|
break;
|
|
|
|
default:
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"VBT tp1 wakeup time value %d is outside range[0-3], defaulting to max value 2500us\n",
|
|
|
|
psr_table->tp1_wakeup_time);
|
2020-08-23 17:36:59 -05:00
|
|
|
fallthrough;
|
2018-05-22 14:57:23 +05:30
|
|
|
case 2:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.psr.tp1_wakeup_time_us = 2500;
|
2018-05-22 14:57:23 +05:30
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (psr_table->tp2_tp3_wakeup_time) {
|
|
|
|
case 0:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.psr.tp2_tp3_wakeup_time_us = 500;
|
2018-05-22 14:57:23 +05:30
|
|
|
break;
|
|
|
|
case 1:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.psr.tp2_tp3_wakeup_time_us = 100;
|
2018-05-22 14:57:23 +05:30
|
|
|
break;
|
|
|
|
case 3:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.psr.tp2_tp3_wakeup_time_us = 0;
|
2018-05-22 14:57:23 +05:30
|
|
|
break;
|
|
|
|
default:
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"VBT tp2_tp3 wakeup time value %d is outside range[0-3], defaulting to max value 2500us\n",
|
|
|
|
psr_table->tp2_tp3_wakeup_time);
|
2020-08-23 17:36:59 -05:00
|
|
|
fallthrough;
|
2018-05-22 14:57:23 +05:30
|
|
|
case 2:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.psr.tp2_tp3_wakeup_time_us = 2500;
|
2018-05-22 14:57:23 +05:30
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.psr.tp1_wakeup_time_us = psr_table->tp1_wakeup_time * 100;
|
|
|
|
panel->vbt.psr.tp2_tp3_wakeup_time_us = psr_table->tp2_tp3_wakeup_time * 100;
|
2018-05-22 14:57:23 +05:30
|
|
|
}
|
2019-03-12 12:57:41 -07:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (display->vbt.version >= 226) {
|
2019-07-17 15:34:51 -07:00
|
|
|
u32 wakeup_time = psr->psr2_tp2_tp3_wakeup_time;
|
2019-03-12 12:57:41 -07:00
|
|
|
|
2022-06-15 18:14:45 +03:00
|
|
|
wakeup_time = panel_bits(wakeup_time, panel_type, 2);
|
2019-03-12 12:57:41 -07:00
|
|
|
switch (wakeup_time) {
|
|
|
|
case 0:
|
|
|
|
wakeup_time = 500;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
wakeup_time = 100;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
wakeup_time = 50;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
case 2:
|
|
|
|
wakeup_time = 2500;
|
|
|
|
break;
|
|
|
|
}
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.psr.psr2_tp2_tp3_wakeup_time_us = wakeup_time;
|
2019-03-12 12:57:41 -07:00
|
|
|
} else {
|
|
|
|
/* Reusing PSR1 wakeup time for PSR2 in older VBTs */
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.psr.psr2_tp2_tp3_wakeup_time_us = panel->vbt.psr.tp2_tp3_wakeup_time_us;
|
2019-03-12 12:57:41 -07:00
|
|
|
}
|
2014-11-14 08:52:30 -08:00
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
static void parse_dsi_backlight_ports(struct intel_display *display,
|
2022-05-10 13:42:39 +03:00
|
|
|
struct intel_panel *panel,
|
|
|
|
enum port port)
|
2017-10-13 18:14:59 +05:30
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
enum port port_bc = DISPLAY_VER(display) >= 11 ? PORT_B : PORT_C;
|
2022-08-16 18:37:21 +03:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (!panel->vbt.dsi.config->dual_link || display->vbt.version < 197) {
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.dsi.bl_ports = BIT(port);
|
|
|
|
if (panel->vbt.dsi.config->cabc_supported)
|
|
|
|
panel->vbt.dsi.cabc_ports = BIT(port);
|
2017-10-13 18:14:59 +05:30
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-05-10 13:42:39 +03:00
|
|
|
switch (panel->vbt.dsi.config->dl_dcs_backlight_ports) {
|
2017-10-13 18:14:59 +05:30
|
|
|
case DL_DCS_PORT_A:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.dsi.bl_ports = BIT(PORT_A);
|
2017-10-13 18:14:59 +05:30
|
|
|
break;
|
|
|
|
case DL_DCS_PORT_C:
|
2022-08-16 18:37:21 +03:00
|
|
|
panel->vbt.dsi.bl_ports = BIT(port_bc);
|
2017-10-13 18:14:59 +05:30
|
|
|
break;
|
|
|
|
default:
|
|
|
|
case DL_DCS_PORT_A_AND_C:
|
2022-08-16 18:37:21 +03:00
|
|
|
panel->vbt.dsi.bl_ports = BIT(PORT_A) | BIT(port_bc);
|
2017-10-13 18:14:59 +05:30
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2022-05-10 13:42:39 +03:00
|
|
|
if (!panel->vbt.dsi.config->cabc_supported)
|
2017-10-13 18:14:59 +05:30
|
|
|
return;
|
|
|
|
|
2022-05-10 13:42:39 +03:00
|
|
|
switch (panel->vbt.dsi.config->dl_dcs_cabc_ports) {
|
2017-10-13 18:14:59 +05:30
|
|
|
case DL_DCS_PORT_A:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.dsi.cabc_ports = BIT(PORT_A);
|
2017-10-13 18:14:59 +05:30
|
|
|
break;
|
|
|
|
case DL_DCS_PORT_C:
|
2022-08-16 18:37:21 +03:00
|
|
|
panel->vbt.dsi.cabc_ports = BIT(port_bc);
|
2017-10-13 18:14:59 +05:30
|
|
|
break;
|
|
|
|
default:
|
|
|
|
case DL_DCS_PORT_A_AND_C:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.dsi.cabc_ports =
|
2022-08-16 18:37:21 +03:00
|
|
|
BIT(PORT_A) | BIT(port_bc);
|
2017-10-13 18:14:59 +05:30
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-27 15:12:25 +03:00
|
|
|
static void
|
2024-08-09 17:27:06 +03:00
|
|
|
parse_mipi_config(struct intel_display *display,
|
2022-05-10 13:42:39 +03:00
|
|
|
struct intel_panel *panel)
|
2013-08-27 15:12:25 +03:00
|
|
|
{
|
2015-04-15 15:18:28 +03:00
|
|
|
const struct bdb_mipi_config *start;
|
|
|
|
const struct mipi_config *config;
|
|
|
|
const struct mipi_pps_data *pps;
|
2022-05-10 13:42:39 +03:00
|
|
|
int panel_type = panel->vbt.panel_type;
|
2017-10-13 18:14:59 +05:30
|
|
|
enum port port;
|
2014-04-14 11:00:34 +05:30
|
|
|
|
2014-05-27 19:33:59 +05:30
|
|
|
/* parse MIPI blocks only if LFP type is MIPI */
|
2024-08-09 17:27:06 +03:00
|
|
|
if (!intel_bios_is_dsi_present(display, &port))
|
2014-05-27 19:33:59 +05:30
|
|
|
return;
|
|
|
|
|
2014-04-14 11:00:34 +05:30
|
|
|
/* Initialize this to undefined indicating no generic MIPI support */
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.dsi.panel_id = MIPI_DSI_UNDEFINED_PANEL_ID;
|
2014-04-14 11:00:34 +05:30
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
start = bdb_find_section(display, BDB_MIPI_CONFIG);
|
2014-04-14 11:00:34 +05:30
|
|
|
if (!start) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm, "No MIPI config BDB found");
|
2013-08-27 15:12:25 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-09-23 18:24:48 +03:00
|
|
|
drm_dbg_kms(display->drm, "Found MIPI Config block, panel index = %d\n",
|
|
|
|
panel_type);
|
2014-04-14 11:00:34 +05:30
|
|
|
|
|
|
|
/*
|
|
|
|
* get hold of the correct configuration block and pps data as per
|
|
|
|
* the panel_type as index
|
|
|
|
*/
|
|
|
|
config = &start->config[panel_type];
|
|
|
|
pps = &start->pps[panel_type];
|
|
|
|
|
|
|
|
/* store as of now full data. Trim when we realise all is not needed */
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.dsi.config = kmemdup(config, sizeof(struct mipi_config), GFP_KERNEL);
|
|
|
|
if (!panel->vbt.dsi.config)
|
2014-04-14 11:00:34 +05:30
|
|
|
return;
|
|
|
|
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.dsi.pps = kmemdup(pps, sizeof(struct mipi_pps_data), GFP_KERNEL);
|
|
|
|
if (!panel->vbt.dsi.pps) {
|
|
|
|
kfree(panel->vbt.dsi.config);
|
2014-04-14 11:00:34 +05:30
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
parse_dsi_backlight_ports(display, panel, port);
|
2016-03-30 17:03:40 +03:00
|
|
|
|
2018-10-22 17:20:15 +03:00
|
|
|
/* FIXME is the 90 vs. 270 correct? */
|
|
|
|
switch (config->rotation) {
|
|
|
|
case ENABLE_ROTATION_0:
|
|
|
|
/*
|
|
|
|
* Most (all?) VBTs claim 0 degrees despite having
|
|
|
|
* an upside down panel, thus we do not trust this.
|
|
|
|
*/
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.dsi.orientation =
|
2018-10-22 17:20:15 +03:00
|
|
|
DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
|
|
|
|
break;
|
|
|
|
case ENABLE_ROTATION_90:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.dsi.orientation =
|
2018-10-22 17:20:15 +03:00
|
|
|
DRM_MODE_PANEL_ORIENTATION_RIGHT_UP;
|
|
|
|
break;
|
|
|
|
case ENABLE_ROTATION_180:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.dsi.orientation =
|
2018-10-22 17:20:15 +03:00
|
|
|
DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP;
|
|
|
|
break;
|
|
|
|
case ENABLE_ROTATION_270:
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.dsi.orientation =
|
2018-10-22 17:20:15 +03:00
|
|
|
DRM_MODE_PANEL_ORIENTATION_LEFT_UP;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-04-14 11:00:34 +05:30
|
|
|
/* We have mandatory mipi config blocks. Initialize as generic panel */
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.dsi.panel_id = MIPI_DSI_GENERIC_PANEL_ID;
|
2015-12-21 15:10:54 +02:00
|
|
|
}
|
|
|
|
|
2016-01-05 15:50:51 +02:00
|
|
|
/* Find the sequence block and size for the given panel. */
|
|
|
|
static const u8 *
|
2024-08-09 17:27:06 +03:00
|
|
|
find_panel_sequence_block(struct intel_display *display,
|
2024-02-08 17:17:14 +02:00
|
|
|
const struct bdb_mipi_sequence *sequence,
|
2016-01-11 15:15:02 +02:00
|
|
|
u16 panel_id, u32 *seq_size)
|
2016-01-05 15:50:51 +02:00
|
|
|
{
|
|
|
|
u32 total = get_blocksize(sequence);
|
|
|
|
const u8 *data = &sequence->data[0];
|
|
|
|
u8 current_id;
|
2016-01-11 15:15:02 +02:00
|
|
|
u32 current_size;
|
|
|
|
int header_size = sequence->version >= 3 ? 5 : 3;
|
2016-01-05 15:50:51 +02:00
|
|
|
int index = 0;
|
|
|
|
int i;
|
|
|
|
|
2016-01-11 15:15:02 +02:00
|
|
|
/* skip new block size */
|
|
|
|
if (sequence->version >= 3)
|
|
|
|
data += 4;
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_MIPI_CONFIGURATIONS && index < total; i++) {
|
|
|
|
if (index + header_size > total) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_err(display->drm,
|
|
|
|
"Invalid sequence block (header)\n");
|
2016-01-11 15:15:02 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-01-05 15:50:51 +02:00
|
|
|
current_id = *(data + index);
|
2016-01-11 15:15:02 +02:00
|
|
|
if (sequence->version >= 3)
|
|
|
|
current_size = *((const u32 *)(data + index + 1));
|
|
|
|
else
|
|
|
|
current_size = *((const u16 *)(data + index + 1));
|
2016-01-05 15:50:51 +02:00
|
|
|
|
2016-01-11 15:15:02 +02:00
|
|
|
index += header_size;
|
2016-01-05 15:50:51 +02:00
|
|
|
|
|
|
|
if (index + current_size > total) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_err(display->drm, "Invalid sequence block\n");
|
2016-01-05 15:50:51 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_id == panel_id) {
|
|
|
|
*seq_size = current_size;
|
|
|
|
return data + index;
|
|
|
|
}
|
|
|
|
|
|
|
|
index += current_size;
|
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_err(display->drm,
|
|
|
|
"Sequence block detected but no valid configuration\n");
|
2016-01-05 15:50:51 +02:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
static int goto_next_sequence(struct intel_display *display,
|
2024-02-08 17:17:14 +02:00
|
|
|
const u8 *data, int index, int total)
|
2015-12-21 15:10:57 +02:00
|
|
|
{
|
|
|
|
u16 len;
|
|
|
|
|
|
|
|
/* Skip Sequence Byte. */
|
|
|
|
for (index = index + 1; index < total; index += len) {
|
|
|
|
u8 operation_byte = *(data + index);
|
|
|
|
index++;
|
|
|
|
|
|
|
|
switch (operation_byte) {
|
|
|
|
case MIPI_SEQ_ELEM_END:
|
|
|
|
return index;
|
|
|
|
case MIPI_SEQ_ELEM_SEND_PKT:
|
|
|
|
if (index + 4 > total)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
len = *((const u16 *)(data + index + 2)) + 4;
|
|
|
|
break;
|
|
|
|
case MIPI_SEQ_ELEM_DELAY:
|
|
|
|
len = 4;
|
|
|
|
break;
|
|
|
|
case MIPI_SEQ_ELEM_GPIO:
|
|
|
|
len = 2;
|
|
|
|
break;
|
2015-12-21 15:11:00 +02:00
|
|
|
case MIPI_SEQ_ELEM_I2C:
|
|
|
|
if (index + 7 > total)
|
|
|
|
return 0;
|
|
|
|
len = *(data + index + 6) + 7;
|
|
|
|
break;
|
2015-12-21 15:10:57 +02:00
|
|
|
default:
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_err(display->drm, "Unknown operation byte\n");
|
2015-12-21 15:10:57 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
static int goto_next_sequence_v3(struct intel_display *display,
|
2024-02-08 17:17:14 +02:00
|
|
|
const u8 *data, int index, int total)
|
2016-01-11 15:15:02 +02:00
|
|
|
{
|
|
|
|
int seq_end;
|
|
|
|
u16 len;
|
2016-01-14 17:12:07 +02:00
|
|
|
u32 size_of_sequence;
|
2016-01-11 15:15:02 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Could skip sequence based on Size of Sequence alone, but also do some
|
|
|
|
* checking on the structure.
|
|
|
|
*/
|
|
|
|
if (total < 5) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_err(display->drm, "Too small sequence size\n");
|
2016-01-11 15:15:02 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-01-14 17:12:07 +02:00
|
|
|
/* Skip Sequence Byte. */
|
|
|
|
index++;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Size of Sequence. Excludes the Sequence Byte and the size itself,
|
|
|
|
* includes MIPI_SEQ_ELEM_END byte, excludes the final MIPI_SEQ_END
|
|
|
|
* byte.
|
|
|
|
*/
|
2018-06-12 12:19:29 +03:00
|
|
|
size_of_sequence = *((const u32 *)(data + index));
|
2016-01-14 17:12:07 +02:00
|
|
|
index += 4;
|
|
|
|
|
|
|
|
seq_end = index + size_of_sequence;
|
2016-01-11 15:15:02 +02:00
|
|
|
if (seq_end > total) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_err(display->drm, "Invalid sequence size\n");
|
2016-01-11 15:15:02 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-01-14 17:12:07 +02:00
|
|
|
for (; index < total; index += len) {
|
2016-01-11 15:15:02 +02:00
|
|
|
u8 operation_byte = *(data + index);
|
|
|
|
index++;
|
|
|
|
|
|
|
|
if (operation_byte == MIPI_SEQ_ELEM_END) {
|
|
|
|
if (index != seq_end) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_err(display->drm,
|
|
|
|
"Invalid element structure\n");
|
2016-01-11 15:15:02 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
|
|
|
len = *(data + index);
|
|
|
|
index++;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FIXME: Would be nice to check elements like for v1/v2 in
|
|
|
|
* goto_next_sequence() above.
|
|
|
|
*/
|
|
|
|
switch (operation_byte) {
|
|
|
|
case MIPI_SEQ_ELEM_SEND_PKT:
|
|
|
|
case MIPI_SEQ_ELEM_DELAY:
|
|
|
|
case MIPI_SEQ_ELEM_GPIO:
|
|
|
|
case MIPI_SEQ_ELEM_I2C:
|
|
|
|
case MIPI_SEQ_ELEM_SPI:
|
|
|
|
case MIPI_SEQ_ELEM_PMIC:
|
|
|
|
break;
|
|
|
|
default:
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_err(display->drm, "Unknown operation byte %u\n",
|
2024-02-08 17:17:14 +02:00
|
|
|
operation_byte);
|
2016-01-11 15:15:02 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
drm/i915: Fix DSI panels with v1 MIPI sequences without a DEASSERT sequence v3
So far models of the Dell Venue 8 Pro, with a panel with MIPI panel
index = 3, one of which has been kindly provided to me by Jan Brummer,
where not working with the i915 driver, giving a black screen on the
first modeset.
The problem with at least these Dells is that their VBT defines a MIPI
ASSERT sequence, but not a DEASSERT sequence. Instead they DEASSERT the
reset in their INIT_OTP sequence, but the deassert must be done before
calling intel_dsi_device_ready(), so that is too late.
Simply doing the INIT_OTP sequence earlier is not enough to fix this,
because the INIT_OTP sequence also sends various MIPI packets to the
panel, which can only happen after calling intel_dsi_device_ready().
This commit fixes this by splitting the INIT_OTP sequence into everything
before the first DSI packet and everything else, including the first DSI
packet. The first part (everything before the first DSI packet) is then
used as deassert sequence.
Changed in v2:
-Split the init OTP sequence into a deassert reset and the actual init
OTP sequence, instead of calling it earlier and then having the first
mipi_exec_send_packet() call call intel_dsi_device_ready().
Changes in v3:
-Move the whole shebang to intel_bios.c
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=82880
References: https://bugs.freedesktop.org/show_bug.cgi?id=101205
Cc: Jan-Michael Brummer <jan.brummer@tabos.org>
Reported-by: Jan-Michael Brummer <jan.brummer@tabos.org>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Acked-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180214082151.25015-3-hdegoede@redhat.com
2018-02-14 09:21:51 +01:00
|
|
|
/*
|
|
|
|
* Get len of pre-fixed deassert fragment from a v1 init OTP sequence,
|
|
|
|
* skip all delay + gpio operands and stop at the first DSI packet op.
|
|
|
|
*/
|
2024-08-09 17:27:06 +03:00
|
|
|
static int get_init_otp_deassert_fragment_len(struct intel_display *display,
|
2022-05-10 13:42:39 +03:00
|
|
|
struct intel_panel *panel)
|
drm/i915: Fix DSI panels with v1 MIPI sequences without a DEASSERT sequence v3
So far models of the Dell Venue 8 Pro, with a panel with MIPI panel
index = 3, one of which has been kindly provided to me by Jan Brummer,
where not working with the i915 driver, giving a black screen on the
first modeset.
The problem with at least these Dells is that their VBT defines a MIPI
ASSERT sequence, but not a DEASSERT sequence. Instead they DEASSERT the
reset in their INIT_OTP sequence, but the deassert must be done before
calling intel_dsi_device_ready(), so that is too late.
Simply doing the INIT_OTP sequence earlier is not enough to fix this,
because the INIT_OTP sequence also sends various MIPI packets to the
panel, which can only happen after calling intel_dsi_device_ready().
This commit fixes this by splitting the INIT_OTP sequence into everything
before the first DSI packet and everything else, including the first DSI
packet. The first part (everything before the first DSI packet) is then
used as deassert sequence.
Changed in v2:
-Split the init OTP sequence into a deassert reset and the actual init
OTP sequence, instead of calling it earlier and then having the first
mipi_exec_send_packet() call call intel_dsi_device_ready().
Changes in v3:
-Move the whole shebang to intel_bios.c
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=82880
References: https://bugs.freedesktop.org/show_bug.cgi?id=101205
Cc: Jan-Michael Brummer <jan.brummer@tabos.org>
Reported-by: Jan-Michael Brummer <jan.brummer@tabos.org>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Acked-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180214082151.25015-3-hdegoede@redhat.com
2018-02-14 09:21:51 +01:00
|
|
|
{
|
2022-05-10 13:42:39 +03:00
|
|
|
const u8 *data = panel->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP];
|
drm/i915: Fix DSI panels with v1 MIPI sequences without a DEASSERT sequence v3
So far models of the Dell Venue 8 Pro, with a panel with MIPI panel
index = 3, one of which has been kindly provided to me by Jan Brummer,
where not working with the i915 driver, giving a black screen on the
first modeset.
The problem with at least these Dells is that their VBT defines a MIPI
ASSERT sequence, but not a DEASSERT sequence. Instead they DEASSERT the
reset in their INIT_OTP sequence, but the deassert must be done before
calling intel_dsi_device_ready(), so that is too late.
Simply doing the INIT_OTP sequence earlier is not enough to fix this,
because the INIT_OTP sequence also sends various MIPI packets to the
panel, which can only happen after calling intel_dsi_device_ready().
This commit fixes this by splitting the INIT_OTP sequence into everything
before the first DSI packet and everything else, including the first DSI
packet. The first part (everything before the first DSI packet) is then
used as deassert sequence.
Changed in v2:
-Split the init OTP sequence into a deassert reset and the actual init
OTP sequence, instead of calling it earlier and then having the first
mipi_exec_send_packet() call call intel_dsi_device_ready().
Changes in v3:
-Move the whole shebang to intel_bios.c
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=82880
References: https://bugs.freedesktop.org/show_bug.cgi?id=101205
Cc: Jan-Michael Brummer <jan.brummer@tabos.org>
Reported-by: Jan-Michael Brummer <jan.brummer@tabos.org>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Acked-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180214082151.25015-3-hdegoede@redhat.com
2018-02-14 09:21:51 +01:00
|
|
|
int index, len;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (drm_WARN_ON(display->drm,
|
drm/i915/bios: Apply vlv_fixup_mipi_sequences() to v2 mipi-sequences too
It turns out that the fixup from vlv_fixup_mipi_sequences() is necessary
for some DSI panel's with version 2 mipi-sequences too.
Specifically the Acer Iconia One 8 A1-840 (not to be confused with the
A1-840FHD which is different) has the following sequences:
BDB block 53 (1284 bytes) - MIPI sequence block:
Sequence block version v2
Panel 0 *
Sequence 2 - MIPI_SEQ_INIT_OTP
GPIO index 9, source 0, set 0 (0x00)
Delay: 50000 us
GPIO index 9, source 0, set 1 (0x01)
Delay: 6000 us
GPIO index 9, source 0, set 0 (0x00)
Delay: 6000 us
GPIO index 9, source 0, set 1 (0x01)
Delay: 25000 us
Send DCS: Port A, VC 0, LP, Type 39, Length 5, Data ff aa 55 a5 80
Send DCS: Port A, VC 0, LP, Type 39, Length 3, Data 6f 11 00
...
Send DCS: Port A, VC 0, LP, Type 05, Length 1, Data 29
Delay: 120000 us
Sequence 4 - MIPI_SEQ_DISPLAY_OFF
Send DCS: Port A, VC 0, LP, Type 05, Length 1, Data 28
Delay: 105000 us
Send DCS: Port A, VC 0, LP, Type 05, Length 2, Data 10 00
Delay: 10000 us
Sequence 5 - MIPI_SEQ_ASSERT_RESET
Delay: 10000 us
GPIO index 9, source 0, set 0 (0x00)
Notice how there is no MIPI_SEQ_DEASSERT_RESET, instead the deassert
is done at the beginning of MIPI_SEQ_INIT_OTP, which is exactly what
the fixup from vlv_fixup_mipi_sequences() fixes up.
Extend it to also apply to v2 sequences, this fixes the panel not working
on the Acer Iconia One 8 A1-840.
Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14605
Signed-off-by: Hans de Goede <hansg@kernel.org>
Acked-by: Jani Nikula <jani.nikula@intel.com>
Link: https://lore.kernel.org/r/20250703143824.7121-1-hansg@kernel.org
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
2025-07-07 23:14:12 +02:00
|
|
|
!data || panel->vbt.dsi.seq_version >= 3))
|
drm/i915: Fix DSI panels with v1 MIPI sequences without a DEASSERT sequence v3
So far models of the Dell Venue 8 Pro, with a panel with MIPI panel
index = 3, one of which has been kindly provided to me by Jan Brummer,
where not working with the i915 driver, giving a black screen on the
first modeset.
The problem with at least these Dells is that their VBT defines a MIPI
ASSERT sequence, but not a DEASSERT sequence. Instead they DEASSERT the
reset in their INIT_OTP sequence, but the deassert must be done before
calling intel_dsi_device_ready(), so that is too late.
Simply doing the INIT_OTP sequence earlier is not enough to fix this,
because the INIT_OTP sequence also sends various MIPI packets to the
panel, which can only happen after calling intel_dsi_device_ready().
This commit fixes this by splitting the INIT_OTP sequence into everything
before the first DSI packet and everything else, including the first DSI
packet. The first part (everything before the first DSI packet) is then
used as deassert sequence.
Changed in v2:
-Split the init OTP sequence into a deassert reset and the actual init
OTP sequence, instead of calling it earlier and then having the first
mipi_exec_send_packet() call call intel_dsi_device_ready().
Changes in v3:
-Move the whole shebang to intel_bios.c
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=82880
References: https://bugs.freedesktop.org/show_bug.cgi?id=101205
Cc: Jan-Michael Brummer <jan.brummer@tabos.org>
Reported-by: Jan-Michael Brummer <jan.brummer@tabos.org>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Acked-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180214082151.25015-3-hdegoede@redhat.com
2018-02-14 09:21:51 +01:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* index = 1 to skip sequence byte */
|
|
|
|
for (index = 1; data[index] != MIPI_SEQ_ELEM_END; index += len) {
|
|
|
|
switch (data[index]) {
|
|
|
|
case MIPI_SEQ_ELEM_SEND_PKT:
|
|
|
|
return index == 1 ? 0 : index;
|
|
|
|
case MIPI_SEQ_ELEM_DELAY:
|
|
|
|
len = 5; /* 1 byte for operand + uint32 */
|
|
|
|
break;
|
|
|
|
case MIPI_SEQ_ELEM_GPIO:
|
|
|
|
len = 3; /* 1 byte for op, 1 for gpio_nr, 1 for value */
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
drm/i915/bios: Apply vlv_fixup_mipi_sequences() to v2 mipi-sequences too
It turns out that the fixup from vlv_fixup_mipi_sequences() is necessary
for some DSI panel's with version 2 mipi-sequences too.
Specifically the Acer Iconia One 8 A1-840 (not to be confused with the
A1-840FHD which is different) has the following sequences:
BDB block 53 (1284 bytes) - MIPI sequence block:
Sequence block version v2
Panel 0 *
Sequence 2 - MIPI_SEQ_INIT_OTP
GPIO index 9, source 0, set 0 (0x00)
Delay: 50000 us
GPIO index 9, source 0, set 1 (0x01)
Delay: 6000 us
GPIO index 9, source 0, set 0 (0x00)
Delay: 6000 us
GPIO index 9, source 0, set 1 (0x01)
Delay: 25000 us
Send DCS: Port A, VC 0, LP, Type 39, Length 5, Data ff aa 55 a5 80
Send DCS: Port A, VC 0, LP, Type 39, Length 3, Data 6f 11 00
...
Send DCS: Port A, VC 0, LP, Type 05, Length 1, Data 29
Delay: 120000 us
Sequence 4 - MIPI_SEQ_DISPLAY_OFF
Send DCS: Port A, VC 0, LP, Type 05, Length 1, Data 28
Delay: 105000 us
Send DCS: Port A, VC 0, LP, Type 05, Length 2, Data 10 00
Delay: 10000 us
Sequence 5 - MIPI_SEQ_ASSERT_RESET
Delay: 10000 us
GPIO index 9, source 0, set 0 (0x00)
Notice how there is no MIPI_SEQ_DEASSERT_RESET, instead the deassert
is done at the beginning of MIPI_SEQ_INIT_OTP, which is exactly what
the fixup from vlv_fixup_mipi_sequences() fixes up.
Extend it to also apply to v2 sequences, this fixes the panel not working
on the Acer Iconia One 8 A1-840.
Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14605
Signed-off-by: Hans de Goede <hansg@kernel.org>
Acked-by: Jani Nikula <jani.nikula@intel.com>
Link: https://lore.kernel.org/r/20250703143824.7121-1-hansg@kernel.org
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
2025-07-07 23:14:12 +02:00
|
|
|
* Some v1/v2 VBT MIPI sequences do the deassert in the init OTP sequence.
|
drm/i915: Fix DSI panels with v1 MIPI sequences without a DEASSERT sequence v3
So far models of the Dell Venue 8 Pro, with a panel with MIPI panel
index = 3, one of which has been kindly provided to me by Jan Brummer,
where not working with the i915 driver, giving a black screen on the
first modeset.
The problem with at least these Dells is that their VBT defines a MIPI
ASSERT sequence, but not a DEASSERT sequence. Instead they DEASSERT the
reset in their INIT_OTP sequence, but the deassert must be done before
calling intel_dsi_device_ready(), so that is too late.
Simply doing the INIT_OTP sequence earlier is not enough to fix this,
because the INIT_OTP sequence also sends various MIPI packets to the
panel, which can only happen after calling intel_dsi_device_ready().
This commit fixes this by splitting the INIT_OTP sequence into everything
before the first DSI packet and everything else, including the first DSI
packet. The first part (everything before the first DSI packet) is then
used as deassert sequence.
Changed in v2:
-Split the init OTP sequence into a deassert reset and the actual init
OTP sequence, instead of calling it earlier and then having the first
mipi_exec_send_packet() call call intel_dsi_device_ready().
Changes in v3:
-Move the whole shebang to intel_bios.c
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=82880
References: https://bugs.freedesktop.org/show_bug.cgi?id=101205
Cc: Jan-Michael Brummer <jan.brummer@tabos.org>
Reported-by: Jan-Michael Brummer <jan.brummer@tabos.org>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Acked-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180214082151.25015-3-hdegoede@redhat.com
2018-02-14 09:21:51 +01:00
|
|
|
* The deassert must be done before calling intel_dsi_device_ready, so for
|
|
|
|
* these devices we split the init OTP sequence into a deassert sequence and
|
|
|
|
* the actual init OTP part.
|
|
|
|
*/
|
2024-08-09 17:27:06 +03:00
|
|
|
static void vlv_fixup_mipi_sequences(struct intel_display *display,
|
2024-03-05 10:36:59 +02:00
|
|
|
struct intel_panel *panel)
|
drm/i915: Fix DSI panels with v1 MIPI sequences without a DEASSERT sequence v3
So far models of the Dell Venue 8 Pro, with a panel with MIPI panel
index = 3, one of which has been kindly provided to me by Jan Brummer,
where not working with the i915 driver, giving a black screen on the
first modeset.
The problem with at least these Dells is that their VBT defines a MIPI
ASSERT sequence, but not a DEASSERT sequence. Instead they DEASSERT the
reset in their INIT_OTP sequence, but the deassert must be done before
calling intel_dsi_device_ready(), so that is too late.
Simply doing the INIT_OTP sequence earlier is not enough to fix this,
because the INIT_OTP sequence also sends various MIPI packets to the
panel, which can only happen after calling intel_dsi_device_ready().
This commit fixes this by splitting the INIT_OTP sequence into everything
before the first DSI packet and everything else, including the first DSI
packet. The first part (everything before the first DSI packet) is then
used as deassert sequence.
Changed in v2:
-Split the init OTP sequence into a deassert reset and the actual init
OTP sequence, instead of calling it earlier and then having the first
mipi_exec_send_packet() call call intel_dsi_device_ready().
Changes in v3:
-Move the whole shebang to intel_bios.c
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=82880
References: https://bugs.freedesktop.org/show_bug.cgi?id=101205
Cc: Jan-Michael Brummer <jan.brummer@tabos.org>
Reported-by: Jan-Michael Brummer <jan.brummer@tabos.org>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Acked-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180214082151.25015-3-hdegoede@redhat.com
2018-02-14 09:21:51 +01:00
|
|
|
{
|
|
|
|
u8 *init_otp;
|
|
|
|
int len;
|
|
|
|
|
drm/i915/bios: Apply vlv_fixup_mipi_sequences() to v2 mipi-sequences too
It turns out that the fixup from vlv_fixup_mipi_sequences() is necessary
for some DSI panel's with version 2 mipi-sequences too.
Specifically the Acer Iconia One 8 A1-840 (not to be confused with the
A1-840FHD which is different) has the following sequences:
BDB block 53 (1284 bytes) - MIPI sequence block:
Sequence block version v2
Panel 0 *
Sequence 2 - MIPI_SEQ_INIT_OTP
GPIO index 9, source 0, set 0 (0x00)
Delay: 50000 us
GPIO index 9, source 0, set 1 (0x01)
Delay: 6000 us
GPIO index 9, source 0, set 0 (0x00)
Delay: 6000 us
GPIO index 9, source 0, set 1 (0x01)
Delay: 25000 us
Send DCS: Port A, VC 0, LP, Type 39, Length 5, Data ff aa 55 a5 80
Send DCS: Port A, VC 0, LP, Type 39, Length 3, Data 6f 11 00
...
Send DCS: Port A, VC 0, LP, Type 05, Length 1, Data 29
Delay: 120000 us
Sequence 4 - MIPI_SEQ_DISPLAY_OFF
Send DCS: Port A, VC 0, LP, Type 05, Length 1, Data 28
Delay: 105000 us
Send DCS: Port A, VC 0, LP, Type 05, Length 2, Data 10 00
Delay: 10000 us
Sequence 5 - MIPI_SEQ_ASSERT_RESET
Delay: 10000 us
GPIO index 9, source 0, set 0 (0x00)
Notice how there is no MIPI_SEQ_DEASSERT_RESET, instead the deassert
is done at the beginning of MIPI_SEQ_INIT_OTP, which is exactly what
the fixup from vlv_fixup_mipi_sequences() fixes up.
Extend it to also apply to v2 sequences, this fixes the panel not working
on the Acer Iconia One 8 A1-840.
Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14605
Signed-off-by: Hans de Goede <hansg@kernel.org>
Acked-by: Jani Nikula <jani.nikula@intel.com>
Link: https://lore.kernel.org/r/20250703143824.7121-1-hansg@kernel.org
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
2025-07-07 23:14:12 +02:00
|
|
|
/* Limit this to v1/v2 vid-mode sequences */
|
2022-05-10 13:42:39 +03:00
|
|
|
if (panel->vbt.dsi.config->is_cmd_mode ||
|
drm/i915/bios: Apply vlv_fixup_mipi_sequences() to v2 mipi-sequences too
It turns out that the fixup from vlv_fixup_mipi_sequences() is necessary
for some DSI panel's with version 2 mipi-sequences too.
Specifically the Acer Iconia One 8 A1-840 (not to be confused with the
A1-840FHD which is different) has the following sequences:
BDB block 53 (1284 bytes) - MIPI sequence block:
Sequence block version v2
Panel 0 *
Sequence 2 - MIPI_SEQ_INIT_OTP
GPIO index 9, source 0, set 0 (0x00)
Delay: 50000 us
GPIO index 9, source 0, set 1 (0x01)
Delay: 6000 us
GPIO index 9, source 0, set 0 (0x00)
Delay: 6000 us
GPIO index 9, source 0, set 1 (0x01)
Delay: 25000 us
Send DCS: Port A, VC 0, LP, Type 39, Length 5, Data ff aa 55 a5 80
Send DCS: Port A, VC 0, LP, Type 39, Length 3, Data 6f 11 00
...
Send DCS: Port A, VC 0, LP, Type 05, Length 1, Data 29
Delay: 120000 us
Sequence 4 - MIPI_SEQ_DISPLAY_OFF
Send DCS: Port A, VC 0, LP, Type 05, Length 1, Data 28
Delay: 105000 us
Send DCS: Port A, VC 0, LP, Type 05, Length 2, Data 10 00
Delay: 10000 us
Sequence 5 - MIPI_SEQ_ASSERT_RESET
Delay: 10000 us
GPIO index 9, source 0, set 0 (0x00)
Notice how there is no MIPI_SEQ_DEASSERT_RESET, instead the deassert
is done at the beginning of MIPI_SEQ_INIT_OTP, which is exactly what
the fixup from vlv_fixup_mipi_sequences() fixes up.
Extend it to also apply to v2 sequences, this fixes the panel not working
on the Acer Iconia One 8 A1-840.
Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14605
Signed-off-by: Hans de Goede <hansg@kernel.org>
Acked-by: Jani Nikula <jani.nikula@intel.com>
Link: https://lore.kernel.org/r/20250703143824.7121-1-hansg@kernel.org
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
2025-07-07 23:14:12 +02:00
|
|
|
panel->vbt.dsi.seq_version >= 3)
|
drm/i915: Fix DSI panels with v1 MIPI sequences without a DEASSERT sequence v3
So far models of the Dell Venue 8 Pro, with a panel with MIPI panel
index = 3, one of which has been kindly provided to me by Jan Brummer,
where not working with the i915 driver, giving a black screen on the
first modeset.
The problem with at least these Dells is that their VBT defines a MIPI
ASSERT sequence, but not a DEASSERT sequence. Instead they DEASSERT the
reset in their INIT_OTP sequence, but the deassert must be done before
calling intel_dsi_device_ready(), so that is too late.
Simply doing the INIT_OTP sequence earlier is not enough to fix this,
because the INIT_OTP sequence also sends various MIPI packets to the
panel, which can only happen after calling intel_dsi_device_ready().
This commit fixes this by splitting the INIT_OTP sequence into everything
before the first DSI packet and everything else, including the first DSI
packet. The first part (everything before the first DSI packet) is then
used as deassert sequence.
Changed in v2:
-Split the init OTP sequence into a deassert reset and the actual init
OTP sequence, instead of calling it earlier and then having the first
mipi_exec_send_packet() call call intel_dsi_device_ready().
Changes in v3:
-Move the whole shebang to intel_bios.c
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=82880
References: https://bugs.freedesktop.org/show_bug.cgi?id=101205
Cc: Jan-Michael Brummer <jan.brummer@tabos.org>
Reported-by: Jan-Michael Brummer <jan.brummer@tabos.org>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Acked-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180214082151.25015-3-hdegoede@redhat.com
2018-02-14 09:21:51 +01:00
|
|
|
return;
|
|
|
|
|
|
|
|
/* Only do this if there are otp and assert seqs and no deassert seq */
|
2022-05-10 13:42:39 +03:00
|
|
|
if (!panel->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP] ||
|
|
|
|
!panel->vbt.dsi.sequence[MIPI_SEQ_ASSERT_RESET] ||
|
|
|
|
panel->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET])
|
drm/i915: Fix DSI panels with v1 MIPI sequences without a DEASSERT sequence v3
So far models of the Dell Venue 8 Pro, with a panel with MIPI panel
index = 3, one of which has been kindly provided to me by Jan Brummer,
where not working with the i915 driver, giving a black screen on the
first modeset.
The problem with at least these Dells is that their VBT defines a MIPI
ASSERT sequence, but not a DEASSERT sequence. Instead they DEASSERT the
reset in their INIT_OTP sequence, but the deassert must be done before
calling intel_dsi_device_ready(), so that is too late.
Simply doing the INIT_OTP sequence earlier is not enough to fix this,
because the INIT_OTP sequence also sends various MIPI packets to the
panel, which can only happen after calling intel_dsi_device_ready().
This commit fixes this by splitting the INIT_OTP sequence into everything
before the first DSI packet and everything else, including the first DSI
packet. The first part (everything before the first DSI packet) is then
used as deassert sequence.
Changed in v2:
-Split the init OTP sequence into a deassert reset and the actual init
OTP sequence, instead of calling it earlier and then having the first
mipi_exec_send_packet() call call intel_dsi_device_ready().
Changes in v3:
-Move the whole shebang to intel_bios.c
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=82880
References: https://bugs.freedesktop.org/show_bug.cgi?id=101205
Cc: Jan-Michael Brummer <jan.brummer@tabos.org>
Reported-by: Jan-Michael Brummer <jan.brummer@tabos.org>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Acked-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180214082151.25015-3-hdegoede@redhat.com
2018-02-14 09:21:51 +01:00
|
|
|
return;
|
|
|
|
|
|
|
|
/* The deassert-sequence ends at the first DSI packet */
|
2024-08-09 17:27:06 +03:00
|
|
|
len = get_init_otp_deassert_fragment_len(display, panel);
|
drm/i915: Fix DSI panels with v1 MIPI sequences without a DEASSERT sequence v3
So far models of the Dell Venue 8 Pro, with a panel with MIPI panel
index = 3, one of which has been kindly provided to me by Jan Brummer,
where not working with the i915 driver, giving a black screen on the
first modeset.
The problem with at least these Dells is that their VBT defines a MIPI
ASSERT sequence, but not a DEASSERT sequence. Instead they DEASSERT the
reset in their INIT_OTP sequence, but the deassert must be done before
calling intel_dsi_device_ready(), so that is too late.
Simply doing the INIT_OTP sequence earlier is not enough to fix this,
because the INIT_OTP sequence also sends various MIPI packets to the
panel, which can only happen after calling intel_dsi_device_ready().
This commit fixes this by splitting the INIT_OTP sequence into everything
before the first DSI packet and everything else, including the first DSI
packet. The first part (everything before the first DSI packet) is then
used as deassert sequence.
Changed in v2:
-Split the init OTP sequence into a deassert reset and the actual init
OTP sequence, instead of calling it earlier and then having the first
mipi_exec_send_packet() call call intel_dsi_device_ready().
Changes in v3:
-Move the whole shebang to intel_bios.c
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=82880
References: https://bugs.freedesktop.org/show_bug.cgi?id=101205
Cc: Jan-Michael Brummer <jan.brummer@tabos.org>
Reported-by: Jan-Michael Brummer <jan.brummer@tabos.org>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Acked-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180214082151.25015-3-hdegoede@redhat.com
2018-02-14 09:21:51 +01:00
|
|
|
if (!len)
|
|
|
|
return;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"Using init OTP fragment to deassert reset\n");
|
drm/i915: Fix DSI panels with v1 MIPI sequences without a DEASSERT sequence v3
So far models of the Dell Venue 8 Pro, with a panel with MIPI panel
index = 3, one of which has been kindly provided to me by Jan Brummer,
where not working with the i915 driver, giving a black screen on the
first modeset.
The problem with at least these Dells is that their VBT defines a MIPI
ASSERT sequence, but not a DEASSERT sequence. Instead they DEASSERT the
reset in their INIT_OTP sequence, but the deassert must be done before
calling intel_dsi_device_ready(), so that is too late.
Simply doing the INIT_OTP sequence earlier is not enough to fix this,
because the INIT_OTP sequence also sends various MIPI packets to the
panel, which can only happen after calling intel_dsi_device_ready().
This commit fixes this by splitting the INIT_OTP sequence into everything
before the first DSI packet and everything else, including the first DSI
packet. The first part (everything before the first DSI packet) is then
used as deassert sequence.
Changed in v2:
-Split the init OTP sequence into a deassert reset and the actual init
OTP sequence, instead of calling it earlier and then having the first
mipi_exec_send_packet() call call intel_dsi_device_ready().
Changes in v3:
-Move the whole shebang to intel_bios.c
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=82880
References: https://bugs.freedesktop.org/show_bug.cgi?id=101205
Cc: Jan-Michael Brummer <jan.brummer@tabos.org>
Reported-by: Jan-Michael Brummer <jan.brummer@tabos.org>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Acked-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180214082151.25015-3-hdegoede@redhat.com
2018-02-14 09:21:51 +01:00
|
|
|
|
|
|
|
/* Copy the fragment, update seq byte and terminate it */
|
2022-05-10 13:42:39 +03:00
|
|
|
init_otp = (u8 *)panel->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP];
|
|
|
|
panel->vbt.dsi.deassert_seq = kmemdup(init_otp, len + 1, GFP_KERNEL);
|
|
|
|
if (!panel->vbt.dsi.deassert_seq)
|
drm/i915: Fix DSI panels with v1 MIPI sequences without a DEASSERT sequence v3
So far models of the Dell Venue 8 Pro, with a panel with MIPI panel
index = 3, one of which has been kindly provided to me by Jan Brummer,
where not working with the i915 driver, giving a black screen on the
first modeset.
The problem with at least these Dells is that their VBT defines a MIPI
ASSERT sequence, but not a DEASSERT sequence. Instead they DEASSERT the
reset in their INIT_OTP sequence, but the deassert must be done before
calling intel_dsi_device_ready(), so that is too late.
Simply doing the INIT_OTP sequence earlier is not enough to fix this,
because the INIT_OTP sequence also sends various MIPI packets to the
panel, which can only happen after calling intel_dsi_device_ready().
This commit fixes this by splitting the INIT_OTP sequence into everything
before the first DSI packet and everything else, including the first DSI
packet. The first part (everything before the first DSI packet) is then
used as deassert sequence.
Changed in v2:
-Split the init OTP sequence into a deassert reset and the actual init
OTP sequence, instead of calling it earlier and then having the first
mipi_exec_send_packet() call call intel_dsi_device_ready().
Changes in v3:
-Move the whole shebang to intel_bios.c
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=82880
References: https://bugs.freedesktop.org/show_bug.cgi?id=101205
Cc: Jan-Michael Brummer <jan.brummer@tabos.org>
Reported-by: Jan-Michael Brummer <jan.brummer@tabos.org>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Acked-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180214082151.25015-3-hdegoede@redhat.com
2018-02-14 09:21:51 +01:00
|
|
|
return;
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.dsi.deassert_seq[0] = MIPI_SEQ_DEASSERT_RESET;
|
|
|
|
panel->vbt.dsi.deassert_seq[len] = MIPI_SEQ_ELEM_END;
|
drm/i915: Fix DSI panels with v1 MIPI sequences without a DEASSERT sequence v3
So far models of the Dell Venue 8 Pro, with a panel with MIPI panel
index = 3, one of which has been kindly provided to me by Jan Brummer,
where not working with the i915 driver, giving a black screen on the
first modeset.
The problem with at least these Dells is that their VBT defines a MIPI
ASSERT sequence, but not a DEASSERT sequence. Instead they DEASSERT the
reset in their INIT_OTP sequence, but the deassert must be done before
calling intel_dsi_device_ready(), so that is too late.
Simply doing the INIT_OTP sequence earlier is not enough to fix this,
because the INIT_OTP sequence also sends various MIPI packets to the
panel, which can only happen after calling intel_dsi_device_ready().
This commit fixes this by splitting the INIT_OTP sequence into everything
before the first DSI packet and everything else, including the first DSI
packet. The first part (everything before the first DSI packet) is then
used as deassert sequence.
Changed in v2:
-Split the init OTP sequence into a deassert reset and the actual init
OTP sequence, instead of calling it earlier and then having the first
mipi_exec_send_packet() call call intel_dsi_device_ready().
Changes in v3:
-Move the whole shebang to intel_bios.c
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=82880
References: https://bugs.freedesktop.org/show_bug.cgi?id=101205
Cc: Jan-Michael Brummer <jan.brummer@tabos.org>
Reported-by: Jan-Michael Brummer <jan.brummer@tabos.org>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Acked-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180214082151.25015-3-hdegoede@redhat.com
2018-02-14 09:21:51 +01:00
|
|
|
/* Use the copy for deassert */
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET] =
|
|
|
|
panel->vbt.dsi.deassert_seq;
|
drm/i915: Fix DSI panels with v1 MIPI sequences without a DEASSERT sequence v3
So far models of the Dell Venue 8 Pro, with a panel with MIPI panel
index = 3, one of which has been kindly provided to me by Jan Brummer,
where not working with the i915 driver, giving a black screen on the
first modeset.
The problem with at least these Dells is that their VBT defines a MIPI
ASSERT sequence, but not a DEASSERT sequence. Instead they DEASSERT the
reset in their INIT_OTP sequence, but the deassert must be done before
calling intel_dsi_device_ready(), so that is too late.
Simply doing the INIT_OTP sequence earlier is not enough to fix this,
because the INIT_OTP sequence also sends various MIPI packets to the
panel, which can only happen after calling intel_dsi_device_ready().
This commit fixes this by splitting the INIT_OTP sequence into everything
before the first DSI packet and everything else, including the first DSI
packet. The first part (everything before the first DSI packet) is then
used as deassert sequence.
Changed in v2:
-Split the init OTP sequence into a deassert reset and the actual init
OTP sequence, instead of calling it earlier and then having the first
mipi_exec_send_packet() call call intel_dsi_device_ready().
Changes in v3:
-Move the whole shebang to intel_bios.c
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=82880
References: https://bugs.freedesktop.org/show_bug.cgi?id=101205
Cc: Jan-Michael Brummer <jan.brummer@tabos.org>
Reported-by: Jan-Michael Brummer <jan.brummer@tabos.org>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Acked-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180214082151.25015-3-hdegoede@redhat.com
2018-02-14 09:21:51 +01:00
|
|
|
/* Replace the last byte of the fragment with init OTP seq byte */
|
|
|
|
init_otp[len - 1] = MIPI_SEQ_INIT_OTP;
|
|
|
|
/* And make MIPI_MIPI_SEQ_INIT_OTP point to it */
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP] = init_otp + len - 1;
|
drm/i915: Fix DSI panels with v1 MIPI sequences without a DEASSERT sequence v3
So far models of the Dell Venue 8 Pro, with a panel with MIPI panel
index = 3, one of which has been kindly provided to me by Jan Brummer,
where not working with the i915 driver, giving a black screen on the
first modeset.
The problem with at least these Dells is that their VBT defines a MIPI
ASSERT sequence, but not a DEASSERT sequence. Instead they DEASSERT the
reset in their INIT_OTP sequence, but the deassert must be done before
calling intel_dsi_device_ready(), so that is too late.
Simply doing the INIT_OTP sequence earlier is not enough to fix this,
because the INIT_OTP sequence also sends various MIPI packets to the
panel, which can only happen after calling intel_dsi_device_ready().
This commit fixes this by splitting the INIT_OTP sequence into everything
before the first DSI packet and everything else, including the first DSI
packet. The first part (everything before the first DSI packet) is then
used as deassert sequence.
Changed in v2:
-Split the init OTP sequence into a deassert reset and the actual init
OTP sequence, instead of calling it earlier and then having the first
mipi_exec_send_packet() call call intel_dsi_device_ready().
Changes in v3:
-Move the whole shebang to intel_bios.c
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=82880
References: https://bugs.freedesktop.org/show_bug.cgi?id=101205
Cc: Jan-Michael Brummer <jan.brummer@tabos.org>
Reported-by: Jan-Michael Brummer <jan.brummer@tabos.org>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Acked-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180214082151.25015-3-hdegoede@redhat.com
2018-02-14 09:21:51 +01:00
|
|
|
}
|
|
|
|
|
2024-03-05 10:36:59 +02:00
|
|
|
/*
|
|
|
|
* Some machines (eg. Lenovo 82TQ) appear to have broken
|
|
|
|
* VBT sequences:
|
|
|
|
* - INIT_OTP is not present at all
|
|
|
|
* - what should be in INIT_OTP is in DISPLAY_ON
|
|
|
|
* - what should be in DISPLAY_ON is in BACKLIGHT_ON
|
|
|
|
* (along with the actual backlight stuff)
|
|
|
|
*
|
|
|
|
* To make those work we simply swap DISPLAY_ON and INIT_OTP.
|
|
|
|
*
|
|
|
|
* TODO: Do we need to limit this to specific machines,
|
|
|
|
* or examine the contents of the sequences to
|
|
|
|
* avoid false positives?
|
|
|
|
*/
|
2024-08-09 17:27:06 +03:00
|
|
|
static void icl_fixup_mipi_sequences(struct intel_display *display,
|
2024-03-05 10:36:59 +02:00
|
|
|
struct intel_panel *panel)
|
|
|
|
{
|
|
|
|
if (!panel->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP] &&
|
|
|
|
panel->vbt.dsi.sequence[MIPI_SEQ_DISPLAY_ON]) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
|
|
|
"Broken VBT: Swapping INIT_OTP and DISPLAY_ON sequences\n");
|
2024-03-05 10:36:59 +02:00
|
|
|
|
|
|
|
swap(panel->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP],
|
|
|
|
panel->vbt.dsi.sequence[MIPI_SEQ_DISPLAY_ON]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
static void fixup_mipi_sequences(struct intel_display *display,
|
2024-03-05 10:36:59 +02:00
|
|
|
struct intel_panel *panel)
|
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
if (DISPLAY_VER(display) >= 11)
|
|
|
|
icl_fixup_mipi_sequences(display, panel);
|
2024-10-28 21:48:44 +02:00
|
|
|
else if (display->platform.valleyview)
|
2024-08-09 17:27:06 +03:00
|
|
|
vlv_fixup_mipi_sequences(display, panel);
|
2024-03-05 10:36:59 +02:00
|
|
|
}
|
|
|
|
|
2015-12-21 15:10:54 +02:00
|
|
|
static void
|
2024-08-09 17:27:06 +03:00
|
|
|
parse_mipi_sequence(struct intel_display *display,
|
2022-05-10 13:42:39 +03:00
|
|
|
struct intel_panel *panel)
|
2015-12-21 15:10:54 +02:00
|
|
|
{
|
2022-05-10 13:42:39 +03:00
|
|
|
int panel_type = panel->vbt.panel_type;
|
2015-12-21 15:10:54 +02:00
|
|
|
const struct bdb_mipi_sequence *sequence;
|
|
|
|
const u8 *seq_data;
|
2016-01-11 15:15:02 +02:00
|
|
|
u32 seq_size;
|
2015-12-21 15:10:54 +02:00
|
|
|
u8 *data;
|
2015-12-21 15:10:57 +02:00
|
|
|
int index = 0;
|
2015-12-21 15:10:54 +02:00
|
|
|
|
|
|
|
/* Only our generic panel driver uses the sequence block. */
|
2022-05-10 13:42:39 +03:00
|
|
|
if (panel->vbt.dsi.panel_id != MIPI_DSI_GENERIC_PANEL_ID)
|
2015-12-21 15:10:54 +02:00
|
|
|
return;
|
2014-04-14 11:00:34 +05:30
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
sequence = bdb_find_section(display, BDB_MIPI_SEQUENCE);
|
2014-04-14 11:00:34 +05:30
|
|
|
if (!sequence) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"No MIPI Sequence found, parsing complete\n");
|
2014-04-14 11:00:34 +05:30
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-09-17 16:42:07 +03:00
|
|
|
/* Fail gracefully for forward incompatible sequence block. */
|
2016-01-11 15:15:02 +02:00
|
|
|
if (sequence->version >= 4) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_err(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"Unable to parse MIPI Sequence Block v%u\n",
|
|
|
|
sequence->version);
|
2015-09-17 16:42:07 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-09-23 18:24:48 +03:00
|
|
|
drm_dbg_kms(display->drm, "Found MIPI sequence block v%u\n",
|
|
|
|
sequence->version);
|
2014-04-14 11:00:34 +05:30
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
seq_data = find_panel_sequence_block(display, sequence, panel_type, &seq_size);
|
2016-01-05 15:50:51 +02:00
|
|
|
if (!seq_data)
|
2014-04-14 11:00:34 +05:30
|
|
|
return;
|
|
|
|
|
2015-12-21 15:10:57 +02:00
|
|
|
data = kmemdup(seq_data, seq_size, GFP_KERNEL);
|
|
|
|
if (!data)
|
2014-04-14 11:00:34 +05:30
|
|
|
return;
|
|
|
|
|
2015-12-21 15:10:57 +02:00
|
|
|
/* Parse the sequences, store pointers to each sequence. */
|
|
|
|
for (;;) {
|
|
|
|
u8 seq_id = *(data + index);
|
|
|
|
if (seq_id == MIPI_SEQ_END)
|
|
|
|
break;
|
2014-04-14 11:00:34 +05:30
|
|
|
|
2015-12-21 15:10:57 +02:00
|
|
|
if (seq_id >= MIPI_SEQ_MAX) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_err(display->drm, "Unknown sequence %u\n",
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
seq_id);
|
2014-04-14 11:00:34 +05:30
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2016-09-19 15:02:29 +03:00
|
|
|
/* Log about presence of sequences we won't run. */
|
|
|
|
if (seq_id == MIPI_SEQ_TEAR_ON || seq_id == MIPI_SEQ_TEAR_OFF)
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"Unsupported sequence %u\n", seq_id);
|
2016-09-19 15:02:29 +03:00
|
|
|
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.dsi.sequence[seq_id] = data + index;
|
2014-04-14 11:00:34 +05:30
|
|
|
|
2016-01-11 15:15:02 +02:00
|
|
|
if (sequence->version >= 3)
|
2024-08-09 17:27:06 +03:00
|
|
|
index = goto_next_sequence_v3(display, data, index, seq_size);
|
2016-01-11 15:15:02 +02:00
|
|
|
else
|
2024-08-09 17:27:06 +03:00
|
|
|
index = goto_next_sequence(display, data, index, seq_size);
|
2015-12-21 15:10:57 +02:00
|
|
|
if (!index) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_err(display->drm, "Invalid sequence %u\n",
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
seq_id);
|
2014-04-14 11:00:34 +05:30
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-10 13:42:39 +03:00
|
|
|
panel->vbt.dsi.data = data;
|
|
|
|
panel->vbt.dsi.size = seq_size;
|
|
|
|
panel->vbt.dsi.seq_version = sequence->version;
|
2015-12-21 15:10:57 +02:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
fixup_mipi_sequences(display, panel);
|
drm/i915: Fix DSI panels with v1 MIPI sequences without a DEASSERT sequence v3
So far models of the Dell Venue 8 Pro, with a panel with MIPI panel
index = 3, one of which has been kindly provided to me by Jan Brummer,
where not working with the i915 driver, giving a black screen on the
first modeset.
The problem with at least these Dells is that their VBT defines a MIPI
ASSERT sequence, but not a DEASSERT sequence. Instead they DEASSERT the
reset in their INIT_OTP sequence, but the deassert must be done before
calling intel_dsi_device_ready(), so that is too late.
Simply doing the INIT_OTP sequence earlier is not enough to fix this,
because the INIT_OTP sequence also sends various MIPI packets to the
panel, which can only happen after calling intel_dsi_device_ready().
This commit fixes this by splitting the INIT_OTP sequence into everything
before the first DSI packet and everything else, including the first DSI
packet. The first part (everything before the first DSI packet) is then
used as deassert sequence.
Changed in v2:
-Split the init OTP sequence into a deassert reset and the actual init
OTP sequence, instead of calling it earlier and then having the first
mipi_exec_send_packet() call call intel_dsi_device_ready().
Changes in v3:
-Move the whole shebang to intel_bios.c
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=82880
References: https://bugs.freedesktop.org/show_bug.cgi?id=101205
Cc: Jan-Michael Brummer <jan.brummer@tabos.org>
Reported-by: Jan-Michael Brummer <jan.brummer@tabos.org>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Acked-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180214082151.25015-3-hdegoede@redhat.com
2018-02-14 09:21:51 +01:00
|
|
|
|
2024-09-23 18:24:48 +03:00
|
|
|
drm_dbg_kms(display->drm, "MIPI related VBT parsing complete\n");
|
2014-04-14 11:00:34 +05:30
|
|
|
return;
|
|
|
|
|
2015-12-21 15:10:57 +02:00
|
|
|
err:
|
|
|
|
kfree(data);
|
2022-05-10 13:42:39 +03:00
|
|
|
memset(panel->vbt.dsi.sequence, 0, sizeof(panel->vbt.dsi.sequence));
|
2013-08-27 15:12:25 +03:00
|
|
|
}
|
|
|
|
|
2019-12-10 12:50:46 +02:00
|
|
|
static void
|
2024-08-09 17:27:06 +03:00
|
|
|
parse_compression_parameters(struct intel_display *display)
|
2019-12-10 12:50:46 +02:00
|
|
|
{
|
|
|
|
const struct bdb_compression_parameters *params;
|
2021-03-17 18:36:47 +02:00
|
|
|
struct intel_bios_encoder_data *devdata;
|
2019-12-10 12:50:46 +02:00
|
|
|
u16 block_size;
|
|
|
|
int index;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (display->vbt.version < 198)
|
2019-12-10 12:50:46 +02:00
|
|
|
return;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
params = bdb_find_section(display, BDB_COMPRESSION_PARAMETERS);
|
2019-12-10 12:50:46 +02:00
|
|
|
if (params) {
|
|
|
|
/* Sanity checks */
|
|
|
|
if (params->entry_size != sizeof(params->data[0])) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"VBT: unsupported compression param entry size\n");
|
2019-12-10 12:50:46 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
block_size = get_blocksize(params);
|
|
|
|
if (block_size < sizeof(*params)) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"VBT: expected 16 compression param entries\n");
|
2019-12-10 12:50:46 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
list_for_each_entry(devdata, &display->vbt.display_devices, node) {
|
2023-02-08 03:55:00 +02:00
|
|
|
const struct child_device_config *child = &devdata->child;
|
2019-12-10 12:50:46 +02:00
|
|
|
|
|
|
|
if (!child->compression_enable)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!params) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"VBT: compression params not available\n");
|
2019-12-10 12:50:46 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (child->compression_method_cps) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"VBT: CPS compression not supported\n");
|
2019-12-10 12:50:46 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
index = child->compression_structure_index;
|
|
|
|
|
|
|
|
devdata->dsc = kmemdup(¶ms->data[index],
|
|
|
|
sizeof(*devdata->dsc), GFP_KERNEL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
static u8 translate_iboost(struct intel_display *display, u8 val)
|
2015-07-10 14:10:55 +03:00
|
|
|
{
|
|
|
|
static const u8 mapping[] = { 1, 3, 7 }; /* See VBT spec */
|
|
|
|
|
|
|
|
if (val >= ARRAY_SIZE(mapping)) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
2024-02-08 17:17:14 +02:00
|
|
|
"Unsupported I_boost value found in VBT (%d), display may not work properly\n", val);
|
2015-07-10 14:10:55 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return mapping[val];
|
|
|
|
}
|
|
|
|
|
2021-09-01 19:10:03 +03:00
|
|
|
static const u8 cnp_ddc_pin_map[] = {
|
|
|
|
[0] = 0, /* N/A */
|
2023-05-09 19:02:05 +03:00
|
|
|
[GMBUS_PIN_1_BXT] = DDC_BUS_DDI_B,
|
|
|
|
[GMBUS_PIN_2_BXT] = DDC_BUS_DDI_C,
|
|
|
|
[GMBUS_PIN_4_CNP] = DDC_BUS_DDI_D, /* sic */
|
|
|
|
[GMBUS_PIN_3_BXT] = DDC_BUS_DDI_F, /* sic */
|
2021-09-01 19:10:03 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
static const u8 icp_ddc_pin_map[] = {
|
2023-05-09 19:02:05 +03:00
|
|
|
[GMBUS_PIN_1_BXT] = ICL_DDC_BUS_DDI_A,
|
|
|
|
[GMBUS_PIN_2_BXT] = ICL_DDC_BUS_DDI_B,
|
|
|
|
[GMBUS_PIN_3_BXT] = TGL_DDC_BUS_DDI_C,
|
|
|
|
[GMBUS_PIN_9_TC1_ICP] = ICL_DDC_BUS_PORT_1,
|
|
|
|
[GMBUS_PIN_10_TC2_ICP] = ICL_DDC_BUS_PORT_2,
|
|
|
|
[GMBUS_PIN_11_TC3_ICP] = ICL_DDC_BUS_PORT_3,
|
|
|
|
[GMBUS_PIN_12_TC4_ICP] = ICL_DDC_BUS_PORT_4,
|
|
|
|
[GMBUS_PIN_13_TC5_TGP] = TGL_DDC_BUS_PORT_5,
|
|
|
|
[GMBUS_PIN_14_TC6_TGP] = TGL_DDC_BUS_PORT_6,
|
2021-09-01 19:10:03 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
static const u8 rkl_pch_tgp_ddc_pin_map[] = {
|
2023-05-09 19:02:05 +03:00
|
|
|
[GMBUS_PIN_1_BXT] = ICL_DDC_BUS_DDI_A,
|
|
|
|
[GMBUS_PIN_2_BXT] = ICL_DDC_BUS_DDI_B,
|
|
|
|
[GMBUS_PIN_9_TC1_ICP] = RKL_DDC_BUS_DDI_D,
|
|
|
|
[GMBUS_PIN_10_TC2_ICP] = RKL_DDC_BUS_DDI_E,
|
2021-09-01 19:10:03 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
static const u8 adls_ddc_pin_map[] = {
|
2023-05-09 19:02:05 +03:00
|
|
|
[GMBUS_PIN_1_BXT] = ICL_DDC_BUS_DDI_A,
|
|
|
|
[GMBUS_PIN_9_TC1_ICP] = ADLS_DDC_BUS_PORT_TC1,
|
|
|
|
[GMBUS_PIN_10_TC2_ICP] = ADLS_DDC_BUS_PORT_TC2,
|
|
|
|
[GMBUS_PIN_11_TC3_ICP] = ADLS_DDC_BUS_PORT_TC3,
|
|
|
|
[GMBUS_PIN_12_TC4_ICP] = ADLS_DDC_BUS_PORT_TC4,
|
2021-09-01 19:10:03 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
static const u8 gen9bc_tgp_ddc_pin_map[] = {
|
2023-05-09 19:02:05 +03:00
|
|
|
[GMBUS_PIN_2_BXT] = DDC_BUS_DDI_B,
|
|
|
|
[GMBUS_PIN_9_TC1_ICP] = DDC_BUS_DDI_C,
|
|
|
|
[GMBUS_PIN_10_TC2_ICP] = DDC_BUS_DDI_D,
|
2021-09-01 19:10:03 +03:00
|
|
|
};
|
|
|
|
|
2021-12-03 13:07:20 +05:30
|
|
|
static const u8 adlp_ddc_pin_map[] = {
|
2023-05-09 19:02:05 +03:00
|
|
|
[GMBUS_PIN_1_BXT] = ICL_DDC_BUS_DDI_A,
|
|
|
|
[GMBUS_PIN_2_BXT] = ICL_DDC_BUS_DDI_B,
|
|
|
|
[GMBUS_PIN_9_TC1_ICP] = ADLP_DDC_BUS_PORT_TC1,
|
|
|
|
[GMBUS_PIN_10_TC2_ICP] = ADLP_DDC_BUS_PORT_TC2,
|
|
|
|
[GMBUS_PIN_11_TC3_ICP] = ADLP_DDC_BUS_PORT_TC3,
|
|
|
|
[GMBUS_PIN_12_TC4_ICP] = ADLP_DDC_BUS_PORT_TC4,
|
2021-12-03 13:07:20 +05:30
|
|
|
};
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
static u8 map_ddc_pin(struct intel_display *display, u8 vbt_pin)
|
2021-09-01 19:10:03 +03:00
|
|
|
{
|
|
|
|
const u8 *ddc_pin_map;
|
2023-05-09 19:02:05 +03:00
|
|
|
int i, n_entries;
|
2021-09-01 19:10:03 +03:00
|
|
|
|
2025-04-17 12:10:36 +03:00
|
|
|
if (INTEL_PCH_TYPE(display) >= PCH_MTL || display->platform.alderlake_p) {
|
2021-12-03 13:07:20 +05:30
|
|
|
ddc_pin_map = adlp_ddc_pin_map;
|
|
|
|
n_entries = ARRAY_SIZE(adlp_ddc_pin_map);
|
2024-10-28 21:48:44 +02:00
|
|
|
} else if (display->platform.alderlake_s) {
|
2021-09-01 19:10:03 +03:00
|
|
|
ddc_pin_map = adls_ddc_pin_map;
|
|
|
|
n_entries = ARRAY_SIZE(adls_ddc_pin_map);
|
2025-04-17 12:10:36 +03:00
|
|
|
} else if (INTEL_PCH_TYPE(display) >= PCH_DG1) {
|
2024-04-30 10:28:45 -07:00
|
|
|
return vbt_pin;
|
2025-04-17 12:10:36 +03:00
|
|
|
} else if (display->platform.rocketlake && INTEL_PCH_TYPE(display) == PCH_TGP) {
|
2021-09-01 19:10:03 +03:00
|
|
|
ddc_pin_map = rkl_pch_tgp_ddc_pin_map;
|
|
|
|
n_entries = ARRAY_SIZE(rkl_pch_tgp_ddc_pin_map);
|
2025-04-17 12:10:36 +03:00
|
|
|
} else if (HAS_PCH_TGP(display) && DISPLAY_VER(display) == 9) {
|
2021-09-01 19:10:03 +03:00
|
|
|
ddc_pin_map = gen9bc_tgp_ddc_pin_map;
|
|
|
|
n_entries = ARRAY_SIZE(gen9bc_tgp_ddc_pin_map);
|
2025-04-17 12:10:36 +03:00
|
|
|
} else if (INTEL_PCH_TYPE(display) >= PCH_ICP) {
|
2021-09-01 19:10:03 +03:00
|
|
|
ddc_pin_map = icp_ddc_pin_map;
|
|
|
|
n_entries = ARRAY_SIZE(icp_ddc_pin_map);
|
2025-04-17 12:10:36 +03:00
|
|
|
} else if (HAS_PCH_CNP(display)) {
|
2021-09-01 19:10:03 +03:00
|
|
|
ddc_pin_map = cnp_ddc_pin_map;
|
|
|
|
n_entries = ARRAY_SIZE(cnp_ddc_pin_map);
|
|
|
|
} else {
|
|
|
|
/* Assuming direct map */
|
|
|
|
return vbt_pin;
|
|
|
|
}
|
|
|
|
|
2023-05-09 19:02:05 +03:00
|
|
|
for (i = 0; i < n_entries; i++) {
|
|
|
|
if (ddc_pin_map[i] == vbt_pin)
|
|
|
|
return i;
|
|
|
|
}
|
2021-09-01 19:10:03 +03:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
2021-09-01 19:10:03 +03:00
|
|
|
"Ignoring alternate pin: VBT claims DDC pin %d, which is not valid for this platform\n",
|
|
|
|
vbt_pin);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-10-25 17:21:47 +03:00
|
|
|
static u8 dvo_port_type(u8 dvo_port)
|
|
|
|
{
|
|
|
|
switch (dvo_port) {
|
|
|
|
case DVO_PORT_HDMIA:
|
|
|
|
case DVO_PORT_HDMIB:
|
|
|
|
case DVO_PORT_HDMIC:
|
|
|
|
case DVO_PORT_HDMID:
|
|
|
|
case DVO_PORT_HDMIE:
|
|
|
|
case DVO_PORT_HDMIF:
|
|
|
|
case DVO_PORT_HDMIG:
|
|
|
|
case DVO_PORT_HDMIH:
|
|
|
|
case DVO_PORT_HDMII:
|
|
|
|
return DVO_PORT_HDMIA;
|
|
|
|
case DVO_PORT_DPA:
|
|
|
|
case DVO_PORT_DPB:
|
|
|
|
case DVO_PORT_DPC:
|
|
|
|
case DVO_PORT_DPD:
|
|
|
|
case DVO_PORT_DPE:
|
|
|
|
case DVO_PORT_DPF:
|
|
|
|
case DVO_PORT_DPG:
|
|
|
|
case DVO_PORT_DPH:
|
|
|
|
case DVO_PORT_DPI:
|
|
|
|
return DVO_PORT_DPA;
|
|
|
|
case DVO_PORT_MIPIA:
|
|
|
|
case DVO_PORT_MIPIB:
|
|
|
|
case DVO_PORT_MIPIC:
|
|
|
|
case DVO_PORT_MIPID:
|
|
|
|
return DVO_PORT_MIPIA;
|
|
|
|
default:
|
|
|
|
return dvo_port;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-03 14:15:20 -07:00
|
|
|
static enum port __dvo_port_to_port(int n_ports, int n_dvo,
|
|
|
|
const int port_mapping[][3], u8 dvo_port)
|
2013-09-12 17:06:24 -03:00
|
|
|
{
|
2019-03-22 14:10:08 +02:00
|
|
|
enum port port;
|
|
|
|
int i;
|
2013-09-12 17:06:24 -03:00
|
|
|
|
2020-06-03 14:15:20 -07:00
|
|
|
for (port = PORT_A; port < n_ports; port++) {
|
|
|
|
for (i = 0; i < n_dvo; i++) {
|
|
|
|
if (port_mapping[port][i] == -1)
|
2013-09-12 17:06:24 -03:00
|
|
|
break;
|
|
|
|
|
2020-06-03 14:15:20 -07:00
|
|
|
if (dvo_port == port_mapping[port][i])
|
2019-03-22 14:10:08 +02:00
|
|
|
return port;
|
2013-09-12 17:06:24 -03:00
|
|
|
}
|
|
|
|
}
|
2019-03-22 14:10:08 +02:00
|
|
|
|
|
|
|
return PORT_NONE;
|
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
static enum port dvo_port_to_port(struct intel_display *display,
|
2020-06-03 14:15:20 -07:00
|
|
|
u8 dvo_port)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Each DDI port can have more than one value on the "DVO Port" field,
|
|
|
|
* so look for all the possible values for each port.
|
|
|
|
*/
|
|
|
|
static const int port_mapping[][3] = {
|
|
|
|
[PORT_A] = { DVO_PORT_HDMIA, DVO_PORT_DPA, -1 },
|
|
|
|
[PORT_B] = { DVO_PORT_HDMIB, DVO_PORT_DPB, -1 },
|
|
|
|
[PORT_C] = { DVO_PORT_HDMIC, DVO_PORT_DPC, -1 },
|
|
|
|
[PORT_D] = { DVO_PORT_HDMID, DVO_PORT_DPD, -1 },
|
2020-06-05 20:18:03 -07:00
|
|
|
[PORT_E] = { DVO_PORT_HDMIE, DVO_PORT_DPE, DVO_PORT_CRT },
|
2020-06-03 14:15:20 -07:00
|
|
|
[PORT_F] = { DVO_PORT_HDMIF, DVO_PORT_DPF, -1 },
|
|
|
|
[PORT_G] = { DVO_PORT_HDMIG, DVO_PORT_DPG, -1 },
|
2020-07-01 00:55:53 +03:00
|
|
|
[PORT_H] = { DVO_PORT_HDMIH, DVO_PORT_DPH, -1 },
|
|
|
|
[PORT_I] = { DVO_PORT_HDMII, DVO_PORT_DPI, -1 },
|
2020-06-03 14:15:20 -07:00
|
|
|
};
|
|
|
|
/*
|
2020-10-28 23:33:06 +02:00
|
|
|
* RKL VBT uses PHY based mapping. Combo PHYs A,B,C,D
|
|
|
|
* map to DDI A,B,TC1,TC2 respectively.
|
2020-06-03 14:15:20 -07:00
|
|
|
*/
|
|
|
|
static const int rkl_port_mapping[][3] = {
|
|
|
|
[PORT_A] = { DVO_PORT_HDMIA, DVO_PORT_DPA, -1 },
|
|
|
|
[PORT_B] = { DVO_PORT_HDMIB, DVO_PORT_DPB, -1 },
|
|
|
|
[PORT_C] = { -1 },
|
2020-10-28 23:33:06 +02:00
|
|
|
[PORT_TC1] = { DVO_PORT_HDMIC, DVO_PORT_DPC, -1 },
|
|
|
|
[PORT_TC2] = { DVO_PORT_HDMID, DVO_PORT_DPD, -1 },
|
2020-06-03 14:15:20 -07:00
|
|
|
};
|
2021-01-25 06:07:52 -08:00
|
|
|
/*
|
|
|
|
* Alderlake S ports used in the driver are PORT_A, PORT_D, PORT_E,
|
|
|
|
* PORT_F and PORT_G, we need to map that to correct VBT sections.
|
|
|
|
*/
|
|
|
|
static const int adls_port_mapping[][3] = {
|
|
|
|
[PORT_A] = { DVO_PORT_HDMIA, DVO_PORT_DPA, -1 },
|
|
|
|
[PORT_B] = { -1 },
|
|
|
|
[PORT_C] = { -1 },
|
|
|
|
[PORT_TC1] = { DVO_PORT_HDMIB, DVO_PORT_DPB, -1 },
|
|
|
|
[PORT_TC2] = { DVO_PORT_HDMIC, DVO_PORT_DPC, -1 },
|
|
|
|
[PORT_TC3] = { DVO_PORT_HDMID, DVO_PORT_DPD, -1 },
|
|
|
|
[PORT_TC4] = { DVO_PORT_HDMIE, DVO_PORT_DPE, -1 },
|
|
|
|
};
|
2021-05-14 08:36:58 -07:00
|
|
|
static const int xelpd_port_mapping[][3] = {
|
|
|
|
[PORT_A] = { DVO_PORT_HDMIA, DVO_PORT_DPA, -1 },
|
|
|
|
[PORT_B] = { DVO_PORT_HDMIB, DVO_PORT_DPB, -1 },
|
|
|
|
[PORT_C] = { DVO_PORT_HDMIC, DVO_PORT_DPC, -1 },
|
|
|
|
[PORT_D_XELPD] = { DVO_PORT_HDMID, DVO_PORT_DPD, -1 },
|
|
|
|
[PORT_E_XELPD] = { DVO_PORT_HDMIE, DVO_PORT_DPE, -1 },
|
|
|
|
[PORT_TC1] = { DVO_PORT_HDMIF, DVO_PORT_DPF, -1 },
|
|
|
|
[PORT_TC2] = { DVO_PORT_HDMIG, DVO_PORT_DPG, -1 },
|
|
|
|
[PORT_TC3] = { DVO_PORT_HDMIH, DVO_PORT_DPH, -1 },
|
|
|
|
[PORT_TC4] = { DVO_PORT_HDMII, DVO_PORT_DPI, -1 },
|
|
|
|
};
|
2020-06-03 14:15:20 -07:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (DISPLAY_VER(display) >= 13)
|
2021-05-14 08:36:58 -07:00
|
|
|
return __dvo_port_to_port(ARRAY_SIZE(xelpd_port_mapping),
|
|
|
|
ARRAY_SIZE(xelpd_port_mapping[0]),
|
|
|
|
xelpd_port_mapping,
|
|
|
|
dvo_port);
|
2024-10-28 21:48:44 +02:00
|
|
|
else if (display->platform.alderlake_s)
|
2021-01-25 06:07:52 -08:00
|
|
|
return __dvo_port_to_port(ARRAY_SIZE(adls_port_mapping),
|
|
|
|
ARRAY_SIZE(adls_port_mapping[0]),
|
|
|
|
adls_port_mapping,
|
|
|
|
dvo_port);
|
2024-10-28 21:48:44 +02:00
|
|
|
else if (display->platform.dg1 || display->platform.rocketlake)
|
2020-06-03 14:15:20 -07:00
|
|
|
return __dvo_port_to_port(ARRAY_SIZE(rkl_port_mapping),
|
|
|
|
ARRAY_SIZE(rkl_port_mapping[0]),
|
|
|
|
rkl_port_mapping,
|
|
|
|
dvo_port);
|
|
|
|
else
|
|
|
|
return __dvo_port_to_port(ARRAY_SIZE(port_mapping),
|
|
|
|
ARRAY_SIZE(port_mapping[0]),
|
|
|
|
port_mapping,
|
|
|
|
dvo_port);
|
|
|
|
}
|
|
|
|
|
2023-02-07 08:43:35 +02:00
|
|
|
static enum port
|
2024-08-09 17:27:06 +03:00
|
|
|
dsi_dvo_port_to_port(struct intel_display *display, u8 dvo_port)
|
2023-02-07 08:43:35 +02:00
|
|
|
{
|
|
|
|
switch (dvo_port) {
|
|
|
|
case DVO_PORT_MIPIA:
|
|
|
|
return PORT_A;
|
|
|
|
case DVO_PORT_MIPIC:
|
2024-08-09 17:27:06 +03:00
|
|
|
if (DISPLAY_VER(display) >= 11)
|
2023-02-07 08:43:35 +02:00
|
|
|
return PORT_B;
|
|
|
|
else
|
|
|
|
return PORT_C;
|
|
|
|
default:
|
|
|
|
return PORT_NONE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-30 18:58:46 +03:00
|
|
|
enum port intel_bios_encoder_port(const struct intel_bios_encoder_data *devdata)
|
2023-06-30 18:58:45 +03:00
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
struct intel_display *display = devdata->display;
|
2023-06-30 18:58:45 +03:00
|
|
|
const struct child_device_config *child = &devdata->child;
|
|
|
|
enum port port;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
port = dvo_port_to_port(display, child->dvo_port);
|
|
|
|
if (port == PORT_NONE && DISPLAY_VER(display) >= 11)
|
|
|
|
port = dsi_dvo_port_to_port(display, child->dvo_port);
|
2023-06-30 18:58:45 +03:00
|
|
|
|
|
|
|
return port;
|
|
|
|
}
|
|
|
|
|
2021-02-18 13:23:33 +08:00
|
|
|
static int parse_bdb_230_dp_max_link_rate(const int vbt_max_link_rate)
|
|
|
|
{
|
|
|
|
switch (vbt_max_link_rate) {
|
|
|
|
default:
|
|
|
|
case BDB_230_VBT_DP_MAX_LINK_RATE_DEF:
|
|
|
|
return 0;
|
|
|
|
case BDB_230_VBT_DP_MAX_LINK_RATE_UHBR20:
|
|
|
|
return 2000000;
|
|
|
|
case BDB_230_VBT_DP_MAX_LINK_RATE_UHBR13P5:
|
|
|
|
return 1350000;
|
|
|
|
case BDB_230_VBT_DP_MAX_LINK_RATE_UHBR10:
|
|
|
|
return 1000000;
|
|
|
|
case BDB_230_VBT_DP_MAX_LINK_RATE_HBR3:
|
|
|
|
return 810000;
|
|
|
|
case BDB_230_VBT_DP_MAX_LINK_RATE_HBR2:
|
|
|
|
return 540000;
|
|
|
|
case BDB_230_VBT_DP_MAX_LINK_RATE_HBR:
|
|
|
|
return 270000;
|
|
|
|
case BDB_230_VBT_DP_MAX_LINK_RATE_LBR:
|
|
|
|
return 162000;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int parse_bdb_216_dp_max_link_rate(const int vbt_max_link_rate)
|
|
|
|
{
|
|
|
|
switch (vbt_max_link_rate) {
|
|
|
|
default:
|
|
|
|
case BDB_216_VBT_DP_MAX_LINK_RATE_HBR3:
|
|
|
|
return 810000;
|
|
|
|
case BDB_216_VBT_DP_MAX_LINK_RATE_HBR2:
|
|
|
|
return 540000;
|
|
|
|
case BDB_216_VBT_DP_MAX_LINK_RATE_HBR:
|
|
|
|
return 270000;
|
|
|
|
case BDB_216_VBT_DP_MAX_LINK_RATE_LBR:
|
|
|
|
return 162000;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-16 02:04:25 +02:00
|
|
|
int intel_bios_dp_max_link_rate(const struct intel_bios_encoder_data *devdata)
|
2021-09-01 19:10:01 +03:00
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
if (!devdata || devdata->display->vbt.version < 216)
|
2021-09-01 19:10:01 +03:00
|
|
|
return 0;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (devdata->display->vbt.version >= 230)
|
2021-09-01 19:10:01 +03:00
|
|
|
return parse_bdb_230_dp_max_link_rate(devdata->child.dp_max_link_rate);
|
|
|
|
else
|
|
|
|
return parse_bdb_216_dp_max_link_rate(devdata->child.dp_max_link_rate);
|
|
|
|
}
|
|
|
|
|
2023-02-16 02:04:25 +02:00
|
|
|
int intel_bios_dp_max_lane_count(const struct intel_bios_encoder_data *devdata)
|
2022-07-15 23:20:44 +03:00
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
if (!devdata || devdata->display->vbt.version < 244)
|
2022-07-15 23:20:44 +03:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
return devdata->child.dp_max_lane_count + 1;
|
|
|
|
}
|
|
|
|
|
2021-03-17 18:36:49 +02:00
|
|
|
static void sanitize_device_type(struct intel_bios_encoder_data *devdata,
|
|
|
|
enum port port)
|
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
struct intel_display *display = devdata->display;
|
2021-03-17 18:36:49 +02:00
|
|
|
bool is_hdmi;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (port != PORT_A || DISPLAY_VER(display) >= 12)
|
2021-03-17 18:36:49 +02:00
|
|
|
return;
|
|
|
|
|
2022-06-10 17:10:25 +03:00
|
|
|
if (!intel_bios_encoder_supports_dvi(devdata))
|
2021-03-17 18:36:49 +02:00
|
|
|
return;
|
|
|
|
|
2022-06-10 17:10:25 +03:00
|
|
|
is_hdmi = intel_bios_encoder_supports_hdmi(devdata);
|
2021-03-17 18:36:49 +02:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm, "VBT claims port A supports DVI%s, ignoring\n",
|
2021-03-17 18:36:49 +02:00
|
|
|
is_hdmi ? "/HDMI" : "");
|
|
|
|
|
|
|
|
devdata->child.device_type &= ~DEVICE_TYPE_TMDS_DVI_SIGNALING;
|
|
|
|
devdata->child.device_type |= DEVICE_TYPE_NOT_HDMI_OUTPUT;
|
|
|
|
}
|
|
|
|
|
2023-10-13 17:02:14 +03:00
|
|
|
static void sanitize_hdmi_level_shift(struct intel_bios_encoder_data *devdata,
|
|
|
|
enum port port)
|
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
struct intel_display *display = devdata->display;
|
2023-10-13 17:02:14 +03:00
|
|
|
|
|
|
|
if (!intel_bios_encoder_supports_dvi(devdata))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Some BDW machines (eg. HP Pavilion 15-ab) shipped
|
|
|
|
* with a HSW VBT where the level shifter value goes
|
|
|
|
* up to 11, whereas the BDW max is 9.
|
|
|
|
*/
|
2024-10-28 21:48:44 +02:00
|
|
|
if (display->platform.broadwell && devdata->child.hdmi_level_shifter_value > 9) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
|
|
|
"Bogus port %c VBT HDMI level shift %d, adjusting to %d\n",
|
2023-10-13 17:02:14 +03:00
|
|
|
port_name(port), devdata->child.hdmi_level_shifter_value, 9);
|
|
|
|
|
|
|
|
devdata->child.hdmi_level_shifter_value = 9;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-17 18:36:49 +02:00
|
|
|
static bool
|
|
|
|
intel_bios_encoder_supports_crt(const struct intel_bios_encoder_data *devdata)
|
|
|
|
{
|
|
|
|
return devdata->child.device_type & DEVICE_TYPE_ANALOG_OUTPUT;
|
|
|
|
}
|
|
|
|
|
2021-03-17 18:36:51 +02:00
|
|
|
bool
|
2021-03-17 18:36:49 +02:00
|
|
|
intel_bios_encoder_supports_dvi(const struct intel_bios_encoder_data *devdata)
|
|
|
|
{
|
|
|
|
return devdata->child.device_type & DEVICE_TYPE_TMDS_DVI_SIGNALING;
|
|
|
|
}
|
|
|
|
|
2021-03-17 18:36:51 +02:00
|
|
|
bool
|
2021-03-17 18:36:49 +02:00
|
|
|
intel_bios_encoder_supports_hdmi(const struct intel_bios_encoder_data *devdata)
|
|
|
|
{
|
|
|
|
return intel_bios_encoder_supports_dvi(devdata) &&
|
|
|
|
(devdata->child.device_type & DEVICE_TYPE_NOT_HDMI_OUTPUT) == 0;
|
|
|
|
}
|
|
|
|
|
2021-03-17 18:36:51 +02:00
|
|
|
bool
|
2021-03-17 18:36:49 +02:00
|
|
|
intel_bios_encoder_supports_dp(const struct intel_bios_encoder_data *devdata)
|
|
|
|
{
|
|
|
|
return devdata->child.device_type & DEVICE_TYPE_DISPLAYPORT_OUTPUT;
|
|
|
|
}
|
|
|
|
|
2023-02-08 03:55:08 +02:00
|
|
|
bool
|
2021-03-17 18:36:49 +02:00
|
|
|
intel_bios_encoder_supports_edp(const struct intel_bios_encoder_data *devdata)
|
|
|
|
{
|
|
|
|
return intel_bios_encoder_supports_dp(devdata) &&
|
|
|
|
devdata->child.device_type & DEVICE_TYPE_INTERNAL_CONNECTOR;
|
|
|
|
}
|
|
|
|
|
2023-06-30 18:58:46 +03:00
|
|
|
bool
|
2023-02-07 08:43:36 +02:00
|
|
|
intel_bios_encoder_supports_dsi(const struct intel_bios_encoder_data *devdata)
|
|
|
|
{
|
|
|
|
return devdata->child.device_type & DEVICE_TYPE_MIPI_OUTPUT;
|
|
|
|
}
|
|
|
|
|
2023-02-08 03:55:01 +02:00
|
|
|
bool
|
|
|
|
intel_bios_encoder_is_lspcon(const struct intel_bios_encoder_data *devdata)
|
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
return devdata && HAS_LSPCON(devdata->display) && devdata->child.lspcon;
|
2023-02-08 03:55:01 +02:00
|
|
|
}
|
|
|
|
|
2023-02-16 02:04:25 +02:00
|
|
|
/* This is an index in the HDMI/DVI DDI buffer translation table, or -1 */
|
|
|
|
int intel_bios_hdmi_level_shift(const struct intel_bios_encoder_data *devdata)
|
2021-09-01 19:09:59 +03:00
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
if (!devdata || devdata->display->vbt.version < 158 ||
|
|
|
|
DISPLAY_VER(devdata->display) >= 14)
|
2021-09-01 19:09:59 +03:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
return devdata->child.hdmi_level_shifter_value;
|
|
|
|
}
|
|
|
|
|
2023-02-16 02:04:25 +02:00
|
|
|
int intel_bios_hdmi_max_tmds_clock(const struct intel_bios_encoder_data *devdata)
|
2021-09-01 19:10:00 +03:00
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
if (!devdata || devdata->display->vbt.version < 204)
|
2021-09-01 19:10:00 +03:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
switch (devdata->child.hdmi_max_data_rate) {
|
|
|
|
default:
|
|
|
|
MISSING_CASE(devdata->child.hdmi_max_data_rate);
|
|
|
|
fallthrough;
|
|
|
|
case HDMI_MAX_DATA_RATE_PLATFORM:
|
|
|
|
return 0;
|
2022-03-03 16:38:02 +08:00
|
|
|
case HDMI_MAX_DATA_RATE_594:
|
|
|
|
return 594000;
|
|
|
|
case HDMI_MAX_DATA_RATE_340:
|
|
|
|
return 340000;
|
|
|
|
case HDMI_MAX_DATA_RATE_300:
|
|
|
|
return 300000;
|
2021-09-01 19:10:00 +03:00
|
|
|
case HDMI_MAX_DATA_RATE_297:
|
|
|
|
return 297000;
|
|
|
|
case HDMI_MAX_DATA_RATE_165:
|
|
|
|
return 165000;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
static bool is_port_valid(struct intel_display *display, enum port port)
|
2021-04-30 15:38:08 -07:00
|
|
|
{
|
|
|
|
/*
|
2021-07-28 14:59:22 -07:00
|
|
|
* On some ICL SKUs port F is not present, but broken VBTs mark
|
2021-04-30 15:38:08 -07:00
|
|
|
* the port as present. Only try to initialize port F for the
|
|
|
|
* SKUs that may actually have it.
|
|
|
|
*/
|
2024-10-28 21:48:44 +02:00
|
|
|
if (port == PORT_F && display->platform.icelake)
|
|
|
|
return display->platform.icelake_port_f;
|
2021-04-30 15:38:08 -07:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-06-30 18:58:46 +03:00
|
|
|
static void print_ddi_port(const struct intel_bios_encoder_data *devdata)
|
2019-03-22 14:10:08 +02:00
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
struct intel_display *display = devdata->display;
|
2019-12-10 12:50:45 +02:00
|
|
|
const struct child_device_config *child = &devdata->child;
|
2023-02-07 08:43:36 +02:00
|
|
|
bool is_dvi, is_hdmi, is_dp, is_edp, is_dsi, is_crt, supports_typec_usb, supports_tbt;
|
2021-09-01 19:10:01 +03:00
|
|
|
int dp_boost_level, dp_max_link_rate, hdmi_boost_level, hdmi_level_shift, max_tmds_clock;
|
2023-06-30 18:58:46 +03:00
|
|
|
enum port port;
|
|
|
|
|
|
|
|
port = intel_bios_encoder_port(devdata);
|
|
|
|
if (port == PORT_NONE)
|
|
|
|
return;
|
2013-09-12 17:10:11 -03:00
|
|
|
|
2021-03-17 18:36:49 +02:00
|
|
|
is_dvi = intel_bios_encoder_supports_dvi(devdata);
|
|
|
|
is_dp = intel_bios_encoder_supports_dp(devdata);
|
|
|
|
is_crt = intel_bios_encoder_supports_crt(devdata);
|
|
|
|
is_hdmi = intel_bios_encoder_supports_hdmi(devdata);
|
|
|
|
is_edp = intel_bios_encoder_supports_edp(devdata);
|
2023-02-07 08:43:36 +02:00
|
|
|
is_dsi = intel_bios_encoder_supports_dsi(devdata);
|
2017-09-21 17:19:20 +03:00
|
|
|
|
2021-03-17 18:36:52 +02:00
|
|
|
supports_typec_usb = intel_bios_encoder_supports_typec_usb(devdata);
|
|
|
|
supports_tbt = intel_bios_encoder_supports_tbt(devdata);
|
2018-12-14 20:27:01 +02:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
2023-05-09 19:02:06 +03:00
|
|
|
"Port %c VBT info: CRT:%d DVI:%d HDMI:%d DP:%d eDP:%d DSI:%d DP++:%d LSPCON:%d USB-Type-C:%d TBT:%d DSC:%d\n",
|
2023-02-07 08:43:36 +02:00
|
|
|
port_name(port), is_crt, is_dvi, is_hdmi, is_dp, is_edp, is_dsi,
|
2023-05-09 19:02:06 +03:00
|
|
|
intel_bios_encoder_supports_dp_dual_mode(devdata),
|
2023-02-08 03:55:01 +02:00
|
|
|
intel_bios_encoder_is_lspcon(devdata),
|
2021-03-17 18:36:52 +02:00
|
|
|
supports_typec_usb, supports_tbt,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
devdata->dsc != NULL);
|
2013-09-12 17:10:11 -03:00
|
|
|
|
2023-02-16 02:04:25 +02:00
|
|
|
hdmi_level_shift = intel_bios_hdmi_level_shift(devdata);
|
2021-09-01 19:09:59 +03:00
|
|
|
if (hdmi_level_shift >= 0) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
2021-01-27 10:45:34 +02:00
|
|
|
"Port %c VBT HDMI level shift: %d\n",
|
2021-09-01 19:09:59 +03:00
|
|
|
port_name(port), hdmi_level_shift);
|
2013-09-12 17:06:24 -03:00
|
|
|
}
|
2015-07-10 14:10:55 +03:00
|
|
|
|
2023-02-16 02:04:25 +02:00
|
|
|
max_tmds_clock = intel_bios_hdmi_max_tmds_clock(devdata);
|
2021-09-01 19:10:00 +03:00
|
|
|
if (max_tmds_clock)
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
2021-09-01 19:10:00 +03:00
|
|
|
"Port %c VBT HDMI max TMDS clock: %d kHz\n",
|
|
|
|
port_name(port), max_tmds_clock);
|
2017-10-30 16:57:02 +02:00
|
|
|
|
2021-03-17 18:36:53 +02:00
|
|
|
/* I_boost config for SKL and above */
|
2023-02-16 02:04:25 +02:00
|
|
|
dp_boost_level = intel_bios_dp_boost_level(devdata);
|
2021-03-17 18:36:53 +02:00
|
|
|
if (dp_boost_level)
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
2021-01-27 10:45:34 +02:00
|
|
|
"Port %c VBT (e)DP boost level: %d\n",
|
2021-03-17 18:36:53 +02:00
|
|
|
port_name(port), dp_boost_level);
|
|
|
|
|
2023-02-16 02:04:25 +02:00
|
|
|
hdmi_boost_level = intel_bios_hdmi_boost_level(devdata);
|
2021-03-17 18:36:53 +02:00
|
|
|
if (hdmi_boost_level)
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
2021-01-27 10:45:34 +02:00
|
|
|
"Port %c VBT HDMI boost level: %d\n",
|
2021-03-17 18:36:53 +02:00
|
|
|
port_name(port), hdmi_boost_level);
|
2018-02-01 13:03:43 +02:00
|
|
|
|
2023-02-16 02:04:25 +02:00
|
|
|
dp_max_link_rate = intel_bios_dp_max_link_rate(devdata);
|
2021-09-01 19:10:01 +03:00
|
|
|
if (dp_max_link_rate)
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
2021-01-27 10:45:34 +02:00
|
|
|
"Port %c VBT DP max link rate: %d\n",
|
2021-09-01 19:10:01 +03:00
|
|
|
port_name(port), dp_max_link_rate);
|
2022-09-16 23:41:32 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* FIXME need to implement support for VBT
|
|
|
|
* vswing/preemph tables should this ever trigger.
|
|
|
|
*/
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_WARN(display->drm, child->use_vbt_vswing,
|
2022-09-16 23:41:32 +03:00
|
|
|
"Port %c asks to use VBT vswing/preemph tables\n",
|
|
|
|
port_name(port));
|
2022-06-10 17:10:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void parse_ddi_port(struct intel_bios_encoder_data *devdata)
|
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
struct intel_display *display = devdata->display;
|
2022-06-10 17:10:27 +03:00
|
|
|
enum port port;
|
|
|
|
|
2023-06-30 18:58:45 +03:00
|
|
|
port = intel_bios_encoder_port(devdata);
|
2022-06-10 17:10:27 +03:00
|
|
|
if (port == PORT_NONE)
|
|
|
|
return;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (!is_port_valid(display, port)) {
|
|
|
|
drm_dbg_kms(display->drm,
|
2022-06-10 17:10:27 +03:00
|
|
|
"VBT reports port %c as supported, but that can't be true: skipping\n",
|
|
|
|
port_name(port));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sanitize_device_type(devdata, port);
|
2023-10-13 17:02:14 +03:00
|
|
|
sanitize_hdmi_level_shift(devdata, port);
|
2013-09-12 17:06:24 -03:00
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
static bool has_ddi_port_info(struct intel_display *display)
|
2021-12-17 17:53:58 +02:00
|
|
|
{
|
2024-10-28 21:48:44 +02:00
|
|
|
return DISPLAY_VER(display) >= 5 || display->platform.g4x;
|
2021-12-17 17:53:58 +02:00
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
static void parse_ddi_ports(struct intel_display *display)
|
2013-09-12 17:06:24 -03:00
|
|
|
{
|
2021-03-17 18:36:47 +02:00
|
|
|
struct intel_bios_encoder_data *devdata;
|
2013-09-12 17:06:24 -03:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (!has_ddi_port_info(display))
|
2013-09-12 17:06:24 -03:00
|
|
|
return;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
list_for_each_entry(devdata, &display->vbt.display_devices, node)
|
2022-06-10 17:10:26 +03:00
|
|
|
parse_ddi_port(devdata);
|
2022-06-21 15:37:32 +03:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
list_for_each_entry(devdata, &display->vbt.display_devices, node)
|
2023-06-30 18:58:46 +03:00
|
|
|
print_ddi_port(devdata);
|
2013-09-12 17:06:24 -03:00
|
|
|
}
|
|
|
|
|
2024-02-26 19:58:54 +02:00
|
|
|
static int child_device_expected_size(u16 version)
|
|
|
|
{
|
|
|
|
BUILD_BUG_ON(sizeof(struct child_device_config) < 40);
|
|
|
|
|
|
|
|
if (version > 256)
|
|
|
|
return -ENOENT;
|
|
|
|
else if (version >= 256)
|
|
|
|
return 40;
|
|
|
|
else if (version >= 216)
|
|
|
|
return 39;
|
|
|
|
else if (version >= 196)
|
|
|
|
return 38;
|
|
|
|
else if (version >= 195)
|
|
|
|
return 37;
|
|
|
|
else if (version >= 111)
|
|
|
|
return LEGACY_CHILD_DEVICE_CONFIG_SIZE;
|
|
|
|
else if (version >= 106)
|
|
|
|
return 27;
|
|
|
|
else
|
|
|
|
return 22;
|
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
static bool child_device_size_valid(struct intel_display *display, int size)
|
2024-02-26 19:58:53 +02:00
|
|
|
{
|
|
|
|
int expected_size;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
expected_size = child_device_expected_size(display->vbt.version);
|
2024-02-26 19:58:54 +02:00
|
|
|
if (expected_size < 0) {
|
2024-02-26 19:58:53 +02:00
|
|
|
expected_size = sizeof(struct child_device_config);
|
2024-09-23 18:24:48 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
|
|
|
"Expected child device config size for VBT version %u not known; assuming %d\n",
|
|
|
|
display->vbt.version, expected_size);
|
2024-02-26 19:58:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Flag an error for unexpected size, but continue anyway. */
|
|
|
|
if (size != expected_size)
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_err(display->drm,
|
2024-02-26 19:58:53 +02:00
|
|
|
"Unexpected child device config size %d (expected %d for VBT version %u)\n",
|
2024-08-09 17:27:06 +03:00
|
|
|
size, expected_size, display->vbt.version);
|
2024-02-26 19:58:53 +02:00
|
|
|
|
|
|
|
/* The legacy sized child device config is the minimum we need. */
|
|
|
|
if (size < LEGACY_CHILD_DEVICE_CONFIG_SIZE) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
2024-02-26 19:58:53 +02:00
|
|
|
"Child device config size %d is too small.\n",
|
|
|
|
size);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-11-24 09:48:44 +08:00
|
|
|
static void
|
2024-08-09 17:27:06 +03:00
|
|
|
parse_general_definitions(struct intel_display *display)
|
2009-11-24 09:48:44 +08:00
|
|
|
{
|
2017-08-24 21:54:08 +03:00
|
|
|
const struct bdb_general_definitions *defs;
|
2021-03-17 18:36:47 +02:00
|
|
|
struct intel_bios_encoder_data *devdata;
|
2017-08-24 21:54:08 +03:00
|
|
|
const struct child_device_config *child;
|
2019-11-08 17:39:49 +02:00
|
|
|
int i, child_device_num;
|
2015-08-21 16:52:01 +03:00
|
|
|
u16 block_size;
|
2017-09-28 11:22:02 +03:00
|
|
|
int bus_pin;
|
2009-11-24 09:48:44 +08:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
defs = bdb_find_section(display, BDB_GENERAL_DEFINITIONS);
|
2017-08-24 21:54:08 +03:00
|
|
|
if (!defs) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"No general definition block is found, no devices defined.\n");
|
2009-11-24 09:48:44 +08:00
|
|
|
return;
|
|
|
|
}
|
2017-09-28 11:22:02 +03:00
|
|
|
|
|
|
|
block_size = get_blocksize(defs);
|
|
|
|
if (block_size < sizeof(*defs)) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"General definitions block too small (%u)\n",
|
|
|
|
block_size);
|
2017-09-28 11:22:02 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bus_pin = defs->crt_ddc_gmbus_pin;
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm, "crt_ddc_bus_pin: %d\n", bus_pin);
|
2024-10-28 22:07:19 +02:00
|
|
|
if (intel_gmbus_is_valid_pin(display, bus_pin))
|
2024-08-09 17:27:06 +03:00
|
|
|
display->vbt.crt_ddc_pin = bus_pin;
|
2017-09-28 11:22:02 +03:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (!child_device_size_valid(display, defs->child_dev_size))
|
2015-12-14 18:23:46 +02:00
|
|
|
return;
|
|
|
|
|
2009-11-24 09:48:44 +08:00
|
|
|
/* get the number of child device */
|
2017-08-24 21:54:08 +03:00
|
|
|
child_device_num = (block_size - sizeof(*defs)) / defs->child_dev_size;
|
2009-11-24 09:48:44 +08:00
|
|
|
|
|
|
|
for (i = 0; i < child_device_num; i++) {
|
2017-08-24 21:54:08 +03:00
|
|
|
child = child_device_ptr(defs, i);
|
2017-09-28 11:22:01 +03:00
|
|
|
if (!child->device_type)
|
2009-11-24 09:48:44 +08:00
|
|
|
continue;
|
2014-05-27 19:33:59 +05:30
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"Found VBT child device with type 0x%x\n",
|
|
|
|
child->device_type);
|
2019-06-18 10:51:31 -07:00
|
|
|
|
2019-11-08 17:39:49 +02:00
|
|
|
devdata = kzalloc(sizeof(*devdata), GFP_KERNEL);
|
|
|
|
if (!devdata)
|
|
|
|
break;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
devdata->display = display;
|
2021-03-17 18:36:48 +02:00
|
|
|
|
2015-08-21 16:52:01 +03:00
|
|
|
/*
|
|
|
|
* Copy as much as we know (sizeof) and is available
|
2019-11-08 17:39:49 +02:00
|
|
|
* (child_dev_size) of the child device config. Accessing the
|
|
|
|
* data must depend on VBT version.
|
2015-08-21 16:52:01 +03:00
|
|
|
*/
|
2019-11-08 17:39:49 +02:00
|
|
|
memcpy(&devdata->child, child,
|
2017-08-24 21:54:08 +03:00
|
|
|
min_t(size_t, defs->child_dev_size, sizeof(*child)));
|
2019-11-08 17:39:49 +02:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
list_add_tail(&devdata->node, &display->vbt.display_devices);
|
2009-11-24 09:48:44 +08:00
|
|
|
}
|
2019-11-08 17:39:49 +02:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (list_empty(&display->vbt.display_devices))
|
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"no child dev is parsed from VBT\n");
|
2009-11-24 09:48:44 +08:00
|
|
|
}
|
2010-08-19 16:09:23 +01:00
|
|
|
|
2017-03-10 15:27:58 +02:00
|
|
|
/* Common defaults which may be overridden by VBT. */
|
2010-09-30 09:36:39 +01:00
|
|
|
static void
|
2024-08-09 17:27:06 +03:00
|
|
|
init_vbt_defaults(struct intel_display *display)
|
2010-09-30 09:36:39 +01:00
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
display->vbt.crt_ddc_pin = GMBUS_PIN_VGADDC;
|
2010-09-30 09:36:39 +01:00
|
|
|
|
|
|
|
/* general features */
|
2024-08-09 17:27:06 +03:00
|
|
|
display->vbt.int_tv_support = 1;
|
|
|
|
display->vbt.int_crt_support = 1;
|
2011-01-12 13:38:39 -08:00
|
|
|
|
2018-05-08 17:08:14 +03:00
|
|
|
/* driver features */
|
2024-08-09 17:27:06 +03:00
|
|
|
display->vbt.int_lvds_support = 1;
|
2018-05-08 17:08:14 +03:00
|
|
|
|
2011-01-12 13:38:39 -08:00
|
|
|
/* Default to using SSC */
|
2024-08-09 17:27:06 +03:00
|
|
|
display->vbt.lvds_use_ssc = 1;
|
2013-11-13 17:59:43 -08:00
|
|
|
/*
|
|
|
|
* Core/SandyBridge/IvyBridge use alternative (120MHz) reference
|
|
|
|
* clock for LVDS.
|
|
|
|
*/
|
2024-08-09 17:27:06 +03:00
|
|
|
display->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(display,
|
2025-04-17 12:10:36 +03:00
|
|
|
!HAS_PCH_SPLIT(display));
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm, "Set default to SSC at %d kHz\n",
|
|
|
|
display->vbt.lvds_ssc_freq);
|
2017-03-10 15:27:58 +02:00
|
|
|
}
|
|
|
|
|
2022-05-10 13:42:39 +03:00
|
|
|
/* Common defaults which may be overridden by VBT. */
|
|
|
|
static void
|
|
|
|
init_vbt_panel_defaults(struct intel_panel *panel)
|
|
|
|
{
|
|
|
|
/* Default to having backlight */
|
|
|
|
panel->vbt.backlight.present = true;
|
|
|
|
|
|
|
|
/* LFP panel data */
|
|
|
|
panel->vbt.lvds_dither = true;
|
|
|
|
}
|
|
|
|
|
2017-03-10 15:27:58 +02:00
|
|
|
/* Defaults to initialize only if there is no VBT. */
|
|
|
|
static void
|
2024-08-09 17:27:06 +03:00
|
|
|
init_vbt_missing_defaults(struct intel_display *display)
|
2017-03-10 15:27:58 +02:00
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
unsigned int ports = DISPLAY_RUNTIME_INFO(display)->port_mask;
|
2017-03-10 15:27:58 +02:00
|
|
|
enum port port;
|
|
|
|
|
2024-10-28 21:48:44 +02:00
|
|
|
if (!HAS_DDI(display) && !display->platform.cherryview)
|
2021-03-17 18:36:44 +02:00
|
|
|
return;
|
|
|
|
|
2021-03-17 18:36:45 +02:00
|
|
|
for_each_port_masked(port, ports) {
|
2021-03-17 18:36:47 +02:00
|
|
|
struct intel_bios_encoder_data *devdata;
|
2021-03-17 18:36:46 +02:00
|
|
|
struct child_device_config *child;
|
2025-03-04 12:27:30 +02:00
|
|
|
enum phy phy = intel_port_to_phy(display, port);
|
2013-09-12 17:12:18 -03:00
|
|
|
|
2019-01-28 13:42:42 +02:00
|
|
|
/*
|
|
|
|
* VBT has the TypeC mode (native,TBT/USB) and we don't want
|
|
|
|
* to detect it.
|
|
|
|
*/
|
2025-03-04 12:27:30 +02:00
|
|
|
if (intel_phy_is_tc(display, phy))
|
2019-01-28 13:42:42 +02:00
|
|
|
continue;
|
|
|
|
|
2021-03-17 18:36:46 +02:00
|
|
|
/* Create fake child device config */
|
|
|
|
devdata = kzalloc(sizeof(*devdata), GFP_KERNEL);
|
|
|
|
if (!devdata)
|
|
|
|
break;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
devdata->display = display;
|
2021-03-17 18:36:46 +02:00
|
|
|
child = &devdata->child;
|
|
|
|
|
|
|
|
if (port == PORT_F)
|
|
|
|
child->dvo_port = DVO_PORT_HDMIF;
|
|
|
|
else if (port == PORT_E)
|
|
|
|
child->dvo_port = DVO_PORT_HDMIE;
|
|
|
|
else
|
|
|
|
child->dvo_port = DVO_PORT_HDMIA + port;
|
|
|
|
|
|
|
|
if (port != PORT_A && port != PORT_E)
|
|
|
|
child->device_type |= DEVICE_TYPE_TMDS_DVI_SIGNALING;
|
|
|
|
|
|
|
|
if (port != PORT_E)
|
|
|
|
child->device_type |= DEVICE_TYPE_DISPLAYPORT_OUTPUT;
|
|
|
|
|
|
|
|
if (port == PORT_A)
|
|
|
|
child->device_type |= DEVICE_TYPE_INTERNAL_CONNECTOR;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
list_add_tail(&devdata->node, &display->vbt.display_devices);
|
2021-03-17 18:36:46 +02:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
2024-09-05 14:25:19 +03:00
|
|
|
"Generating default VBT child device with type 0x%04x on port %c\n",
|
2021-03-17 18:36:46 +02:00
|
|
|
child->device_type, port_name(port));
|
2013-09-12 17:06:24 -03:00
|
|
|
}
|
2021-03-17 18:36:46 +02:00
|
|
|
|
|
|
|
/* Bypass some minimum baseline VBT version checks */
|
2024-08-09 17:27:06 +03:00
|
|
|
display->vbt.version = 155;
|
2010-09-30 09:36:39 +01:00
|
|
|
}
|
|
|
|
|
2015-12-14 12:50:47 +02:00
|
|
|
static const struct bdb_header *get_bdb_header(const struct vbt_header *vbt)
|
|
|
|
{
|
|
|
|
const void *_vbt = vbt;
|
|
|
|
|
|
|
|
return _vbt + vbt->bdb_offset;
|
|
|
|
}
|
|
|
|
|
2024-09-23 18:24:52 +03:00
|
|
|
static const char vbt_signature[] = "$VBT";
|
|
|
|
static const int vbt_signature_len = 4;
|
|
|
|
|
2015-12-15 13:16:15 +02:00
|
|
|
/**
|
|
|
|
* intel_bios_is_valid_vbt - does the given buffer contain a valid VBT
|
2024-08-09 17:27:06 +03:00
|
|
|
* @display: display device
|
2015-12-15 13:16:15 +02:00
|
|
|
* @buf: pointer to a buffer to validate
|
|
|
|
* @size: size of the buffer
|
|
|
|
*
|
|
|
|
* Returns true on valid VBT.
|
|
|
|
*/
|
2024-08-09 17:27:06 +03:00
|
|
|
bool intel_bios_is_valid_vbt(struct intel_display *display,
|
2024-02-08 17:17:14 +02:00
|
|
|
const void *buf, size_t size)
|
2014-04-18 18:04:22 -03:00
|
|
|
{
|
2015-12-15 13:16:15 +02:00
|
|
|
const struct vbt_header *vbt = buf;
|
2015-05-12 15:41:32 +03:00
|
|
|
const struct bdb_header *bdb;
|
2014-04-18 18:04:22 -03:00
|
|
|
|
2015-12-14 12:50:47 +02:00
|
|
|
if (!vbt)
|
2015-12-15 13:16:15 +02:00
|
|
|
return false;
|
2015-12-14 12:50:47 +02:00
|
|
|
|
2015-12-15 13:16:15 +02:00
|
|
|
if (sizeof(struct vbt_header) > size) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm, "VBT header incomplete\n");
|
2015-12-15 13:16:15 +02:00
|
|
|
return false;
|
2014-04-18 18:04:22 -03:00
|
|
|
}
|
|
|
|
|
2024-09-23 18:24:52 +03:00
|
|
|
if (memcmp(vbt->signature, vbt_signature, vbt_signature_len)) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm, "VBT invalid signature\n");
|
2015-12-15 13:16:15 +02:00
|
|
|
return false;
|
2014-04-18 18:04:22 -03:00
|
|
|
}
|
|
|
|
|
2019-11-08 13:13:52 -08:00
|
|
|
if (vbt->vbt_size > size) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
|
|
|
"VBT incomplete (vbt_size overflows)\n");
|
2019-11-08 13:13:52 -08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
size = vbt->vbt_size;
|
|
|
|
|
2017-01-06 15:20:12 +00:00
|
|
|
if (range_overflows_t(size_t,
|
|
|
|
vbt->bdb_offset,
|
|
|
|
sizeof(struct bdb_header),
|
|
|
|
size)) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm, "BDB header incomplete\n");
|
2015-12-15 13:16:15 +02:00
|
|
|
return false;
|
2014-04-18 18:04:22 -03:00
|
|
|
}
|
|
|
|
|
2015-12-14 12:50:47 +02:00
|
|
|
bdb = get_bdb_header(vbt);
|
2017-01-06 15:20:12 +00:00
|
|
|
if (range_overflows_t(size_t, vbt->bdb_offset, bdb->bdb_size, size)) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm, "BDB incomplete\n");
|
2015-12-15 13:16:15 +02:00
|
|
|
return false;
|
2014-04-18 18:04:22 -03:00
|
|
|
}
|
|
|
|
|
2015-12-14 12:50:47 +02:00
|
|
|
return vbt;
|
2014-04-18 18:04:22 -03:00
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
static struct vbt_header *firmware_get_vbt(struct intel_display *display,
|
2024-02-28 13:32:32 -08:00
|
|
|
size_t *size)
|
|
|
|
{
|
|
|
|
struct vbt_header *vbt = NULL;
|
|
|
|
const struct firmware *fw = NULL;
|
2024-08-09 17:27:06 +03:00
|
|
|
const char *name = display->params.vbt_firmware;
|
2024-02-28 13:32:32 -08:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (!name || !*name)
|
|
|
|
return NULL;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
ret = request_firmware(&fw, name, display->drm->dev);
|
2024-02-28 13:32:32 -08:00
|
|
|
if (ret) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_err(display->drm,
|
2024-02-28 13:32:32 -08:00
|
|
|
"Requesting VBT firmware \"%s\" failed (%d)\n",
|
|
|
|
name, ret);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (intel_bios_is_valid_vbt(display, fw->data, fw->size)) {
|
2024-02-28 13:32:32 -08:00
|
|
|
vbt = kmemdup(fw->data, fw->size, GFP_KERNEL);
|
|
|
|
if (vbt) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
2024-02-28 13:32:32 -08:00
|
|
|
"Found valid VBT firmware \"%s\"\n", name);
|
|
|
|
if (size)
|
|
|
|
*size = fw->size;
|
|
|
|
}
|
|
|
|
} else {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm, "Invalid VBT firmware \"%s\"\n",
|
2024-02-28 13:32:32 -08:00
|
|
|
name);
|
|
|
|
}
|
|
|
|
|
|
|
|
release_firmware(fw);
|
|
|
|
|
|
|
|
return vbt;
|
|
|
|
}
|
|
|
|
|
2024-09-23 18:24:53 +03:00
|
|
|
static struct vbt_header *oprom_get_vbt(struct intel_display *display,
|
|
|
|
struct intel_rom *rom,
|
|
|
|
size_t *size, const char *type)
|
2021-12-15 22:26:45 -08:00
|
|
|
{
|
2024-09-23 18:24:53 +03:00
|
|
|
struct vbt_header *vbt;
|
|
|
|
size_t vbt_size;
|
|
|
|
loff_t offset;
|
2021-12-15 22:26:45 -08:00
|
|
|
|
2024-09-23 18:24:53 +03:00
|
|
|
if (!rom)
|
|
|
|
return NULL;
|
2021-12-15 22:26:45 -08:00
|
|
|
|
2024-09-23 18:24:52 +03:00
|
|
|
BUILD_BUG_ON(vbt_signature_len != sizeof(vbt_signature) - 1);
|
|
|
|
BUILD_BUG_ON(vbt_signature_len != sizeof(u32));
|
|
|
|
|
2024-09-23 18:24:53 +03:00
|
|
|
offset = intel_rom_find(rom, *(const u32 *)vbt_signature);
|
|
|
|
if (offset < 0)
|
|
|
|
goto err_free_rom;
|
2021-12-15 22:26:45 -08:00
|
|
|
|
2024-09-23 18:24:53 +03:00
|
|
|
if (sizeof(struct vbt_header) > intel_rom_size(rom) - offset) {
|
2024-09-23 18:24:49 +03:00
|
|
|
drm_dbg_kms(display->drm, "VBT header incomplete\n");
|
2024-09-23 18:24:53 +03:00
|
|
|
goto err_free_rom;
|
2024-09-23 18:24:49 +03:00
|
|
|
}
|
|
|
|
|
2024-09-23 18:24:53 +03:00
|
|
|
BUILD_BUG_ON(sizeof(vbt->vbt_size) != sizeof(u16));
|
2021-12-15 22:26:45 -08:00
|
|
|
|
2024-09-23 18:24:53 +03:00
|
|
|
vbt_size = intel_rom_read16(rom, offset + offsetof(struct vbt_header, vbt_size));
|
|
|
|
if (vbt_size > intel_rom_size(rom) - offset) {
|
|
|
|
drm_dbg_kms(display->drm, "VBT incomplete (vbt_size overflows)\n");
|
|
|
|
goto err_free_rom;
|
2024-09-23 18:24:49 +03:00
|
|
|
}
|
|
|
|
|
2021-12-22 10:16:54 +02:00
|
|
|
vbt = kzalloc(round_up(vbt_size, 4), GFP_KERNEL);
|
2021-12-15 22:26:45 -08:00
|
|
|
if (!vbt)
|
2024-09-23 18:24:53 +03:00
|
|
|
goto err_free_rom;
|
2021-12-15 22:26:45 -08:00
|
|
|
|
2024-09-23 18:24:53 +03:00
|
|
|
intel_rom_read_block(rom, vbt, offset, vbt_size);
|
2021-12-15 22:26:45 -08:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (!intel_bios_is_valid_vbt(display, vbt, vbt_size))
|
2021-12-15 22:26:45 -08:00
|
|
|
goto err_free_vbt;
|
|
|
|
|
2024-09-23 18:24:53 +03:00
|
|
|
drm_dbg_kms(display->drm, "Found valid VBT in %s\n", type);
|
2021-12-15 22:26:45 -08:00
|
|
|
|
2024-02-28 13:32:31 -08:00
|
|
|
if (size)
|
|
|
|
*size = vbt_size;
|
|
|
|
|
2024-09-23 18:24:53 +03:00
|
|
|
intel_rom_free(rom);
|
2021-12-15 22:26:45 -08:00
|
|
|
|
2019-11-26 14:51:08 -08:00
|
|
|
return vbt;
|
|
|
|
|
|
|
|
err_free_vbt:
|
|
|
|
kfree(vbt);
|
2024-09-23 18:24:53 +03:00
|
|
|
err_free_rom:
|
|
|
|
intel_rom_free(rom);
|
2015-12-15 13:16:15 +02:00
|
|
|
return NULL;
|
2015-05-13 15:34:04 +03:00
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
static const struct vbt_header *intel_bios_get_vbt(struct intel_display *display,
|
2024-03-04 13:23:31 -08:00
|
|
|
size_t *sizep)
|
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
struct drm_i915_private *i915 = to_i915(display->drm);
|
2024-03-04 13:23:31 -08:00
|
|
|
const struct vbt_header *vbt = NULL;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
vbt = firmware_get_vbt(display, sizep);
|
2024-03-04 13:23:31 -08:00
|
|
|
|
|
|
|
if (!vbt)
|
2024-08-09 17:27:05 +03:00
|
|
|
vbt = intel_opregion_get_vbt(display, sizep);
|
2024-03-04 13:23:31 -08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the OpRegion does not have VBT, look in SPI flash
|
|
|
|
* through MMIO or PCI mapping
|
|
|
|
*/
|
2025-04-09 21:17:53 +03:00
|
|
|
if (!vbt && display->platform.dgfx)
|
2025-03-20 17:03:56 +02:00
|
|
|
with_intel_display_rpm(display)
|
2024-09-23 18:24:53 +03:00
|
|
|
vbt = oprom_get_vbt(display, intel_rom_spi(i915), sizep, "SPI flash");
|
2024-03-04 13:23:31 -08:00
|
|
|
|
|
|
|
if (!vbt)
|
2025-03-20 17:03:56 +02:00
|
|
|
with_intel_display_rpm(display)
|
2024-09-23 18:24:53 +03:00
|
|
|
vbt = oprom_get_vbt(display, intel_rom_pci(i915), sizep, "PCI ROM");
|
2024-03-04 13:23:31 -08:00
|
|
|
|
|
|
|
return vbt;
|
|
|
|
}
|
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
/**
|
2015-12-14 12:50:49 +02:00
|
|
|
* intel_bios_init - find VBT and initialize settings from the BIOS
|
2024-08-09 17:27:06 +03:00
|
|
|
* @display: display device instance
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
*
|
2017-03-10 15:27:57 +02:00
|
|
|
* Parse and initialize settings from the Video BIOS Tables (VBT). If the VBT
|
|
|
|
* was not found in ACPI OpRegion, try to find it in PCI ROM first. Also
|
|
|
|
* initialize some defaults if the VBT is not present at all.
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
*/
|
2024-08-09 17:27:06 +03:00
|
|
|
void intel_bios_init(struct intel_display *display)
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
{
|
2024-01-11 19:21:16 +02:00
|
|
|
const struct vbt_header *vbt;
|
2015-12-14 12:50:47 +02:00
|
|
|
const struct bdb_header *bdb;
|
2010-08-19 16:09:23 +01:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
INIT_LIST_HEAD(&display->vbt.display_devices);
|
|
|
|
INIT_LIST_HEAD(&display->vbt.bdb_blocks);
|
2019-11-08 17:39:49 +02:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (!HAS_DISPLAY(display)) {
|
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"Skipping VBT init due to disabled display.\n");
|
2017-03-10 15:27:57 +02:00
|
|
|
return;
|
|
|
|
}
|
2013-04-05 13:12:41 -07:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
init_vbt_defaults(display);
|
2010-07-20 15:44:45 -07:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
vbt = intel_bios_get_vbt(display, NULL);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
|
2021-12-15 22:26:45 -08:00
|
|
|
if (!vbt)
|
|
|
|
goto out;
|
|
|
|
|
2015-12-14 12:50:47 +02:00
|
|
|
bdb = get_bdb_header(vbt);
|
2024-08-09 17:27:06 +03:00
|
|
|
display->vbt.version = bdb->version;
|
2015-12-14 12:50:47 +02:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"VBT signature \"%.*s\", BDB version %d\n",
|
2024-08-09 17:27:06 +03:00
|
|
|
(int)sizeof(vbt->signature), vbt->signature,
|
|
|
|
display->vbt.version);
|
2015-12-15 13:14:52 +02:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
init_bdb_blocks(display, bdb);
|
2022-04-06 16:38:17 +03:00
|
|
|
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
/* Grab useful general definitions */
|
2024-08-09 17:27:06 +03:00
|
|
|
parse_general_features(display);
|
|
|
|
parse_general_definitions(display);
|
|
|
|
parse_driver_features(display);
|
2017-09-28 11:22:03 +03:00
|
|
|
|
2019-12-10 12:50:46 +02:00
|
|
|
/* Depends on child device list */
|
2024-08-09 17:27:06 +03:00
|
|
|
parse_compression_parameters(display);
|
2019-12-10 12:50:46 +02:00
|
|
|
|
2017-03-10 15:27:57 +02:00
|
|
|
out:
|
2017-03-10 15:27:58 +02:00
|
|
|
if (!vbt) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_info(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"Failed to find VBIOS tables (VBT)\n");
|
2024-08-09 17:27:06 +03:00
|
|
|
init_vbt_missing_defaults(display);
|
2017-03-10 15:27:58 +02:00
|
|
|
}
|
2017-03-10 15:27:57 +02:00
|
|
|
|
2021-03-17 18:36:46 +02:00
|
|
|
/* Further processing on pre-parsed or generated child device data */
|
2024-08-09 17:27:06 +03:00
|
|
|
parse_sdvo_device_mapping(display);
|
|
|
|
parse_ddi_ports(display);
|
2021-03-17 18:36:46 +02:00
|
|
|
|
2024-03-04 13:23:31 -08:00
|
|
|
kfree(vbt);
|
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs.
Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are
supported. HDMI, DisplayPort and additional SDVO output support will
follow.
Support for the mode setting code is controlled by the new 'modeset'
module option. A new config option, CONFIG_DRM_I915_KMS controls the
default behavior, and whether a PCI ID list is built into the module for
use by user level module utilities.
Note that if mode setting is enabled, user level drivers that access
display registers directly or that don't use the kernel graphics memory
manager will likely corrupt kernel graphics memory, disrupt output
configuration (possibly leading to hangs and/or blank displays), and
prevent panic/oops messages from appearing. So use caution when
enabling this code; be sure your user level code supports the new
interfaces.
A new SysRq key, 'g', provides emergency support for switching back to
the kernel's framebuffer console; which is useful for testing.
Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2008-11-07 14:24:08 -08:00
|
|
|
}
|
2016-03-16 12:43:29 +02:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
static void intel_bios_init_panel(struct intel_display *display,
|
2022-11-25 19:31:49 +02:00
|
|
|
struct intel_panel *panel,
|
|
|
|
const struct intel_bios_encoder_data *devdata,
|
2023-01-25 13:10:50 +02:00
|
|
|
const struct drm_edid *drm_edid,
|
2022-11-25 19:31:49 +02:00
|
|
|
bool use_fallback)
|
2022-05-10 13:42:38 +03:00
|
|
|
{
|
2022-11-25 19:31:49 +02:00
|
|
|
/* already have it? */
|
|
|
|
if (panel->vbt.panel_type >= 0) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_WARN_ON(display->drm, !use_fallback);
|
2022-11-25 19:31:49 +02:00
|
|
|
return;
|
|
|
|
}
|
2022-05-10 13:42:39 +03:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
panel->vbt.panel_type = get_panel_type(display, devdata,
|
2023-01-25 13:10:50 +02:00
|
|
|
drm_edid, use_fallback);
|
2022-11-25 19:31:49 +02:00
|
|
|
if (panel->vbt.panel_type < 0) {
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_WARN_ON(display->drm, use_fallback);
|
2022-11-25 19:31:49 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
init_vbt_panel_defaults(panel);
|
2022-06-15 18:14:43 +03:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
parse_panel_options(display, panel);
|
|
|
|
parse_generic_dtd(display, panel);
|
|
|
|
parse_lfp_data(display, panel);
|
|
|
|
parse_lfp_backlight(display, panel);
|
|
|
|
parse_sdvo_lvds_data(display, panel);
|
|
|
|
parse_panel_driver_features(display, panel);
|
|
|
|
parse_power_conservation_features(display, panel);
|
|
|
|
parse_edp(display, panel);
|
|
|
|
parse_psr(display, panel);
|
|
|
|
parse_mipi_config(display, panel);
|
|
|
|
parse_mipi_sequence(display, panel);
|
2022-05-10 13:42:38 +03:00
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
void intel_bios_init_panel_early(struct intel_display *display,
|
2022-11-25 19:31:49 +02:00
|
|
|
struct intel_panel *panel,
|
|
|
|
const struct intel_bios_encoder_data *devdata)
|
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
intel_bios_init_panel(display, panel, devdata, NULL, false);
|
2022-11-25 19:31:49 +02:00
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
void intel_bios_init_panel_late(struct intel_display *display,
|
2022-11-25 19:31:49 +02:00
|
|
|
struct intel_panel *panel,
|
|
|
|
const struct intel_bios_encoder_data *devdata,
|
2023-01-25 13:10:50 +02:00
|
|
|
const struct drm_edid *drm_edid)
|
2022-11-25 19:31:49 +02:00
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
intel_bios_init_panel(display, panel, devdata, drm_edid, true);
|
2022-11-25 19:31:49 +02:00
|
|
|
}
|
|
|
|
|
2018-02-14 09:21:49 +01:00
|
|
|
/**
|
2019-07-12 13:24:29 +02:00
|
|
|
* intel_bios_driver_remove - Free any resources allocated by intel_bios_init()
|
2024-08-09 17:27:06 +03:00
|
|
|
* @display: display device instance
|
2018-02-14 09:21:49 +01:00
|
|
|
*/
|
2024-08-09 17:27:06 +03:00
|
|
|
void intel_bios_driver_remove(struct intel_display *display)
|
2018-02-14 09:21:49 +01:00
|
|
|
{
|
2022-04-06 16:38:17 +03:00
|
|
|
struct intel_bios_encoder_data *devdata, *nd;
|
|
|
|
struct bdb_block_entry *entry, *ne;
|
2019-11-08 17:39:49 +02:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
list_for_each_entry_safe(devdata, nd, &display->vbt.display_devices,
|
|
|
|
node) {
|
2019-11-08 17:39:49 +02:00
|
|
|
list_del(&devdata->node);
|
2019-12-10 12:50:46 +02:00
|
|
|
kfree(devdata->dsc);
|
2019-11-08 17:39:49 +02:00
|
|
|
kfree(devdata);
|
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
list_for_each_entry_safe(entry, ne, &display->vbt.bdb_blocks, node) {
|
2022-04-06 16:38:17 +03:00
|
|
|
list_del(&entry->node);
|
|
|
|
kfree(entry);
|
|
|
|
}
|
2022-05-10 13:42:39 +03:00
|
|
|
}
|
2022-04-06 16:38:17 +03:00
|
|
|
|
2022-05-10 13:42:39 +03:00
|
|
|
void intel_bios_fini_panel(struct intel_panel *panel)
|
|
|
|
{
|
|
|
|
kfree(panel->vbt.sdvo_lvds_vbt_mode);
|
|
|
|
panel->vbt.sdvo_lvds_vbt_mode = NULL;
|
2024-05-03 15:24:18 +03:00
|
|
|
kfree(panel->vbt.lfp_vbt_mode);
|
|
|
|
panel->vbt.lfp_vbt_mode = NULL;
|
2022-05-10 13:42:39 +03:00
|
|
|
kfree(panel->vbt.dsi.data);
|
|
|
|
panel->vbt.dsi.data = NULL;
|
|
|
|
kfree(panel->vbt.dsi.pps);
|
|
|
|
panel->vbt.dsi.pps = NULL;
|
|
|
|
kfree(panel->vbt.dsi.config);
|
|
|
|
panel->vbt.dsi.config = NULL;
|
|
|
|
kfree(panel->vbt.dsi.deassert_seq);
|
|
|
|
panel->vbt.dsi.deassert_seq = NULL;
|
2018-02-14 09:21:49 +01:00
|
|
|
}
|
|
|
|
|
2016-03-16 12:43:29 +02:00
|
|
|
/**
|
|
|
|
* intel_bios_is_tv_present - is integrated TV present in VBT
|
2024-08-09 17:27:06 +03:00
|
|
|
* @display: display device instance
|
2016-03-16 12:43:29 +02:00
|
|
|
*
|
|
|
|
* Return true if TV is present. If no child devices were parsed from VBT,
|
|
|
|
* assume TV is present.
|
|
|
|
*/
|
2024-08-09 17:27:06 +03:00
|
|
|
bool intel_bios_is_tv_present(struct intel_display *display)
|
2016-03-16 12:43:29 +02:00
|
|
|
{
|
2021-03-17 18:36:47 +02:00
|
|
|
const struct intel_bios_encoder_data *devdata;
|
2016-03-16 12:43:29 +02:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (!display->vbt.int_tv_support)
|
2016-03-16 12:43:29 +02:00
|
|
|
return false;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (list_empty(&display->vbt.display_devices))
|
2016-03-16 12:43:29 +02:00
|
|
|
return true;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
list_for_each_entry(devdata, &display->vbt.display_devices, node) {
|
2023-02-08 03:55:00 +02:00
|
|
|
const struct child_device_config *child = &devdata->child;
|
2019-11-08 17:39:49 +02:00
|
|
|
|
2016-03-16 12:43:29 +02:00
|
|
|
/*
|
|
|
|
* If the device type is not TV, continue.
|
|
|
|
*/
|
2017-08-24 21:54:03 +03:00
|
|
|
switch (child->device_type) {
|
2016-03-16 12:43:29 +02:00
|
|
|
case DEVICE_TYPE_INT_TV:
|
|
|
|
case DEVICE_TYPE_TV:
|
|
|
|
case DEVICE_TYPE_TV_SVIDEO_COMPOSITE:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* Only when the addin_offset is non-zero, it is regarded
|
|
|
|
* as present.
|
|
|
|
*/
|
2017-08-24 21:54:03 +03:00
|
|
|
if (child->addin_offset)
|
2016-03-16 12:43:29 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2016-03-16 12:43:30 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* intel_bios_is_lvds_present - is LVDS present in VBT
|
2024-08-09 17:27:06 +03:00
|
|
|
* @display: display device instance
|
2016-03-16 12:43:30 +02:00
|
|
|
* @i2c_pin: i2c pin for LVDS if present
|
|
|
|
*
|
|
|
|
* Return true if LVDS is present. If no child devices were parsed from VBT,
|
|
|
|
* assume LVDS is present.
|
|
|
|
*/
|
2024-08-09 17:27:06 +03:00
|
|
|
bool intel_bios_is_lvds_present(struct intel_display *display, u8 *i2c_pin)
|
2016-03-16 12:43:30 +02:00
|
|
|
{
|
2021-03-17 18:36:47 +02:00
|
|
|
const struct intel_bios_encoder_data *devdata;
|
2016-03-16 12:43:30 +02:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (list_empty(&display->vbt.display_devices))
|
2016-03-16 12:43:30 +02:00
|
|
|
return true;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
list_for_each_entry(devdata, &display->vbt.display_devices, node) {
|
2023-02-08 03:55:00 +02:00
|
|
|
const struct child_device_config *child = &devdata->child;
|
2016-03-16 12:43:30 +02:00
|
|
|
|
|
|
|
/* If the device type is not LFP, continue.
|
|
|
|
* We have to check both the new identifiers as well as the
|
|
|
|
* old for compatibility with some BIOSes.
|
|
|
|
*/
|
|
|
|
if (child->device_type != DEVICE_TYPE_INT_LFP &&
|
|
|
|
child->device_type != DEVICE_TYPE_LFP)
|
|
|
|
continue;
|
|
|
|
|
2024-10-28 22:07:19 +02:00
|
|
|
if (intel_gmbus_is_valid_pin(display, child->i2c_pin))
|
2016-03-16 12:43:30 +02:00
|
|
|
*i2c_pin = child->i2c_pin;
|
|
|
|
|
|
|
|
/* However, we cannot trust the BIOS writers to populate
|
|
|
|
* the VBT correctly. Since LVDS requires additional
|
|
|
|
* information from AIM blocks, a non-zero addin offset is
|
|
|
|
* a good indicator that the LVDS is actually present.
|
|
|
|
*/
|
|
|
|
if (child->addin_offset)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
/* But even then some BIOS writers perform some black magic
|
|
|
|
* and instantiate the device without reference to any
|
|
|
|
* additional data. Trust that if the VBT was written into
|
|
|
|
* the OpRegion then they have validated the LVDS's existence.
|
|
|
|
*/
|
2024-08-09 17:27:05 +03:00
|
|
|
return intel_opregion_vbt_present(display);
|
2016-03-16 12:43:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2016-03-16 12:43:31 +02:00
|
|
|
|
2016-06-03 12:17:43 +03:00
|
|
|
/**
|
|
|
|
* intel_bios_is_port_present - is the specified digital port present
|
2024-08-09 17:27:06 +03:00
|
|
|
* @display: display device instance
|
2016-06-03 12:17:43 +03:00
|
|
|
* @port: port to check
|
|
|
|
*
|
|
|
|
* Return true if the device in %port is present.
|
|
|
|
*/
|
2024-08-09 17:27:06 +03:00
|
|
|
bool intel_bios_is_port_present(struct intel_display *display, enum port port)
|
2016-06-03 12:17:43 +03:00
|
|
|
{
|
2023-02-14 09:38:18 +02:00
|
|
|
const struct intel_bios_encoder_data *devdata;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (WARN_ON(!has_ddi_port_info(display)))
|
2021-12-17 17:54:01 +02:00
|
|
|
return true;
|
2016-06-03 12:17:43 +03:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (!is_port_valid(display, port))
|
2023-02-14 09:38:18 +02:00
|
|
|
return false;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
list_for_each_entry(devdata, &display->vbt.display_devices, node) {
|
2023-02-14 09:38:18 +02:00
|
|
|
const struct child_device_config *child = &devdata->child;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (dvo_port_to_port(display, child->dvo_port) == port)
|
2023-02-14 09:38:18 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2016-06-03 12:17:43 +03:00
|
|
|
}
|
|
|
|
|
2023-05-09 19:02:06 +03:00
|
|
|
bool intel_bios_encoder_supports_dp_dual_mode(const struct intel_bios_encoder_data *devdata)
|
2016-05-04 14:45:22 +03:00
|
|
|
{
|
2021-12-17 17:54:02 +02:00
|
|
|
const struct child_device_config *child = &devdata->child;
|
|
|
|
|
2024-03-19 11:24:42 +02:00
|
|
|
if (!devdata)
|
|
|
|
return false;
|
|
|
|
|
2021-12-17 17:54:02 +02:00
|
|
|
if (!intel_bios_encoder_supports_dp(devdata) ||
|
|
|
|
!intel_bios_encoder_supports_hdmi(devdata))
|
2016-05-04 14:45:22 +03:00
|
|
|
return false;
|
|
|
|
|
2021-10-25 17:21:47 +03:00
|
|
|
if (dvo_port_type(child->dvo_port) == DVO_PORT_DPA)
|
2016-11-11 19:14:24 +02:00
|
|
|
return true;
|
|
|
|
|
|
|
|
/* Only accept a HDMI dvo_port as DP++ if it has an AUX channel */
|
2021-10-25 17:21:47 +03:00
|
|
|
if (dvo_port_type(child->dvo_port) == DVO_PORT_HDMIA &&
|
2017-08-24 21:54:03 +03:00
|
|
|
child->aux_channel != 0)
|
2016-11-11 19:14:24 +02:00
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-03-16 12:43:32 +02:00
|
|
|
/**
|
|
|
|
* intel_bios_is_dsi_present - is DSI present in VBT
|
2024-08-09 17:27:06 +03:00
|
|
|
* @display: display device instance
|
2016-03-16 12:43:32 +02:00
|
|
|
* @port: port for DSI if present
|
|
|
|
*
|
|
|
|
* Return true if DSI is present, and return the port in %port.
|
|
|
|
*/
|
2024-08-09 17:27:06 +03:00
|
|
|
bool intel_bios_is_dsi_present(struct intel_display *display,
|
2016-03-16 12:43:32 +02:00
|
|
|
enum port *port)
|
|
|
|
{
|
2021-03-17 18:36:47 +02:00
|
|
|
const struct intel_bios_encoder_data *devdata;
|
2016-03-16 12:43:32 +02:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
list_for_each_entry(devdata, &display->vbt.display_devices, node) {
|
2023-02-08 03:55:00 +02:00
|
|
|
const struct child_device_config *child = &devdata->child;
|
|
|
|
u8 dvo_port = child->dvo_port;
|
2016-03-16 12:43:32 +02:00
|
|
|
|
2017-08-24 21:54:03 +03:00
|
|
|
if (!(child->device_type & DEVICE_TYPE_MIPI_OUTPUT))
|
2016-03-16 12:43:32 +02:00
|
|
|
continue;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (dsi_dvo_port_to_port(display, dvo_port) == PORT_NONE) {
|
|
|
|
drm_dbg_kms(display->drm,
|
drm/i915/bios: convert to struct drm_device logging macros.
This replaces the printk based logging macros with the struct drm_device
based logging macros.
This conversion was achieved using the following coccinelle script that
transforms based on the existence of a struct drm_i915_private device:
@rule1@
identifier fn, T;
@@
fn(struct drm_i915_private *T,...) {
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
)
...+>
}
@rule2@
identifier fn, T;
@@
fn(...) {
...
struct drm_i915_private *T = ...;
<+...
(
-DRM_INFO(
+drm_info(&T->drm,
...)
|
-DRM_ERROR(
+drm_err(&T->drm,
...)
|
-DRM_WARN(
+drm_warn(&T->drm,
...)
|
-DRM_DEBUG(
+drm_dbg(&T->drm,
...)
|
-DRM_DEBUG_KMS(
+drm_dbg_kms(&T->drm,
...)
|
-DRM_DEBUG_DRIVER(
+drm_dbg(&T->drm,
...)
)
...+>
}
Formatting warnings by checkpatch are addressed manually.
Signed-off-by: Wambui Karuga <wambui.karugax@gmail.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200121134559.17355-3-wambui.karugax@gmail.com
2020-01-21 16:45:56 +03:00
|
|
|
"VBT has unsupported DSI port %c\n",
|
|
|
|
port_name(dvo_port - DVO_PORT_MIPIA));
|
2023-02-07 08:43:35 +02:00
|
|
|
continue;
|
2016-03-16 12:43:32 +02:00
|
|
|
}
|
2023-02-07 08:43:35 +02:00
|
|
|
|
|
|
|
if (port)
|
2024-08-09 17:27:06 +03:00
|
|
|
*port = dsi_dvo_port_to_port(display, dvo_port);
|
2023-02-07 08:43:35 +02:00
|
|
|
return true;
|
2016-03-16 12:43:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2016-03-31 16:11:47 +05:30
|
|
|
|
2019-12-10 12:50:47 +02:00
|
|
|
static void fill_dsc(struct intel_crtc_state *crtc_state,
|
|
|
|
struct dsc_compression_parameters_entry *dsc,
|
|
|
|
int dsc_max_bpc)
|
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
struct intel_display *display = to_intel_display(crtc_state);
|
2019-12-10 12:50:47 +02:00
|
|
|
struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config;
|
|
|
|
int bpc = 8;
|
|
|
|
|
|
|
|
vdsc_cfg->dsc_version_major = dsc->version_major;
|
|
|
|
vdsc_cfg->dsc_version_minor = dsc->version_minor;
|
|
|
|
|
|
|
|
if (dsc->support_12bpc && dsc_max_bpc >= 12)
|
|
|
|
bpc = 12;
|
|
|
|
else if (dsc->support_10bpc && dsc_max_bpc >= 10)
|
|
|
|
bpc = 10;
|
|
|
|
else if (dsc->support_8bpc && dsc_max_bpc >= 8)
|
|
|
|
bpc = 8;
|
|
|
|
else
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm, "VBT: Unsupported BPC %d for DCS\n",
|
2024-02-08 17:17:14 +02:00
|
|
|
dsc_max_bpc);
|
2019-12-10 12:50:47 +02:00
|
|
|
|
|
|
|
crtc_state->pipe_bpp = bpc * 3;
|
|
|
|
|
2024-08-05 18:07:50 +03:00
|
|
|
crtc_state->dsc.compressed_bpp_x16 = fxp_q4_from_int(min(crtc_state->pipe_bpp,
|
|
|
|
VBT_DSC_MAX_BPP(dsc->max_bpp)));
|
2019-12-10 12:50:47 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* FIXME: This is ugly, and slice count should take DSC engine
|
|
|
|
* throughput etc. into account.
|
|
|
|
*
|
|
|
|
* Also, per spec DSI supports 1, 2, 3 or 4 horizontal slices.
|
|
|
|
*/
|
|
|
|
if (dsc->slices_per_line & BIT(2)) {
|
|
|
|
crtc_state->dsc.slice_count = 4;
|
|
|
|
} else if (dsc->slices_per_line & BIT(1)) {
|
|
|
|
crtc_state->dsc.slice_count = 2;
|
|
|
|
} else {
|
|
|
|
/* FIXME */
|
|
|
|
if (!(dsc->slices_per_line & BIT(0)))
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
|
|
|
"VBT: Unsupported DSC slice count for DSI\n");
|
2019-12-10 12:50:47 +02:00
|
|
|
|
|
|
|
crtc_state->dsc.slice_count = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (crtc_state->hw.adjusted_mode.crtc_hdisplay %
|
|
|
|
crtc_state->dsc.slice_count != 0)
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
|
|
|
"VBT: DSC hdisplay %d not divisible by slice count %d\n",
|
2024-02-08 17:17:14 +02:00
|
|
|
crtc_state->hw.adjusted_mode.crtc_hdisplay,
|
|
|
|
crtc_state->dsc.slice_count);
|
2019-12-10 12:50:47 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The VBT rc_buffer_block_size and rc_buffer_size definitions
|
2020-12-08 14:33:54 +02:00
|
|
|
* correspond to DP 1.4 DPCD offsets 0x62 and 0x63.
|
2019-12-10 12:50:47 +02:00
|
|
|
*/
|
2020-12-08 14:33:54 +02:00
|
|
|
vdsc_cfg->rc_model_size = drm_dsc_dp_rc_buffer_size(dsc->rc_buffer_block_size,
|
|
|
|
dsc->rc_buffer_size);
|
2019-12-10 12:50:47 +02:00
|
|
|
|
|
|
|
/* FIXME: DSI spec says bpc + 1 for this one */
|
|
|
|
vdsc_cfg->line_buf_depth = VBT_DSC_LINE_BUFFER_DEPTH(dsc->line_buffer_depth);
|
|
|
|
|
|
|
|
vdsc_cfg->block_pred_enable = dsc->block_prediction_enable;
|
|
|
|
|
|
|
|
vdsc_cfg->slice_height = dsc->slice_height;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: initially DSI specific */
|
|
|
|
bool intel_bios_get_dsc_params(struct intel_encoder *encoder,
|
|
|
|
struct intel_crtc_state *crtc_state,
|
|
|
|
int dsc_max_bpc)
|
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
struct intel_display *display = to_intel_display(encoder);
|
2021-03-17 18:36:47 +02:00
|
|
|
const struct intel_bios_encoder_data *devdata;
|
2019-12-10 12:50:47 +02:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
list_for_each_entry(devdata, &display->vbt.display_devices, node) {
|
2023-02-08 03:55:00 +02:00
|
|
|
const struct child_device_config *child = &devdata->child;
|
2019-12-10 12:50:47 +02:00
|
|
|
|
|
|
|
if (!(child->device_type & DEVICE_TYPE_MIPI_OUTPUT))
|
|
|
|
continue;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (dsi_dvo_port_to_port(display, child->dvo_port) == encoder->port) {
|
2019-12-10 12:50:47 +02:00
|
|
|
if (!devdata->dsc)
|
|
|
|
return false;
|
|
|
|
|
2023-12-07 21:34:36 +02:00
|
|
|
fill_dsc(crtc_state, devdata->dsc, dsc_max_bpc);
|
2019-12-10 12:50:47 +02:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-05-09 19:02:04 +03:00
|
|
|
static const u8 adlp_aux_ch_map[] = {
|
|
|
|
[AUX_CH_A] = DP_AUX_A,
|
|
|
|
[AUX_CH_B] = DP_AUX_B,
|
|
|
|
[AUX_CH_C] = DP_AUX_C,
|
|
|
|
[AUX_CH_D_XELPD] = DP_AUX_D,
|
|
|
|
[AUX_CH_E_XELPD] = DP_AUX_E,
|
|
|
|
[AUX_CH_USBC1] = DP_AUX_F,
|
|
|
|
[AUX_CH_USBC2] = DP_AUX_G,
|
|
|
|
[AUX_CH_USBC3] = DP_AUX_H,
|
|
|
|
[AUX_CH_USBC4] = DP_AUX_I,
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ADL-S VBT uses PHY based mapping. Combo PHYs A,B,C,D,E
|
|
|
|
* map to DDI A,TC1,TC2,TC3,TC4 respectively.
|
|
|
|
*/
|
|
|
|
static const u8 adls_aux_ch_map[] = {
|
|
|
|
[AUX_CH_A] = DP_AUX_A,
|
|
|
|
[AUX_CH_USBC1] = DP_AUX_B,
|
|
|
|
[AUX_CH_USBC2] = DP_AUX_C,
|
|
|
|
[AUX_CH_USBC3] = DP_AUX_D,
|
|
|
|
[AUX_CH_USBC4] = DP_AUX_E,
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* RKL/DG1 VBT uses PHY based mapping. Combo PHYs A,B,C,D
|
|
|
|
* map to DDI A,B,TC1,TC2 respectively.
|
|
|
|
*/
|
|
|
|
static const u8 rkl_aux_ch_map[] = {
|
|
|
|
[AUX_CH_A] = DP_AUX_A,
|
|
|
|
[AUX_CH_B] = DP_AUX_B,
|
|
|
|
[AUX_CH_USBC1] = DP_AUX_C,
|
|
|
|
[AUX_CH_USBC2] = DP_AUX_D,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const u8 direct_aux_ch_map[] = {
|
|
|
|
[AUX_CH_A] = DP_AUX_A,
|
|
|
|
[AUX_CH_B] = DP_AUX_B,
|
|
|
|
[AUX_CH_C] = DP_AUX_C,
|
|
|
|
[AUX_CH_D] = DP_AUX_D, /* aka AUX_CH_USBC1 */
|
|
|
|
[AUX_CH_E] = DP_AUX_E, /* aka AUX_CH_USBC2 */
|
|
|
|
[AUX_CH_F] = DP_AUX_F, /* aka AUX_CH_USBC3 */
|
|
|
|
[AUX_CH_G] = DP_AUX_G, /* aka AUX_CH_USBC4 */
|
|
|
|
[AUX_CH_H] = DP_AUX_H, /* aka AUX_CH_USBC5 */
|
|
|
|
[AUX_CH_I] = DP_AUX_I, /* aka AUX_CH_USBC6 */
|
|
|
|
};
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
static enum aux_ch map_aux_ch(struct intel_display *display, u8 aux_channel)
|
2018-11-01 16:04:20 +02:00
|
|
|
{
|
2023-05-09 19:02:04 +03:00
|
|
|
const u8 *aux_ch_map;
|
|
|
|
int i, n_entries;
|
2018-11-01 16:04:20 +02:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
if (DISPLAY_VER(display) >= 13) {
|
2023-05-09 19:02:04 +03:00
|
|
|
aux_ch_map = adlp_aux_ch_map;
|
|
|
|
n_entries = ARRAY_SIZE(adlp_aux_ch_map);
|
2024-10-28 21:48:44 +02:00
|
|
|
} else if (display->platform.alderlake_s) {
|
2023-05-09 19:02:04 +03:00
|
|
|
aux_ch_map = adls_aux_ch_map;
|
|
|
|
n_entries = ARRAY_SIZE(adls_aux_ch_map);
|
2024-10-28 21:48:44 +02:00
|
|
|
} else if (display->platform.dg1 || display->platform.rocketlake) {
|
2023-05-09 19:02:04 +03:00
|
|
|
aux_ch_map = rkl_aux_ch_map;
|
|
|
|
n_entries = ARRAY_SIZE(rkl_aux_ch_map);
|
|
|
|
} else {
|
|
|
|
aux_ch_map = direct_aux_ch_map;
|
|
|
|
n_entries = ARRAY_SIZE(direct_aux_ch_map);
|
2018-11-01 16:04:20 +02:00
|
|
|
}
|
|
|
|
|
2023-05-09 19:02:04 +03:00
|
|
|
for (i = 0; i < n_entries; i++) {
|
|
|
|
if (aux_ch_map[i] == aux_channel)
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
drm_dbg_kms(display->drm,
|
2023-05-09 19:02:04 +03:00
|
|
|
"Ignoring alternate AUX CH: VBT claims AUX 0x%x, which is not valid for this platform\n",
|
|
|
|
aux_channel);
|
|
|
|
|
|
|
|
return AUX_CH_NONE;
|
2018-11-01 16:04:20 +02:00
|
|
|
}
|
2020-01-17 16:29:21 +02:00
|
|
|
|
2023-02-17 01:13:09 +02:00
|
|
|
enum aux_ch intel_bios_dp_aux_ch(const struct intel_bios_encoder_data *devdata)
|
|
|
|
{
|
|
|
|
if (!devdata || !devdata->child.aux_channel)
|
|
|
|
return AUX_CH_NONE;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
return map_aux_ch(devdata->display, devdata->child.aux_channel);
|
2023-02-17 01:13:09 +02:00
|
|
|
}
|
2020-01-17 16:29:22 +02:00
|
|
|
|
2023-09-08 08:25:27 +03:00
|
|
|
bool intel_bios_dp_has_shared_aux_ch(const struct intel_bios_encoder_data *devdata)
|
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
struct intel_display *display;
|
2023-09-08 08:25:27 +03:00
|
|
|
u8 aux_channel;
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
if (!devdata || !devdata->child.aux_channel)
|
|
|
|
return false;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
display = devdata->display;
|
2023-09-08 08:25:27 +03:00
|
|
|
aux_channel = devdata->child.aux_channel;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
list_for_each_entry(devdata, &display->vbt.display_devices, node) {
|
2023-09-08 08:25:27 +03:00
|
|
|
if (intel_bios_encoder_supports_dp(devdata) &&
|
|
|
|
aux_channel == devdata->child.aux_channel)
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return count > 1;
|
|
|
|
}
|
|
|
|
|
2023-02-16 02:04:25 +02:00
|
|
|
int intel_bios_dp_boost_level(const struct intel_bios_encoder_data *devdata)
|
2020-01-17 16:29:23 +02:00
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
if (!devdata || devdata->display->vbt.version < 196 || !devdata->child.iboost)
|
2021-03-17 18:36:53 +02:00
|
|
|
return 0;
|
2020-01-17 16:29:23 +02:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
return translate_iboost(devdata->display, devdata->child.dp_iboost_level);
|
2020-01-17 16:29:23 +02:00
|
|
|
}
|
2020-01-17 16:29:24 +02:00
|
|
|
|
2023-02-16 02:04:25 +02:00
|
|
|
int intel_bios_hdmi_boost_level(const struct intel_bios_encoder_data *devdata)
|
2020-01-17 16:29:24 +02:00
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
if (!devdata || devdata->display->vbt.version < 196 || !devdata->child.iboost)
|
2021-03-17 18:36:53 +02:00
|
|
|
return 0;
|
2020-01-17 16:29:24 +02:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
return translate_iboost(devdata->display, devdata->child.hdmi_iboost_level);
|
2020-01-17 16:29:24 +02:00
|
|
|
}
|
2020-01-17 16:29:25 +02:00
|
|
|
|
2023-02-16 02:04:25 +02:00
|
|
|
int intel_bios_hdmi_ddc_pin(const struct intel_bios_encoder_data *devdata)
|
2020-01-17 16:29:25 +02:00
|
|
|
{
|
2021-09-01 19:10:04 +03:00
|
|
|
if (!devdata || !devdata->child.ddc_pin)
|
|
|
|
return 0;
|
2020-01-17 16:29:26 +02:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
return map_ddc_pin(devdata->display, devdata->child.ddc_pin);
|
2020-01-17 16:29:26 +02:00
|
|
|
}
|
2020-01-17 16:29:27 +02:00
|
|
|
|
2021-03-17 18:36:52 +02:00
|
|
|
bool intel_bios_encoder_supports_typec_usb(const struct intel_bios_encoder_data *devdata)
|
2020-01-17 16:29:27 +02:00
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
return devdata->display->vbt.version >= 195 && devdata->child.dp_usb_type_c;
|
2020-01-17 16:29:27 +02:00
|
|
|
}
|
|
|
|
|
2021-03-17 18:36:52 +02:00
|
|
|
bool intel_bios_encoder_supports_tbt(const struct intel_bios_encoder_data *devdata)
|
2020-01-17 16:29:27 +02:00
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
return devdata->display->vbt.version >= 209 && devdata->child.tbt;
|
2020-01-17 16:29:27 +02:00
|
|
|
}
|
2021-03-17 18:36:51 +02:00
|
|
|
|
2023-02-08 03:55:02 +02:00
|
|
|
bool intel_bios_encoder_lane_reversal(const struct intel_bios_encoder_data *devdata)
|
|
|
|
{
|
|
|
|
return devdata && devdata->child.lane_reversal;
|
|
|
|
}
|
|
|
|
|
2023-02-08 03:55:03 +02:00
|
|
|
bool intel_bios_encoder_hpd_invert(const struct intel_bios_encoder_data *devdata)
|
|
|
|
{
|
|
|
|
return devdata && devdata->child.hpd_invert;
|
|
|
|
}
|
|
|
|
|
2021-03-17 18:36:51 +02:00
|
|
|
const struct intel_bios_encoder_data *
|
2024-08-09 17:27:06 +03:00
|
|
|
intel_bios_encoder_data_lookup(struct intel_display *display, enum port port)
|
2021-03-17 18:36:51 +02:00
|
|
|
{
|
2023-06-30 18:58:46 +03:00
|
|
|
struct intel_bios_encoder_data *devdata;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
list_for_each_entry(devdata, &display->vbt.display_devices, node) {
|
2023-06-30 18:58:46 +03:00
|
|
|
if (intel_bios_encoder_port(devdata) == port)
|
|
|
|
return devdata;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
void intel_bios_for_each_encoder(struct intel_display *display,
|
|
|
|
void (*func)(struct intel_display *display,
|
2023-06-30 18:58:46 +03:00
|
|
|
const struct intel_bios_encoder_data *devdata))
|
|
|
|
{
|
|
|
|
struct intel_bios_encoder_data *devdata;
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
list_for_each_entry(devdata, &display->vbt.display_devices, node)
|
|
|
|
func(display, devdata);
|
2021-03-17 18:36:51 +02:00
|
|
|
}
|
2024-01-11 19:21:14 +02:00
|
|
|
|
|
|
|
static int intel_bios_vbt_show(struct seq_file *m, void *unused)
|
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
struct intel_display *display = m->private;
|
2024-01-11 19:21:16 +02:00
|
|
|
const void *vbt;
|
|
|
|
size_t vbt_size;
|
2024-01-11 19:21:14 +02:00
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
vbt = intel_bios_get_vbt(display, &vbt_size);
|
2024-03-04 13:23:31 -08:00
|
|
|
|
|
|
|
if (vbt) {
|
2024-01-11 19:21:16 +02:00
|
|
|
seq_write(m, vbt, vbt_size);
|
2024-03-04 13:23:31 -08:00
|
|
|
kfree(vbt);
|
|
|
|
}
|
2024-01-11 19:21:14 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFINE_SHOW_ATTRIBUTE(intel_bios_vbt);
|
|
|
|
|
2024-08-09 17:27:06 +03:00
|
|
|
void intel_bios_debugfs_register(struct intel_display *display)
|
2024-01-11 19:21:14 +02:00
|
|
|
{
|
2024-08-09 17:27:06 +03:00
|
|
|
struct drm_minor *minor = display->drm->primary;
|
2024-01-11 19:21:14 +02:00
|
|
|
|
|
|
|
debugfs_create_file("i915_vbt", 0444, minor->debugfs_root,
|
2024-08-09 17:27:06 +03:00
|
|
|
display, &intel_bios_vbt_fops);
|
2024-01-11 19:21:14 +02:00
|
|
|
}
|