179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes/*
2395072592e8eabf1b2ea424f1ed4c7458440dbf4Keith Packard * Copyright © 2006 Intel Corporation
379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *
479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * Permission is hereby granted, free of charge, to any person obtaining a
579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * copy of this software and associated documentation files (the "Software"),
679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * to deal in the Software without restriction, including without limitation
779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * the rights to use, copy, modify, merge, publish, distribute, sublicense,
879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * and/or sell copies of the Software, and to permit persons to whom the
979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * Software is furnished to do so, subject to the following conditions:
1079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *
1179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * The above copyright notice and this permission notice (including the next
1279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * paragraph) shall be included in all copies or substantial portions of the
1379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * Software.
1479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *
1579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * SOFTWARE.
2279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *
2379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * Authors:
2479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *    Eric Anholt <eric@anholt.net>
2579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *
2679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes */
2725e341cfc33d94435472983825163e97fe370a6cDaniel Vetter#include <linux/dmi.h>
289f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes#include <drm/drm_dp_helper.h>
2979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes#include "drmP.h"
3079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes#include "drm.h"
3179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes#include "i915_drm.h"
3279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes#include "i915_drv.h"
3379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes#include "intel_bios.h"
3479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
359b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao#define	SLAVE_ADDR1	0x70
369b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao#define	SLAVE_ADDR2	0x72
3779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
38500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0cZhenyu Wangstatic int panel_type;
39500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0cZhenyu Wang
4079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnesstatic void *
4179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnesfind_section(struct bdb_header *bdb, int section_id)
4279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes{
4379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	u8 *base = (u8 *)bdb;
4479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	int index = 0;
4579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	u16 total, current_size;
4679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	u8 current_id;
4779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
4879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	/* skip to first section */
4979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	index += bdb->header_size;
5079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	total = bdb->bdb_size;
5179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
5279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	/* walk the sections looking for section_id */
5379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	while (index < total) {
5479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		current_id = *(base + index);
5579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		index++;
5679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		current_size = *((u16 *)(base + index));
5779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		index += 2;
5879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		if (current_id == section_id)
5979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes			return base + index;
6079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		index += current_size;
6179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	}
6279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
6379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	return NULL;
6479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes}
6579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
66db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)static u16
67db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)get_blocksize(void *p)
68db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG){
69db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)	u16 *block_ptr, block_size;
70db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)
71db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)	block_ptr = (u16 *)((char *)p - 2);
72db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)	block_size = *block_ptr;
73db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)	return block_size;
74db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)}
75db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)
7679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnesstatic void
778863170628da4b0b461eb96bf797df1dca0bd03eMa Lingfill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
7899834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson			const struct lvds_dvo_timing *dvo_timing)
798863170628da4b0b461eb96bf797df1dca0bd03eMa Ling{
808863170628da4b0b461eb96bf797df1dca0bd03eMa Ling	panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) |
818863170628da4b0b461eb96bf797df1dca0bd03eMa Ling		dvo_timing->hactive_lo;
828863170628da4b0b461eb96bf797df1dca0bd03eMa Ling	panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay +
838863170628da4b0b461eb96bf797df1dca0bd03eMa Ling		((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo);
848863170628da4b0b461eb96bf797df1dca0bd03eMa Ling	panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start +
858863170628da4b0b461eb96bf797df1dca0bd03eMa Ling		dvo_timing->hsync_pulse_width;
868863170628da4b0b461eb96bf797df1dca0bd03eMa Ling	panel_fixed_mode->htotal = panel_fixed_mode->hdisplay +
878863170628da4b0b461eb96bf797df1dca0bd03eMa Ling		((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo);
888863170628da4b0b461eb96bf797df1dca0bd03eMa Ling
898863170628da4b0b461eb96bf797df1dca0bd03eMa Ling	panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) |
908863170628da4b0b461eb96bf797df1dca0bd03eMa Ling		dvo_timing->vactive_lo;
918863170628da4b0b461eb96bf797df1dca0bd03eMa Ling	panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay +
928863170628da4b0b461eb96bf797df1dca0bd03eMa Ling		dvo_timing->vsync_off;
938863170628da4b0b461eb96bf797df1dca0bd03eMa Ling	panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start +
948863170628da4b0b461eb96bf797df1dca0bd03eMa Ling		dvo_timing->vsync_pulse_width;
958863170628da4b0b461eb96bf797df1dca0bd03eMa Ling	panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay +
968863170628da4b0b461eb96bf797df1dca0bd03eMa Ling		((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo);
978863170628da4b0b461eb96bf797df1dca0bd03eMa Ling	panel_fixed_mode->clock = dvo_timing->clock * 10;
988863170628da4b0b461eb96bf797df1dca0bd03eMa Ling	panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
998863170628da4b0b461eb96bf797df1dca0bd03eMa Ling
1009bc354998f8aa8a83b0cd430e8fcf2cbc3be7367Adam Jackson	if (dvo_timing->hsync_positive)
1019bc354998f8aa8a83b0cd430e8fcf2cbc3be7367Adam Jackson		panel_fixed_mode->flags |= DRM_MODE_FLAG_PHSYNC;
1029bc354998f8aa8a83b0cd430e8fcf2cbc3be7367Adam Jackson	else
1039bc354998f8aa8a83b0cd430e8fcf2cbc3be7367Adam Jackson		panel_fixed_mode->flags |= DRM_MODE_FLAG_NHSYNC;
1049bc354998f8aa8a83b0cd430e8fcf2cbc3be7367Adam Jackson
1059bc354998f8aa8a83b0cd430e8fcf2cbc3be7367Adam Jackson	if (dvo_timing->vsync_positive)
1069bc354998f8aa8a83b0cd430e8fcf2cbc3be7367Adam Jackson		panel_fixed_mode->flags |= DRM_MODE_FLAG_PVSYNC;
1079bc354998f8aa8a83b0cd430e8fcf2cbc3be7367Adam Jackson	else
1089bc354998f8aa8a83b0cd430e8fcf2cbc3be7367Adam Jackson		panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC;
1099bc354998f8aa8a83b0cd430e8fcf2cbc3be7367Adam Jackson
1108863170628da4b0b461eb96bf797df1dca0bd03eMa Ling	/* Some VBTs have bogus h/vtotal values */
1118863170628da4b0b461eb96bf797df1dca0bd03eMa Ling	if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
1128863170628da4b0b461eb96bf797df1dca0bd03eMa Ling		panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
1138863170628da4b0b461eb96bf797df1dca0bd03eMa Ling	if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal)
1148863170628da4b0b461eb96bf797df1dca0bd03eMa Ling		panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1;
1158863170628da4b0b461eb96bf797df1dca0bd03eMa Ling
1168863170628da4b0b461eb96bf797df1dca0bd03eMa Ling	drm_mode_set_name(panel_fixed_mode);
1178863170628da4b0b461eb96bf797df1dca0bd03eMa Ling}
1188863170628da4b0b461eb96bf797df1dca0bd03eMa Ling
11999834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilsonstatic bool
12099834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilsonlvds_dvo_timing_equal_size(const struct lvds_dvo_timing *a,
12199834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson			   const struct lvds_dvo_timing *b)
12299834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson{
12399834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	if (a->hactive_hi != b->hactive_hi ||
12499834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	    a->hactive_lo != b->hactive_lo)
12599834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson		return false;
12699834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson
12799834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	if (a->hsync_off_hi != b->hsync_off_hi ||
12899834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	    a->hsync_off_lo != b->hsync_off_lo)
12999834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson		return false;
13099834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson
13199834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	if (a->hsync_pulse_width != b->hsync_pulse_width)
13299834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson		return false;
13399834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson
13499834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	if (a->hblank_hi != b->hblank_hi ||
13599834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	    a->hblank_lo != b->hblank_lo)
13699834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson		return false;
13799834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson
13899834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	if (a->vactive_hi != b->vactive_hi ||
13999834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	    a->vactive_lo != b->vactive_lo)
14099834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson		return false;
14199834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson
14299834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	if (a->vsync_off != b->vsync_off)
14399834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson		return false;
14499834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson
14599834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	if (a->vsync_pulse_width != b->vsync_pulse_width)
14699834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson		return false;
14799834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson
14899834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	if (a->vblank_hi != b->vblank_hi ||
14999834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	    a->vblank_lo != b->vblank_lo)
15099834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson		return false;
15199834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson
15299834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	return true;
15399834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson}
15499834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson
15599834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilsonstatic const struct lvds_dvo_timing *
15699834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilsonget_lvds_dvo_timing(const struct bdb_lvds_lfp_data *lvds_lfp_data,
15799834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson		    const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs,
15899834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson		    int index)
15999834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson{
16099834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	/*
16199834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	 * the size of fp_timing varies on the different platform.
16299834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	 * So calculate the DVO timing relative offset in LVDS data
16399834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	 * entry to get the DVO timing entry
16499834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	 */
16599834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson
16699834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	int lfp_data_size =
16799834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson		lvds_lfp_data_ptrs->ptr[1].dvo_timing_offset -
16899834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson		lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset;
16999834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	int dvo_timing_offset =
17099834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson		lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset -
17199834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson		lvds_lfp_data_ptrs->ptr[0].fp_timing_offset;
17299834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	char *entry = (char *)lvds_lfp_data->data + lfp_data_size * index;
17399834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson
17499834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	return (struct lvds_dvo_timing *)(entry + dvo_timing_offset);
17599834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson}
17699834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson
1778863170628da4b0b461eb96bf797df1dca0bd03eMa Ling/* Try to find integrated panel data */
1788863170628da4b0b461eb96bf797df1dca0bd03eMa Lingstatic void
1798863170628da4b0b461eb96bf797df1dca0bd03eMa Lingparse_lfp_panel_data(struct drm_i915_private *dev_priv,
1808863170628da4b0b461eb96bf797df1dca0bd03eMa Ling			    struct bdb_header *bdb)
18179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes{
18299834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	const struct bdb_lvds_options *lvds_options;
18399834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	const struct bdb_lvds_lfp_data *lvds_lfp_data;
18499834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
18599834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	const struct lvds_dvo_timing *panel_dvo_timing;
18679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	struct drm_display_mode *panel_fixed_mode;
18799834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	int i, downclock;
18879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
18979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
19079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (!lvds_options)
19179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		return;
19279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
19379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	dev_priv->lvds_dither = lvds_options->pixel_dither;
19479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (lvds_options->panel_type == 0xff)
19579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		return;
1966a04002bea137d2c6359228316d9c827806e475fSimon Que
197500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0cZhenyu Wang	panel_type = lvds_options->panel_type;
19879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
19979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);
20079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (!lvds_lfp_data)
20179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		return;
20279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
2031b16de0b070dc6fa29b7a99980eabe3325ee5983Jesse Barnes	lvds_lfp_data_ptrs = find_section(bdb, BDB_LVDS_LFP_DATA_PTRS);
2041b16de0b070dc6fa29b7a99980eabe3325ee5983Jesse Barnes	if (!lvds_lfp_data_ptrs)
2051b16de0b070dc6fa29b7a99980eabe3325ee5983Jesse Barnes		return;
2061b16de0b070dc6fa29b7a99980eabe3325ee5983Jesse Barnes
20779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	dev_priv->lvds_vbt = 1;
20879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
20999834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	panel_dvo_timing = get_lvds_dvo_timing(lvds_lfp_data,
21099834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson					       lvds_lfp_data_ptrs,
21199834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson					       lvds_options->panel_type);
21279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
2139a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
2146edc3242e35f03990e362e7c115e722717f0f7a7Chris Wilson	if (!panel_fixed_mode)
2156edc3242e35f03990e362e7c115e722717f0f7a7Chris Wilson		return;
21679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
21799834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	fill_detail_timing_data(panel_fixed_mode, panel_dvo_timing);
21879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
2198863170628da4b0b461eb96bf797df1dca0bd03eMa Ling	dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode;
22079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
22128c97730c36e06d5ba0c442156eb2154347cc3feZhao Yakui	DRM_DEBUG_KMS("Found panel mode in BIOS VBT tables:\n");
2228863170628da4b0b461eb96bf797df1dca0bd03eMa Ling	drm_mode_debug_printmodeline(panel_fixed_mode);
22337df96736bfe6f5fd9a141d62946e1083d73e712Jesse Barnes
224d1fcea6a529d22212b324f26cd660c85b289a026Zhao Yakui	/*
22599834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	 * Iterate over the LVDS panel timing info to find the lowest clock
22699834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	 * for the native resolution.
227d1fcea6a529d22212b324f26cd660c85b289a026Zhao Yakui	 */
22899834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	downclock = panel_dvo_timing->clock;
229d1fcea6a529d22212b324f26cd660c85b289a026Zhao Yakui	for (i = 0; i < 16; i++) {
23099834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson		const struct lvds_dvo_timing *dvo_timing;
23199834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson
23299834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson		dvo_timing = get_lvds_dvo_timing(lvds_lfp_data,
23399834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson						 lvds_lfp_data_ptrs,
23499834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson						 i);
23599834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson		if (lvds_dvo_timing_equal_size(dvo_timing, panel_dvo_timing) &&
23699834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson		    dvo_timing->clock < downclock)
23799834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson			downclock = dvo_timing->clock;
238d1fcea6a529d22212b324f26cd660c85b289a026Zhao Yakui	}
23999834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson
24099834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson	if (downclock < panel_dvo_timing->clock && i915_lvds_downclock) {
241d1fcea6a529d22212b324f26cd660c85b289a026Zhao Yakui		dev_priv->lvds_downclock_avail = 1;
24299834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson		dev_priv->lvds_downclock = downclock * 10;
243bbb0aef5cfe95fe9b51a7eeba4a440b69037b01fJoe Perches		DRM_DEBUG_KMS("LVDS downclock is found in VBT. "
244bbb0aef5cfe95fe9b51a7eeba4a440b69037b01fJoe Perches			      "Normal Clock %dKHz, downclock %dKHz\n",
24599834ea446d5c0da3f6cfa355fe4670840d45f79Chris Wilson			      panel_fixed_mode->clock, 10*downclock);
246d1fcea6a529d22212b324f26cd660c85b289a026Zhao Yakui	}
2478863170628da4b0b461eb96bf797df1dca0bd03eMa Ling}
2488863170628da4b0b461eb96bf797df1dca0bd03eMa Ling
2498863170628da4b0b461eb96bf797df1dca0bd03eMa Ling/* Try to find sdvo panel data */
2508863170628da4b0b461eb96bf797df1dca0bd03eMa Lingstatic void
2518863170628da4b0b461eb96bf797df1dca0bd03eMa Lingparse_sdvo_panel_data(struct drm_i915_private *dev_priv,
2528863170628da4b0b461eb96bf797df1dca0bd03eMa Ling		      struct bdb_header *bdb)
2538863170628da4b0b461eb96bf797df1dca0bd03eMa Ling{
2548863170628da4b0b461eb96bf797df1dca0bd03eMa Ling	struct lvds_dvo_timing *dvo_timing;
2558863170628da4b0b461eb96bf797df1dca0bd03eMa Ling	struct drm_display_mode *panel_fixed_mode;
2565a1e5b6c460dccfd189c7e962281c8cce75da728Chris Wilson	int index;
25779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
2585a1e5b6c460dccfd189c7e962281c8cce75da728Chris Wilson	index = i915_vbt_sdvo_panel_type;
2595a1e5b6c460dccfd189c7e962281c8cce75da728Chris Wilson	if (index == -1) {
2605a1e5b6c460dccfd189c7e962281c8cce75da728Chris Wilson		struct bdb_sdvo_lvds_options *sdvo_lvds_options;
2615a1e5b6c460dccfd189c7e962281c8cce75da728Chris Wilson
2625a1e5b6c460dccfd189c7e962281c8cce75da728Chris Wilson		sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
2635a1e5b6c460dccfd189c7e962281c8cce75da728Chris Wilson		if (!sdvo_lvds_options)
2645a1e5b6c460dccfd189c7e962281c8cce75da728Chris Wilson			return;
2655a1e5b6c460dccfd189c7e962281c8cce75da728Chris Wilson
2665a1e5b6c460dccfd189c7e962281c8cce75da728Chris Wilson		index = sdvo_lvds_options->panel_type;
2675a1e5b6c460dccfd189c7e962281c8cce75da728Chris Wilson	}
2688863170628da4b0b461eb96bf797df1dca0bd03eMa Ling
2698863170628da4b0b461eb96bf797df1dca0bd03eMa Ling	dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS);
2708863170628da4b0b461eb96bf797df1dca0bd03eMa Ling	if (!dvo_timing)
2718863170628da4b0b461eb96bf797df1dca0bd03eMa Ling		return;
2728863170628da4b0b461eb96bf797df1dca0bd03eMa Ling
2739a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
2748863170628da4b0b461eb96bf797df1dca0bd03eMa Ling	if (!panel_fixed_mode)
2758863170628da4b0b461eb96bf797df1dca0bd03eMa Ling		return;
2768863170628da4b0b461eb96bf797df1dca0bd03eMa Ling
2775a1e5b6c460dccfd189c7e962281c8cce75da728Chris Wilson	fill_detail_timing_data(panel_fixed_mode, dvo_timing + index);
2788863170628da4b0b461eb96bf797df1dca0bd03eMa Ling
2798863170628da4b0b461eb96bf797df1dca0bd03eMa Ling	dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode;
28079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
2815a1e5b6c460dccfd189c7e962281c8cce75da728Chris Wilson	DRM_DEBUG_KMS("Found SDVO panel mode in BIOS VBT tables:\n");
2825a1e5b6c460dccfd189c7e962281c8cce75da728Chris Wilson	drm_mode_debug_printmodeline(panel_fixed_mode);
28379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes}
28479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
2859a4114ffa7b6f5f4635e3745a8dc051d15d4596aBryan Freedstatic int intel_bios_ssc_frequency(struct drm_device *dev,
2869a4114ffa7b6f5f4635e3745a8dc051d15d4596aBryan Freed				    bool alternate)
2879a4114ffa7b6f5f4635e3745a8dc051d15d4596aBryan Freed{
2889a4114ffa7b6f5f4635e3745a8dc051d15d4596aBryan Freed	switch (INTEL_INFO(dev)->gen) {
2899a4114ffa7b6f5f4635e3745a8dc051d15d4596aBryan Freed	case 2:
2909a4114ffa7b6f5f4635e3745a8dc051d15d4596aBryan Freed		return alternate ? 66 : 48;
2919a4114ffa7b6f5f4635e3745a8dc051d15d4596aBryan Freed	case 3:
2929a4114ffa7b6f5f4635e3745a8dc051d15d4596aBryan Freed	case 4:
2939a4114ffa7b6f5f4635e3745a8dc051d15d4596aBryan Freed		return alternate ? 100 : 96;
2949a4114ffa7b6f5f4635e3745a8dc051d15d4596aBryan Freed	default:
2959a4114ffa7b6f5f4635e3745a8dc051d15d4596aBryan Freed		return alternate ? 100 : 120;
2969a4114ffa7b6f5f4635e3745a8dc051d15d4596aBryan Freed	}
2979a4114ffa7b6f5f4635e3745a8dc051d15d4596aBryan Freed}
2989a4114ffa7b6f5f4635e3745a8dc051d15d4596aBryan Freed
29979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnesstatic void
30079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnesparse_general_features(struct drm_i915_private *dev_priv,
30179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		       struct bdb_header *bdb)
30279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes{
303bad720ff3e8e47a04bd88d9bbc8317e7d7e049d3Eric Anholt	struct drm_device *dev = dev_priv->dev;
30479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	struct bdb_general_features *general;
30579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
30679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	general = find_section(bdb, BDB_GENERAL_FEATURES);
30779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (general) {
30879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		dev_priv->int_tv_support = general->int_tv_support;
30979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		dev_priv->int_crt_support = general->int_crt_support;
31043565a0648e664744ac9201c199681451355edccKristian Høgsberg		dev_priv->lvds_use_ssc = general->enable_ssc;
3119a4114ffa7b6f5f4635e3745a8dc051d15d4596aBryan Freed		dev_priv->lvds_ssc_freq =
3129a4114ffa7b6f5f4635e3745a8dc051d15d4596aBryan Freed			intel_bios_ssc_frequency(dev, general->ssc_freq);
313abd06860185fc613776adae792772e076d77caf2Keith Packard		dev_priv->display_clock_mode = general->display_clock_mode;
314abd06860185fc613776adae792772e076d77caf2Keith Packard		DRM_DEBUG_KMS("BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d\n",
315562396b9e46bcb34cc18f513fea1c4764d8ea06dKeith Packard			      dev_priv->int_tv_support,
316562396b9e46bcb34cc18f513fea1c4764d8ea06dKeith Packard			      dev_priv->int_crt_support,
317562396b9e46bcb34cc18f513fea1c4764d8ea06dKeith Packard			      dev_priv->lvds_use_ssc,
318abd06860185fc613776adae792772e076d77caf2Keith Packard			      dev_priv->lvds_ssc_freq,
319abd06860185fc613776adae792772e076d77caf2Keith Packard			      dev_priv->display_clock_mode);
32079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	}
32179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes}
32279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
3239b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhaostatic void
324db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)parse_general_definitions(struct drm_i915_private *dev_priv,
325db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)			  struct bdb_header *bdb)
326db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG){
327db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)	struct bdb_general_definitions *general;
328db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)
329db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)	general = find_section(bdb, BDB_GENERAL_DEFINITIONS);
330db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)	if (general) {
331db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)		u16 block_size = get_blocksize(general);
332db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)		if (block_size >= sizeof(*general)) {
333db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)			int bus_pin = general->crt_ddc_gmbus_pin;
33428c97730c36e06d5ba0c442156eb2154347cc3feZhao Yakui			DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin);
335f899fc64cda8569d0529452aafc0da31c042df2eChris Wilson			if (bus_pin >= 1 && bus_pin <= 6)
3362896b5397570f6857fd5d0e0533f640b05b1d162Chris Wilson				dev_priv->crt_ddc_pin = bus_pin;
337db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)		} else {
33828c97730c36e06d5ba0c442156eb2154347cc3feZhao Yakui			DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n",
339db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)				  block_size);
340db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)		}
341db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)	}
342db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)}
343db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)
344db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)static void
3459b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhaoparse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
34644834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson			  struct bdb_header *bdb)
3479b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao{
3489b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao	struct sdvo_device_mapping *p_mapping;
3499b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao	struct bdb_general_definitions *p_defs;
3509b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao	struct child_device_config *p_child;
3519b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao	int i, child_device_num, count;
352db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)	u16	block_size;
3539b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao
3549b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao	p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
3559b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao	if (!p_defs) {
35644834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson		DRM_DEBUG_KMS("No general definition block is found, unable to construct sdvo mapping.\n");
3579b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao		return;
3589b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao	}
3599b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao	/* judge whether the size of child device meets the requirements.
3609b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao	 * If the child device size obtained from general definition block
3619b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao	 * is different with sizeof(struct child_device_config), skip the
3629b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao	 * parsing of sdvo device info
3639b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao	 */
3649b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao	if (p_defs->child_dev_size != sizeof(*p_child)) {
3659b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao		/* different child dev size . Ignore it */
36628c97730c36e06d5ba0c442156eb2154347cc3feZhao Yakui		DRM_DEBUG_KMS("different child size is found. Invalid.\n");
3679b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao		return;
3689b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao	}
3699b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao	/* get the block size of general definitions */
370db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)	block_size = get_blocksize(p_defs);
3719b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao	/* get the number of child device */
3729b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao	child_device_num = (block_size - sizeof(*p_defs)) /
3739b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao				sizeof(*p_child);
3749b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao	count = 0;
3759b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao	for (i = 0; i < child_device_num; i++) {
3769b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao		p_child = &(p_defs->devices[i]);
3779b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao		if (!p_child->device_type) {
3789b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao			/* skip the device block if device type is invalid */
3799b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao			continue;
3809b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao		}
3819b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao		if (p_child->slave_addr != SLAVE_ADDR1 &&
3829b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao			p_child->slave_addr != SLAVE_ADDR2) {
3839b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao			/*
3849b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao			 * If the slave address is neither 0x70 nor 0x72,
3859b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao			 * it is not a SDVO device. Skip it.
3869b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao			 */
3879b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao			continue;
3889b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao		}
3899b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao		if (p_child->dvo_port != DEVICE_PORT_DVOB &&
3909b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao			p_child->dvo_port != DEVICE_PORT_DVOC) {
3919b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao			/* skip the incorrect SDVO port */
3920206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi			DRM_DEBUG_KMS("Incorrect SDVO port. Skip it\n");
3939b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao			continue;
3949b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao		}
39528c97730c36e06d5ba0c442156eb2154347cc3feZhao Yakui		DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on"
39628c97730c36e06d5ba0c442156eb2154347cc3feZhao Yakui				" %s port\n",
3979b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao				p_child->slave_addr,
3989b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao				(p_child->dvo_port == DEVICE_PORT_DVOB) ?
3999b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao					"SDVOB" : "SDVOC");
4009b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao		p_mapping = &(dev_priv->sdvo_mappings[p_child->dvo_port - 1]);
4019b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao		if (!p_mapping->initialized) {
4029b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao			p_mapping->dvo_port = p_child->dvo_port;
4039b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao			p_mapping->slave_addr = p_child->slave_addr;
4049b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao			p_mapping->dvo_wiring = p_child->dvo_wiring;
405b1083333de5357577c5ec55df6c7efa17bee41c7Adam Jackson			p_mapping->ddc_pin = p_child->ddc_pin;
406e957d7720a2797b31231616014b68f4f6203145eChris Wilson			p_mapping->i2c_pin = p_child->i2c_pin;
4079b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao			p_mapping->initialized = 1;
40846eb303682f72717d1a75cdd2309733bfed43396Adam Jackson			DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d\n",
409e957d7720a2797b31231616014b68f4f6203145eChris Wilson				      p_mapping->dvo_port,
410e957d7720a2797b31231616014b68f4f6203145eChris Wilson				      p_mapping->slave_addr,
411e957d7720a2797b31231616014b68f4f6203145eChris Wilson				      p_mapping->dvo_wiring,
412e957d7720a2797b31231616014b68f4f6203145eChris Wilson				      p_mapping->ddc_pin,
41346eb303682f72717d1a75cdd2309733bfed43396Adam Jackson				      p_mapping->i2c_pin);
4149b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao		} else {
41528c97730c36e06d5ba0c442156eb2154347cc3feZhao Yakui			DRM_DEBUG_KMS("Maybe one SDVO port is shared by "
4169b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao					 "two SDVO device.\n");
4179b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao		}
4189b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao		if (p_child->slave2_addr) {
4199b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao			/* Maybe this is a SDVO device with multiple inputs */
4209b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao			/* And the mapping info is not added */
42128c97730c36e06d5ba0c442156eb2154347cc3feZhao Yakui			DRM_DEBUG_KMS("there exists the slave2_addr. Maybe this"
42228c97730c36e06d5ba0c442156eb2154347cc3feZhao Yakui				" is a SDVO device with multiple inputs.\n");
4239b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao		}
4249b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao		count++;
4259b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao	}
4269b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao
4279b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao	if (!count) {
4289b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao		/* No SDVO device info is found */
42928c97730c36e06d5ba0c442156eb2154347cc3feZhao Yakui		DRM_DEBUG_KMS("No SDVO device info is found in VBT\n");
4309b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao	}
4319b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao	return;
4329b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao}
43332f9d658aee5be09ebdd28fc730630e61d0b46dbZhenyu Wang
43432f9d658aee5be09ebdd28fc730630e61d0b46dbZhenyu Wangstatic void
43532f9d658aee5be09ebdd28fc730630e61d0b46dbZhenyu Wangparse_driver_features(struct drm_i915_private *dev_priv,
43632f9d658aee5be09ebdd28fc730630e61d0b46dbZhenyu Wang		       struct bdb_header *bdb)
43732f9d658aee5be09ebdd28fc730630e61d0b46dbZhenyu Wang{
43832f9d658aee5be09ebdd28fc730630e61d0b46dbZhenyu Wang	struct drm_device *dev = dev_priv->dev;
43932f9d658aee5be09ebdd28fc730630e61d0b46dbZhenyu Wang	struct bdb_driver_features *driver;
44032f9d658aee5be09ebdd28fc730630e61d0b46dbZhenyu Wang
44132f9d658aee5be09ebdd28fc730630e61d0b46dbZhenyu Wang	driver = find_section(bdb, BDB_DRIVER_FEATURES);
442652c393a3368af84359da37c45afc35a91144960Jesse Barnes	if (!driver)
443652c393a3368af84359da37c45afc35a91144960Jesse Barnes		return;
444652c393a3368af84359da37c45afc35a91144960Jesse Barnes
4455ceb0f9bb7bde101d8b07cb803002591dcb8c804Chris Wilson	if (SUPPORTS_EDP(dev) &&
4465ceb0f9bb7bde101d8b07cb803002591dcb8c804Chris Wilson	    driver->lvds_config == BDB_DRIVER_FEATURE_EDP)
4475ceb0f9bb7bde101d8b07cb803002591dcb8c804Chris Wilson		dev_priv->edp.support = 1;
448652c393a3368af84359da37c45afc35a91144960Jesse Barnes
4495ceb0f9bb7bde101d8b07cb803002591dcb8c804Chris Wilson	if (driver->dual_frequency)
450652c393a3368af84359da37c45afc35a91144960Jesse Barnes		dev_priv->render_reclock_avail = true;
45132f9d658aee5be09ebdd28fc730630e61d0b46dbZhenyu Wang}
45232f9d658aee5be09ebdd28fc730630e61d0b46dbZhenyu Wang
4536363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakuistatic void
454500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0cZhenyu Wangparse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
455500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0cZhenyu Wang{
456500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0cZhenyu Wang	struct bdb_edp *edp;
4579f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes	struct edp_power_seq *edp_pps;
4589f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes	struct edp_link_params *edp_link_params;
459500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0cZhenyu Wang
460500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0cZhenyu Wang	edp = find_section(bdb, BDB_EDP);
461500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0cZhenyu Wang	if (!edp) {
4625ceb0f9bb7bde101d8b07cb803002591dcb8c804Chris Wilson		if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp.support) {
46376e47c30bdc591815eeb5598f1e2a243a30bd585Joe Perches			DRM_DEBUG_KMS("No eDP BDB found but eDP panel "
4645ceb0f9bb7bde101d8b07cb803002591dcb8c804Chris Wilson				      "supported, assume %dbpp panel color "
4655ceb0f9bb7bde101d8b07cb803002591dcb8c804Chris Wilson				      "depth.\n",
4665ceb0f9bb7bde101d8b07cb803002591dcb8c804Chris Wilson				      dev_priv->edp.bpp);
467500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0cZhenyu Wang		}
468500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0cZhenyu Wang		return;
469500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0cZhenyu Wang	}
470500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0cZhenyu Wang
471500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0cZhenyu Wang	switch ((edp->color_depth >> (panel_type * 2)) & 3) {
472500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0cZhenyu Wang	case EDP_18BPP:
4735ceb0f9bb7bde101d8b07cb803002591dcb8c804Chris Wilson		dev_priv->edp.bpp = 18;
474500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0cZhenyu Wang		break;
475500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0cZhenyu Wang	case EDP_24BPP:
4765ceb0f9bb7bde101d8b07cb803002591dcb8c804Chris Wilson		dev_priv->edp.bpp = 24;
477500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0cZhenyu Wang		break;
478500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0cZhenyu Wang	case EDP_30BPP:
4795ceb0f9bb7bde101d8b07cb803002591dcb8c804Chris Wilson		dev_priv->edp.bpp = 30;
480500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0cZhenyu Wang		break;
481500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0cZhenyu Wang	}
4825ceb0f9bb7bde101d8b07cb803002591dcb8c804Chris Wilson
4839f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes	/* Get the eDP sequencing and link info */
4849f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes	edp_pps = &edp->power_seqs[panel_type];
4859f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes	edp_link_params = &edp->link_params[panel_type];
4865ceb0f9bb7bde101d8b07cb803002591dcb8c804Chris Wilson
4879f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes	dev_priv->edp.pps = *edp_pps;
4885ceb0f9bb7bde101d8b07cb803002591dcb8c804Chris Wilson
4899f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes	dev_priv->edp.rate = edp_link_params->rate ? DP_LINK_BW_2_7 :
4909f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes		DP_LINK_BW_1_62;
4919f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes	switch (edp_link_params->lanes) {
4929f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes	case 0:
4939f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes		dev_priv->edp.lanes = 1;
4949f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes		break;
4959f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes	case 1:
4969f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes		dev_priv->edp.lanes = 2;
4979f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes		break;
4989f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes	case 3:
4999f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes	default:
5009f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes		dev_priv->edp.lanes = 4;
5019f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes		break;
5029f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes	}
5039f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes	switch (edp_link_params->preemphasis) {
5049f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes	case 0:
5059f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes		dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_0;
5069f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes		break;
5079f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes	case 1:
5089f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes		dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_3_5;
5099f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes		break;
5109f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes	case 2:
5119f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes		dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_6;
5129f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes		break;
5139f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes	case 3:
5149f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes		dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_9_5;
5159f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes		break;
5169f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes	}
5179f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes	switch (edp_link_params->vswing) {
5189f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes	case 0:
5199f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes		dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_400;
5209f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes		break;
5219f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes	case 1:
5229f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes		dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_600;
5239f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes		break;
5249f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes	case 2:
5259f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes		dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_800;
5269f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes		break;
5279f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes	case 3:
5289f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes		dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_1200;
5299f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes		break;
5309f0e7ff4b366d27570cbe0ffa137ed1018009114Jesse Barnes	}
531500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0cZhenyu Wang}
532500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0cZhenyu Wang
533500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0cZhenyu Wangstatic void
5346363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakuiparse_device_mapping(struct drm_i915_private *dev_priv,
5356363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui		       struct bdb_header *bdb)
5366363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui{
5376363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	struct bdb_general_definitions *p_defs;
5386363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	struct child_device_config *p_child, *child_dev_ptr;
5396363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	int i, child_device_num, count;
5406363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	u16	block_size;
5416363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui
5426363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
5436363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	if (!p_defs) {
54444834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson		DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n");
5456363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui		return;
5466363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	}
5476363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	/* judge whether the size of child device meets the requirements.
5486363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	 * If the child device size obtained from general definition block
5496363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	 * is different with sizeof(struct child_device_config), skip the
5506363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	 * parsing of sdvo device info
5516363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	 */
5526363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	if (p_defs->child_dev_size != sizeof(*p_child)) {
5536363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui		/* different child dev size . Ignore it */
5546363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui		DRM_DEBUG_KMS("different child size is found. Invalid.\n");
5556363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui		return;
5566363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	}
5576363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	/* get the block size of general definitions */
5586363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	block_size = get_blocksize(p_defs);
5596363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	/* get the number of child device */
5606363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	child_device_num = (block_size - sizeof(*p_defs)) /
5616363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui				sizeof(*p_child);
5626363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	count = 0;
5636363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	/* get the number of child device that is present */
5646363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	for (i = 0; i < child_device_num; i++) {
5656363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui		p_child = &(p_defs->devices[i]);
5666363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui		if (!p_child->device_type) {
5676363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui			/* skip the device block if device type is invalid */
5686363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui			continue;
5696363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui		}
5706363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui		count++;
5716363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	}
5726363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	if (!count) {
5730206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi		DRM_DEBUG_KMS("no child dev is parsed from VBT\n");
5746363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui		return;
5756363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	}
576493dea2876df144ec57a6a9efbe55db43c7a729eThomas Meyer	dev_priv->child_dev = kcalloc(count, sizeof(*p_child), GFP_KERNEL);
5776363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	if (!dev_priv->child_dev) {
5786363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui		DRM_DEBUG_KMS("No memory space for child device\n");
5796363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui		return;
5806363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	}
5816363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui
5826363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	dev_priv->child_dev_num = count;
5836363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	count = 0;
5846363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	for (i = 0; i < child_device_num; i++) {
5856363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui		p_child = &(p_defs->devices[i]);
5866363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui		if (!p_child->device_type) {
5876363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui			/* skip the device block if device type is invalid */
5886363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui			continue;
5896363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui		}
5906363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui		child_dev_ptr = dev_priv->child_dev + count;
5916363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui		count++;
5926363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui		memcpy((void *)child_dev_ptr, (void *)p_child,
5936363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui					sizeof(*p_child));
5946363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	}
5956363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	return;
5966363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui}
59744834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson
5986a04002bea137d2c6359228316d9c827806e475fSimon Questatic void
5996a04002bea137d2c6359228316d9c827806e475fSimon Queinit_vbt_defaults(struct drm_i915_private *dev_priv)
6006a04002bea137d2c6359228316d9c827806e475fSimon Que{
6019a4114ffa7b6f5f4635e3745a8dc051d15d4596aBryan Freed	struct drm_device *dev = dev_priv->dev;
6029a4114ffa7b6f5f4635e3745a8dc051d15d4596aBryan Freed
6036a04002bea137d2c6359228316d9c827806e475fSimon Que	dev_priv->crt_ddc_pin = GMBUS_PORT_VGADDC;
6046a04002bea137d2c6359228316d9c827806e475fSimon Que
6056a04002bea137d2c6359228316d9c827806e475fSimon Que	/* LFP panel data */
6066a04002bea137d2c6359228316d9c827806e475fSimon Que	dev_priv->lvds_dither = 1;
6076a04002bea137d2c6359228316d9c827806e475fSimon Que	dev_priv->lvds_vbt = 0;
6086a04002bea137d2c6359228316d9c827806e475fSimon Que
6096a04002bea137d2c6359228316d9c827806e475fSimon Que	/* SDVO panel data */
6106a04002bea137d2c6359228316d9c827806e475fSimon Que	dev_priv->sdvo_lvds_vbt_mode = NULL;
6116a04002bea137d2c6359228316d9c827806e475fSimon Que
6126a04002bea137d2c6359228316d9c827806e475fSimon Que	/* general features */
6136a04002bea137d2c6359228316d9c827806e475fSimon Que	dev_priv->int_tv_support = 1;
6146a04002bea137d2c6359228316d9c827806e475fSimon Que	dev_priv->int_crt_support = 1;
6159a4114ffa7b6f5f4635e3745a8dc051d15d4596aBryan Freed
6169a4114ffa7b6f5f4635e3745a8dc051d15d4596aBryan Freed	/* Default to using SSC */
6179a4114ffa7b6f5f4635e3745a8dc051d15d4596aBryan Freed	dev_priv->lvds_use_ssc = 1;
6189a4114ffa7b6f5f4635e3745a8dc051d15d4596aBryan Freed	dev_priv->lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1);
619562396b9e46bcb34cc18f513fea1c4764d8ea06dKeith Packard	DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq);
6206a04002bea137d2c6359228316d9c827806e475fSimon Que
6216a04002bea137d2c6359228316d9c827806e475fSimon Que	/* eDP data */
6226a04002bea137d2c6359228316d9c827806e475fSimon Que	dev_priv->edp.bpp = 18;
6236a04002bea137d2c6359228316d9c827806e475fSimon Que}
6246a04002bea137d2c6359228316d9c827806e475fSimon Que
62525e341cfc33d94435472983825163e97fe370a6cDaniel Vetterstatic int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
62625e341cfc33d94435472983825163e97fe370a6cDaniel Vetter{
62725e341cfc33d94435472983825163e97fe370a6cDaniel Vetter	DRM_DEBUG_KMS("Falling back to manually reading VBT from "
62825e341cfc33d94435472983825163e97fe370a6cDaniel Vetter		      "VBIOS ROM for %s\n",
62925e341cfc33d94435472983825163e97fe370a6cDaniel Vetter		      id->ident);
63025e341cfc33d94435472983825163e97fe370a6cDaniel Vetter	return 1;
63125e341cfc33d94435472983825163e97fe370a6cDaniel Vetter}
63225e341cfc33d94435472983825163e97fe370a6cDaniel Vetter
63325e341cfc33d94435472983825163e97fe370a6cDaniel Vetterstatic const struct dmi_system_id intel_no_opregion_vbt[] = {
63425e341cfc33d94435472983825163e97fe370a6cDaniel Vetter	{
63525e341cfc33d94435472983825163e97fe370a6cDaniel Vetter		.callback = intel_no_opregion_vbt_callback,
63625e341cfc33d94435472983825163e97fe370a6cDaniel Vetter		.ident = "ThinkCentre A57",
63725e341cfc33d94435472983825163e97fe370a6cDaniel Vetter		.matches = {
63825e341cfc33d94435472983825163e97fe370a6cDaniel Vetter			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
63925e341cfc33d94435472983825163e97fe370a6cDaniel Vetter			DMI_MATCH(DMI_PRODUCT_NAME, "97027RG"),
64025e341cfc33d94435472983825163e97fe370a6cDaniel Vetter		},
64125e341cfc33d94435472983825163e97fe370a6cDaniel Vetter	},
64225e341cfc33d94435472983825163e97fe370a6cDaniel Vetter	{ }
64325e341cfc33d94435472983825163e97fe370a6cDaniel Vetter};
64425e341cfc33d94435472983825163e97fe370a6cDaniel Vetter
64579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes/**
6466d139a87b747aaebc969ac5f4eb8db766fcd9cbdBryan Freed * intel_parse_bios - find VBT and initialize settings from the BIOS
64779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * @dev: DRM device
64879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *
64979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * Loads the Video BIOS and checks that the VBT exists.  Sets scratch registers
65079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * to appropriate values.
65179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *
65279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * Returns 0 on success, nonzero on failure.
65379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes */
65479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnesbool
6556d139a87b747aaebc969ac5f4eb8db766fcd9cbdBryan Freedintel_parse_bios(struct drm_device *dev)
65679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes{
65779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	struct drm_i915_private *dev_priv = dev->dev_private;
65879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	struct pci_dev *pdev = dev->pdev;
65944834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson	struct bdb_header *bdb = NULL;
66044834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson	u8 __iomem *bios = NULL;
66144834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson
6626a04002bea137d2c6359228316d9c827806e475fSimon Que	init_vbt_defaults(dev_priv);
663f899fc64cda8569d0529452aafc0da31c042df2eChris Wilson
66444834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson	/* XXX Should this validation be moved to intel_opregion.c? */
66525e341cfc33d94435472983825163e97fe370a6cDaniel Vetter	if (!dmi_check_system(intel_no_opregion_vbt) && dev_priv->opregion.vbt) {
66644834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson		struct vbt_header *vbt = dev_priv->opregion.vbt;
66744834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson		if (memcmp(vbt->signature, "$VBT", 4) == 0) {
668562396b9e46bcb34cc18f513fea1c4764d8ea06dKeith Packard			DRM_DEBUG_KMS("Using VBT from OpRegion: %20s\n",
66944834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson					 vbt->signature);
67044834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson			bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset);
67144834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson		} else
67244834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson			dev_priv->opregion.vbt = NULL;
67379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	}
67479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
67544834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson	if (bdb == NULL) {
67644834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson		struct vbt_header *vbt = NULL;
67744834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson		size_t size;
67844834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson		int i;
67979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
68044834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson		bios = pci_map_rom(pdev, &size);
68144834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson		if (!bios)
68244834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson			return -1;
68344834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson
68444834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson		/* Scour memory looking for the VBT signature */
68544834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson		for (i = 0; i + 4 < size; i++) {
68644834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson			if (!memcmp(bios + i, "$VBT", 4)) {
68744834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson				vbt = (struct vbt_header *)(bios + i);
68844834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson				break;
68944834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson			}
69044834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson		}
69144834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson
69244834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson		if (!vbt) {
693bd45545f7405eab9093da84715f19c6385a57662Chris Wilson			DRM_DEBUG_DRIVER("VBT signature missing\n");
69444834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson			pci_unmap_rom(pdev, bios);
69544834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson			return -1;
69644834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson		}
69744834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson
69844834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson		bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset);
69944834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson	}
70079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
70179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	/* Grab useful general definitions */
70279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	parse_general_features(dev_priv, bdb);
703db54501900ad3665dd669f5708ecd04fc5aed495David Müller (ELSOFT AG)	parse_general_definitions(dev_priv, bdb);
7048863170628da4b0b461eb96bf797df1dca0bd03eMa Ling	parse_lfp_panel_data(dev_priv, bdb);
7058863170628da4b0b461eb96bf797df1dca0bd03eMa Ling	parse_sdvo_panel_data(dev_priv, bdb);
7069b9d172d06b0f2d51cc9431e2c6c3055f0cf10efyakui_zhao	parse_sdvo_device_mapping(dev_priv, bdb);
7076363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui	parse_device_mapping(dev_priv, bdb);
70832f9d658aee5be09ebdd28fc730630e61d0b46dbZhenyu Wang	parse_driver_features(dev_priv, bdb);
709500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0cZhenyu Wang	parse_edp(dev_priv, bdb);
71032f9d658aee5be09ebdd28fc730630e61d0b46dbZhenyu Wang
71144834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson	if (bios)
71244834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson		pci_unmap_rom(pdev, bios);
71379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
71479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	return 0;
71579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes}
7166d139a87b747aaebc969ac5f4eb8db766fcd9cbdBryan Freed
7176d139a87b747aaebc969ac5f4eb8db766fcd9cbdBryan Freed/* Ensure that vital registers have been initialised, even if the BIOS
7186d139a87b747aaebc969ac5f4eb8db766fcd9cbdBryan Freed * is absent or just failing to do its job.
7196d139a87b747aaebc969ac5f4eb8db766fcd9cbdBryan Freed */
7206d139a87b747aaebc969ac5f4eb8db766fcd9cbdBryan Freedvoid intel_setup_bios(struct drm_device *dev)
7216d139a87b747aaebc969ac5f4eb8db766fcd9cbdBryan Freed{
7226d139a87b747aaebc969ac5f4eb8db766fcd9cbdBryan Freed	struct drm_i915_private *dev_priv = dev->dev_private;
7236d139a87b747aaebc969ac5f4eb8db766fcd9cbdBryan Freed
7246d139a87b747aaebc969ac5f4eb8db766fcd9cbdBryan Freed	 /* Set the Panel Power On/Off timings if uninitialized. */
7256d139a87b747aaebc969ac5f4eb8db766fcd9cbdBryan Freed	if ((I915_READ(PP_ON_DELAYS) == 0) && (I915_READ(PP_OFF_DELAYS) == 0)) {
7266d139a87b747aaebc969ac5f4eb8db766fcd9cbdBryan Freed		/* Set T2 to 40ms and T5 to 200ms */
7276d139a87b747aaebc969ac5f4eb8db766fcd9cbdBryan Freed		I915_WRITE(PP_ON_DELAYS, 0x019007d0);
7286d139a87b747aaebc969ac5f4eb8db766fcd9cbdBryan Freed
7296d139a87b747aaebc969ac5f4eb8db766fcd9cbdBryan Freed		/* Set T3 to 35ms and Tx to 200ms */
7306d139a87b747aaebc969ac5f4eb8db766fcd9cbdBryan Freed		I915_WRITE(PP_OFF_DELAYS, 0x015e07d0);
7316d139a87b747aaebc969ac5f4eb8db766fcd9cbdBryan Freed	}
7326d139a87b747aaebc969ac5f4eb8db766fcd9cbdBryan Freed}
733