Commit 901a0cad authored by Ville Syrjälä's avatar Ville Syrjälä

drm/i915/bios: Get access to the tail end of the LFP data block

We need to start parsing stuff from the tail end of the LFP data block.
This is made awkward by the fact that the fp_timing table has variable
size. So we must use a bit more finesse to get the tail end, and to
make sure we allocate enough memory for it to make sure our struct
representation fits.

v2: Rebase due to the preallocation of BDB blocks
v3: Rebase due to min_size WARN relocation
v4: Document BDB_LVDS_LFP_DATA vs. BDB_LVDS_LFP_DATA_PTRS order (Jani)
Reviewed-by: default avatarJani Nikula <jani.nikula@intel.com>
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220504150440.13748-4-ville.syrjala@linux.intel.com
parent a87d0a84
...@@ -185,10 +185,14 @@ static const struct { ...@@ -185,10 +185,14 @@ static const struct {
.min_size = sizeof(struct bdb_edp), }, .min_size = sizeof(struct bdb_edp), },
{ .section_id = BDB_LVDS_OPTIONS, { .section_id = BDB_LVDS_OPTIONS,
.min_size = sizeof(struct bdb_lvds_options), }, .min_size = sizeof(struct bdb_lvds_options), },
/*
* BDB_LVDS_LFP_DATA depends on BDB_LVDS_LFP_DATA_PTRS,
* so keep the two ordered.
*/
{ .section_id = BDB_LVDS_LFP_DATA_PTRS, { .section_id = BDB_LVDS_LFP_DATA_PTRS,
.min_size = sizeof(struct bdb_lvds_lfp_data_ptrs), }, .min_size = sizeof(struct bdb_lvds_lfp_data_ptrs), },
{ .section_id = BDB_LVDS_LFP_DATA, { .section_id = BDB_LVDS_LFP_DATA,
.min_size = sizeof(struct bdb_lvds_lfp_data), }, .min_size = 0, /* special case */ },
{ .section_id = BDB_LVDS_BACKLIGHT, { .section_id = BDB_LVDS_BACKLIGHT,
.min_size = sizeof(struct bdb_lfp_backlight_data), }, .min_size = sizeof(struct bdb_lfp_backlight_data), },
{ .section_id = BDB_LFP_POWER, { .section_id = BDB_LFP_POWER,
...@@ -203,6 +207,23 @@ static const struct { ...@@ -203,6 +207,23 @@ static const struct {
.min_size = sizeof(struct bdb_generic_dtd), }, .min_size = sizeof(struct bdb_generic_dtd), },
}; };
static size_t lfp_data_min_size(struct drm_i915_private *i915)
{
const struct bdb_lvds_lfp_data_ptrs *ptrs;
size_t size;
ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
if (!ptrs)
return 0;
size = sizeof(struct bdb_lvds_lfp_data);
if (ptrs->panel_name.table_size)
size = max(size, ptrs->panel_name.offset +
sizeof(struct bdb_lvds_lfp_data_tail));
return size;
}
static bool validate_lfp_data_ptrs(const void *bdb, static bool validate_lfp_data_ptrs(const void *bdb,
const struct bdb_lvds_lfp_data_ptrs *ptrs) const struct bdb_lvds_lfp_data_ptrs *ptrs)
{ {
...@@ -490,6 +511,9 @@ static void init_bdb_blocks(struct drm_i915_private *i915, ...@@ -490,6 +511,9 @@ static void init_bdb_blocks(struct drm_i915_private *i915,
enum bdb_block_id section_id = bdb_blocks[i].section_id; enum bdb_block_id section_id = bdb_blocks[i].section_id;
size_t min_size = bdb_blocks[i].min_size; size_t min_size = bdb_blocks[i].min_size;
if (section_id == BDB_LVDS_LFP_DATA)
min_size = lfp_data_min_size(i915);
init_bdb_block(i915, bdb, section_id, min_size); init_bdb_block(i915, bdb, section_id, min_size);
} }
} }
...@@ -560,6 +584,16 @@ get_lvds_fp_timing(const struct bdb_lvds_lfp_data *data, ...@@ -560,6 +584,16 @@ get_lvds_fp_timing(const struct bdb_lvds_lfp_data *data,
return (const void *)data + ptrs->ptr[index].fp_timing.offset; return (const void *)data + ptrs->ptr[index].fp_timing.offset;
} }
static const struct bdb_lvds_lfp_data_tail *
get_lfp_data_tail(const struct bdb_lvds_lfp_data *data,
const struct bdb_lvds_lfp_data_ptrs *ptrs)
{
if (ptrs->panel_name.table_size)
return (const void *)data + ptrs->panel_name.offset;
else
return NULL;
}
/* Parse general panel options */ /* Parse general panel options */
static void static void
parse_panel_options(struct drm_i915_private *i915) parse_panel_options(struct drm_i915_private *i915)
...@@ -664,6 +698,7 @@ static void ...@@ -664,6 +698,7 @@ static void
parse_lfp_data(struct drm_i915_private *i915) parse_lfp_data(struct drm_i915_private *i915)
{ {
const struct bdb_lvds_lfp_data *data; const struct bdb_lvds_lfp_data *data;
const struct bdb_lvds_lfp_data_tail *tail;
const struct bdb_lvds_lfp_data_ptrs *ptrs; const struct bdb_lvds_lfp_data_ptrs *ptrs;
ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS); ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
...@@ -676,6 +711,12 @@ parse_lfp_data(struct drm_i915_private *i915) ...@@ -676,6 +711,12 @@ parse_lfp_data(struct drm_i915_private *i915)
if (!i915->vbt.lfp_lvds_vbt_mode) if (!i915->vbt.lfp_lvds_vbt_mode)
parse_lfp_panel_dtd(i915, data, ptrs); parse_lfp_panel_dtd(i915, data, ptrs);
tail = get_lfp_data_tail(data, ptrs);
if (!tail)
return;
(void)tail;
} }
static void static void
......
...@@ -783,6 +783,23 @@ struct lvds_lfp_panel_name { ...@@ -783,6 +783,23 @@ struct lvds_lfp_panel_name {
u8 name[13]; u8 name[13];
} __packed; } __packed;
struct lvds_lfp_black_border {
u8 top; /* 227 */
u8 bottom; /* 227 */
u8 left; /* 238 */
u8 right; /* 238 */
} __packed;
struct bdb_lvds_lfp_data_tail {
struct lvds_lfp_panel_name panel_name[16]; /* 156-163? */
u16 scaling_enable; /* 187 */
u8 seamless_drrs_min_refresh_rate[16]; /* 188 */
u8 pixel_overlap_count[16]; /* 208 */
struct lvds_lfp_black_border black_border[16]; /* 227 */
u16 dual_lfp_port_sync_enable; /* 231 */
u16 gpu_dithering_for_banding_artifacts; /* 245 */
} __packed;
/* /*
* Block 43 - LFP Backlight Control Data Block * Block 43 - LFP Backlight Control Data Block
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment