brintos

brintos / linux-shallow public Read only

0
0
Text · 28.9 KiB · fb4ed9f Raw
1014 lines · c
1/*2 * Copyright © 2006-2007 Intel Corporation3 * Copyright (c) 2006 Dave Airlie <airlied@linux.ie>4 *5 * Permission is hereby granted, free of charge, to any person obtaining a6 * copy of this software and associated documentation files (the "Software"),7 * to deal in the Software without restriction, including without limitation8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,9 * and/or sell copies of the Software, and to permit persons to whom the10 * Software is furnished to do so, subject to the following conditions:11 *12 * The above copyright notice and this permission notice (including the next13 * paragraph) shall be included in all copies or substantial portions of the14 * Software.15 *16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER22 * DEALINGS IN THE SOFTWARE.23 *24 * Authors:25 *	Eric Anholt <eric@anholt.net>26 *      Dave Airlie <airlied@linux.ie>27 *      Jesse Barnes <jesse.barnes@intel.com>28 */29 30#include <acpi/button.h>31#include <linux/acpi.h>32#include <linux/dmi.h>33#include <linux/i2c.h>34#include <linux/slab.h>35#include <linux/vga_switcheroo.h>36 37#include <drm/drm_atomic_helper.h>38#include <drm/drm_crtc.h>39#include <drm/drm_edid.h>40 41#include "i915_drv.h"42#include "i915_reg.h"43#include "intel_atomic.h"44#include "intel_backlight.h"45#include "intel_connector.h"46#include "intel_de.h"47#include "intel_display_types.h"48#include "intel_dpll.h"49#include "intel_fdi.h"50#include "intel_gmbus.h"51#include "intel_lvds.h"52#include "intel_lvds_regs.h"53#include "intel_panel.h"54#include "intel_pps_regs.h"55 56/* Private structure for the integrated LVDS support */57struct intel_lvds_pps {58	/* 100us units */59	int t1_t2;60	int t3;61	int t4;62	int t5;63	int tx;64 65	int divider;66 67	int port;68	bool powerdown_on_reset;69};70 71struct intel_lvds_encoder {72	struct intel_encoder base;73 74	bool is_dual_link;75	i915_reg_t reg;76	u32 a3_power;77 78	struct intel_lvds_pps init_pps;79	u32 init_lvds_val;80 81	struct intel_connector *attached_connector;82};83 84static struct intel_lvds_encoder *to_lvds_encoder(struct intel_encoder *encoder)85{86	return container_of(encoder, struct intel_lvds_encoder, base);87}88 89bool intel_lvds_port_enabled(struct drm_i915_private *i915,90			     i915_reg_t lvds_reg, enum pipe *pipe)91{92	u32 val;93 94	val = intel_de_read(i915, lvds_reg);95 96	/* asserts want to know the pipe even if the port is disabled */97	if (HAS_PCH_CPT(i915))98		*pipe = REG_FIELD_GET(LVDS_PIPE_SEL_MASK_CPT, val);99	else100		*pipe = REG_FIELD_GET(LVDS_PIPE_SEL_MASK, val);101 102	return val & LVDS_PORT_EN;103}104 105static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,106				    enum pipe *pipe)107{108	struct drm_i915_private *i915 = to_i915(encoder->base.dev);109	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder);110	intel_wakeref_t wakeref;111	bool ret;112 113	wakeref = intel_display_power_get_if_enabled(i915, encoder->power_domain);114	if (!wakeref)115		return false;116 117	ret = intel_lvds_port_enabled(i915, lvds_encoder->reg, pipe);118 119	intel_display_power_put(i915, encoder->power_domain, wakeref);120 121	return ret;122}123 124static void intel_lvds_get_config(struct intel_encoder *encoder,125				  struct intel_crtc_state *crtc_state)126{127	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);128	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder);129	u32 tmp, flags = 0;130 131	crtc_state->output_types |= BIT(INTEL_OUTPUT_LVDS);132 133	tmp = intel_de_read(dev_priv, lvds_encoder->reg);134	if (tmp & LVDS_HSYNC_POLARITY)135		flags |= DRM_MODE_FLAG_NHSYNC;136	else137		flags |= DRM_MODE_FLAG_PHSYNC;138	if (tmp & LVDS_VSYNC_POLARITY)139		flags |= DRM_MODE_FLAG_NVSYNC;140	else141		flags |= DRM_MODE_FLAG_PVSYNC;142 143	crtc_state->hw.adjusted_mode.flags |= flags;144 145	if (DISPLAY_VER(dev_priv) < 5)146		crtc_state->gmch_pfit.lvds_border_bits =147			tmp & LVDS_BORDER_ENABLE;148 149	/* gen2/3 store dither state in pfit control, needs to match */150	if (DISPLAY_VER(dev_priv) < 4) {151		tmp = intel_de_read(dev_priv, PFIT_CONTROL(dev_priv));152 153		crtc_state->gmch_pfit.control |= tmp & PFIT_PANEL_8TO6_DITHER_ENABLE;154	}155 156	crtc_state->hw.adjusted_mode.crtc_clock = crtc_state->port_clock;157}158 159static void intel_lvds_pps_get_hw_state(struct drm_i915_private *dev_priv,160					struct intel_lvds_pps *pps)161{162	u32 val;163 164	pps->powerdown_on_reset = intel_de_read(dev_priv,165						PP_CONTROL(dev_priv, 0)) & PANEL_POWER_RESET;166 167	val = intel_de_read(dev_priv, PP_ON_DELAYS(dev_priv, 0));168	pps->port = REG_FIELD_GET(PANEL_PORT_SELECT_MASK, val);169	pps->t1_t2 = REG_FIELD_GET(PANEL_POWER_UP_DELAY_MASK, val);170	pps->t5 = REG_FIELD_GET(PANEL_LIGHT_ON_DELAY_MASK, val);171 172	val = intel_de_read(dev_priv, PP_OFF_DELAYS(dev_priv, 0));173	pps->t3 = REG_FIELD_GET(PANEL_POWER_DOWN_DELAY_MASK, val);174	pps->tx = REG_FIELD_GET(PANEL_LIGHT_OFF_DELAY_MASK, val);175 176	val = intel_de_read(dev_priv, PP_DIVISOR(dev_priv, 0));177	pps->divider = REG_FIELD_GET(PP_REFERENCE_DIVIDER_MASK, val);178	val = REG_FIELD_GET(PANEL_POWER_CYCLE_DELAY_MASK, val);179	/*180	 * Remove the BSpec specified +1 (100ms) offset that accounts for a181	 * too short power-cycle delay due to the asynchronous programming of182	 * the register.183	 */184	if (val)185		val--;186	/* Convert from 100ms to 100us units */187	pps->t4 = val * 1000;188 189	if (DISPLAY_VER(dev_priv) < 5 &&190	    pps->t1_t2 == 0 && pps->t5 == 0 && pps->t3 == 0 && pps->tx == 0) {191		drm_dbg_kms(&dev_priv->drm,192			    "Panel power timings uninitialized, "193			    "setting defaults\n");194		/* Set T2 to 40ms and T5 to 200ms in 100 usec units */195		pps->t1_t2 = 40 * 10;196		pps->t5 = 200 * 10;197		/* Set T3 to 35ms and Tx to 200ms in 100 usec units */198		pps->t3 = 35 * 10;199		pps->tx = 200 * 10;200	}201 202	drm_dbg(&dev_priv->drm, "LVDS PPS:t1+t2 %d t3 %d t4 %d t5 %d tx %d "203		"divider %d port %d powerdown_on_reset %d\n",204		pps->t1_t2, pps->t3, pps->t4, pps->t5, pps->tx,205		pps->divider, pps->port, pps->powerdown_on_reset);206}207 208static void intel_lvds_pps_init_hw(struct drm_i915_private *dev_priv,209				   struct intel_lvds_pps *pps)210{211	u32 val;212 213	val = intel_de_read(dev_priv, PP_CONTROL(dev_priv, 0));214	drm_WARN_ON(&dev_priv->drm,215		    (val & PANEL_UNLOCK_MASK) != PANEL_UNLOCK_REGS);216	if (pps->powerdown_on_reset)217		val |= PANEL_POWER_RESET;218	intel_de_write(dev_priv, PP_CONTROL(dev_priv, 0), val);219 220	intel_de_write(dev_priv, PP_ON_DELAYS(dev_priv, 0),221		       REG_FIELD_PREP(PANEL_PORT_SELECT_MASK, pps->port) |222		       REG_FIELD_PREP(PANEL_POWER_UP_DELAY_MASK, pps->t1_t2) |223		       REG_FIELD_PREP(PANEL_LIGHT_ON_DELAY_MASK, pps->t5));224 225	intel_de_write(dev_priv, PP_OFF_DELAYS(dev_priv, 0),226		       REG_FIELD_PREP(PANEL_POWER_DOWN_DELAY_MASK, pps->t3) |227		       REG_FIELD_PREP(PANEL_LIGHT_OFF_DELAY_MASK, pps->tx));228 229	intel_de_write(dev_priv, PP_DIVISOR(dev_priv, 0),230		       REG_FIELD_PREP(PP_REFERENCE_DIVIDER_MASK, pps->divider) |231		       REG_FIELD_PREP(PANEL_POWER_CYCLE_DELAY_MASK, DIV_ROUND_UP(pps->t4, 1000) + 1));232}233 234static void intel_pre_enable_lvds(struct intel_atomic_state *state,235				  struct intel_encoder *encoder,236				  const struct intel_crtc_state *crtc_state,237				  const struct drm_connector_state *conn_state)238{239	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder);240	struct drm_i915_private *i915 = to_i915(encoder->base.dev);241	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);242	const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;243	enum pipe pipe = crtc->pipe;244	u32 temp;245 246	if (HAS_PCH_SPLIT(i915)) {247		assert_fdi_rx_pll_disabled(i915, pipe);248		assert_shared_dpll_disabled(i915, crtc_state->shared_dpll);249	} else {250		assert_pll_disabled(i915, pipe);251	}252 253	intel_lvds_pps_init_hw(i915, &lvds_encoder->init_pps);254 255	temp = lvds_encoder->init_lvds_val;256	temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;257 258	if (HAS_PCH_CPT(i915)) {259		temp &= ~LVDS_PIPE_SEL_MASK_CPT;260		temp |= LVDS_PIPE_SEL_CPT(pipe);261	} else {262		temp &= ~LVDS_PIPE_SEL_MASK;263		temp |= LVDS_PIPE_SEL(pipe);264	}265 266	/* set the corresponsding LVDS_BORDER bit */267	temp &= ~LVDS_BORDER_ENABLE;268	temp |= crtc_state->gmch_pfit.lvds_border_bits;269 270	/*271	 * Set the B0-B3 data pairs corresponding to whether we're going to272	 * set the DPLLs for dual-channel mode or not.273	 */274	if (lvds_encoder->is_dual_link)275		temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;276	else277		temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);278 279	/*280	 * It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)281	 * appropriately here, but we need to look more thoroughly into how282	 * panels behave in the two modes. For now, let's just maintain the283	 * value we got from the BIOS.284	 */285	temp &= ~LVDS_A3_POWER_MASK;286	temp |= lvds_encoder->a3_power;287 288	/*289	 * Set the dithering flag on LVDS as needed, note that there is no290	 * special lvds dither control bit on pch-split platforms, dithering is291	 * only controlled through the TRANSCONF reg.292	 */293	if (DISPLAY_VER(i915) == 4) {294		/*295		 * Bspec wording suggests that LVDS port dithering only exists296		 * for 18bpp panels.297		 */298		if (crtc_state->dither && crtc_state->pipe_bpp == 18)299			temp |= LVDS_ENABLE_DITHER;300		else301			temp &= ~LVDS_ENABLE_DITHER;302	}303	temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);304	if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)305		temp |= LVDS_HSYNC_POLARITY;306	if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)307		temp |= LVDS_VSYNC_POLARITY;308 309	intel_de_write(i915, lvds_encoder->reg, temp);310}311 312/*313 * Sets the power state for the panel.314 */315static void intel_enable_lvds(struct intel_atomic_state *state,316			      struct intel_encoder *encoder,317			      const struct intel_crtc_state *crtc_state,318			      const struct drm_connector_state *conn_state)319{320	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder);321	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);322 323	intel_de_rmw(dev_priv, lvds_encoder->reg, 0, LVDS_PORT_EN);324 325	intel_de_rmw(dev_priv, PP_CONTROL(dev_priv, 0), 0, PANEL_POWER_ON);326	intel_de_posting_read(dev_priv, lvds_encoder->reg);327 328	if (intel_de_wait_for_set(dev_priv, PP_STATUS(dev_priv, 0), PP_ON, 5000))329		drm_err(&dev_priv->drm,330			"timed out waiting for panel to power on\n");331 332	intel_backlight_enable(crtc_state, conn_state);333}334 335static void intel_disable_lvds(struct intel_atomic_state *state,336			       struct intel_encoder *encoder,337			       const struct intel_crtc_state *old_crtc_state,338			       const struct drm_connector_state *old_conn_state)339{340	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder);341	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);342 343	intel_de_rmw(dev_priv, PP_CONTROL(dev_priv, 0), PANEL_POWER_ON, 0);344	if (intel_de_wait_for_clear(dev_priv, PP_STATUS(dev_priv, 0), PP_ON, 1000))345		drm_err(&dev_priv->drm,346			"timed out waiting for panel to power off\n");347 348	intel_de_rmw(dev_priv, lvds_encoder->reg, LVDS_PORT_EN, 0);349	intel_de_posting_read(dev_priv, lvds_encoder->reg);350}351 352static void gmch_disable_lvds(struct intel_atomic_state *state,353			      struct intel_encoder *encoder,354			      const struct intel_crtc_state *old_crtc_state,355			      const struct drm_connector_state *old_conn_state)356 357{358	intel_backlight_disable(old_conn_state);359 360	intel_disable_lvds(state, encoder, old_crtc_state, old_conn_state);361}362 363static void pch_disable_lvds(struct intel_atomic_state *state,364			     struct intel_encoder *encoder,365			     const struct intel_crtc_state *old_crtc_state,366			     const struct drm_connector_state *old_conn_state)367{368	intel_backlight_disable(old_conn_state);369}370 371static void pch_post_disable_lvds(struct intel_atomic_state *state,372				  struct intel_encoder *encoder,373				  const struct intel_crtc_state *old_crtc_state,374				  const struct drm_connector_state *old_conn_state)375{376	intel_disable_lvds(state, encoder, old_crtc_state, old_conn_state);377}378 379static void intel_lvds_shutdown(struct intel_encoder *encoder)380{381	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);382 383	if (intel_de_wait_for_clear(dev_priv, PP_STATUS(dev_priv, 0), PP_CYCLE_DELAY_ACTIVE, 5000))384		drm_err(&dev_priv->drm,385			"timed out waiting for panel power cycle delay\n");386}387 388static enum drm_mode_status389intel_lvds_mode_valid(struct drm_connector *_connector,390		      struct drm_display_mode *mode)391{392	struct intel_connector *connector = to_intel_connector(_connector);393	struct drm_i915_private *i915 = to_i915(connector->base.dev);394	const struct drm_display_mode *fixed_mode =395		intel_panel_fixed_mode(connector, mode);396	int max_pixclk = to_i915(connector->base.dev)->display.cdclk.max_dotclk_freq;397	enum drm_mode_status status;398 399	status = intel_cpu_transcoder_mode_valid(i915, mode);400	if (status != MODE_OK)401		return status;402 403	status = intel_panel_mode_valid(connector, mode);404	if (status != MODE_OK)405		return status;406 407	if (fixed_mode->clock > max_pixclk)408		return MODE_CLOCK_HIGH;409 410	return MODE_OK;411}412 413static int intel_lvds_compute_config(struct intel_encoder *encoder,414				     struct intel_crtc_state *crtc_state,415				     struct drm_connector_state *conn_state)416{417	struct drm_i915_private *i915 = to_i915(encoder->base.dev);418	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder);419	struct intel_connector *connector = lvds_encoder->attached_connector;420	struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;421	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);422	unsigned int lvds_bpp;423	int ret;424 425	/* Should never happen!! */426	if (DISPLAY_VER(i915) < 4 && crtc->pipe == 0) {427		drm_err(&i915->drm, "Can't support LVDS on pipe A\n");428		return -EINVAL;429	}430 431	if (HAS_PCH_SPLIT(i915)) {432		crtc_state->has_pch_encoder = true;433		if (!intel_fdi_compute_pipe_bpp(crtc_state))434			return -EINVAL;435	}436 437	if (lvds_encoder->a3_power == LVDS_A3_POWER_UP)438		lvds_bpp = 8*3;439	else440		lvds_bpp = 6*3;441 442	/* TODO: Check crtc_state->max_link_bpp_x16 instead of bw_constrained */443	if (lvds_bpp != crtc_state->pipe_bpp && !crtc_state->bw_constrained) {444		drm_dbg_kms(&i915->drm,445			    "forcing display bpp (was %d) to LVDS (%d)\n",446			    crtc_state->pipe_bpp, lvds_bpp);447		crtc_state->pipe_bpp = lvds_bpp;448	}449 450	crtc_state->sink_format = INTEL_OUTPUT_FORMAT_RGB;451	crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB;452 453	/*454	 * We have timings from the BIOS for the panel, put them in455	 * to the adjusted mode.  The CRTC will be set up for this mode,456	 * with the panel scaling set up to source from the H/VDisplay457	 * of the original mode.458	 */459	ret = intel_panel_compute_config(connector, adjusted_mode);460	if (ret)461		return ret;462 463	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)464		return -EINVAL;465 466	ret = intel_panel_fitting(crtc_state, conn_state);467	if (ret)468		return ret;469 470	/*471	 * XXX: It would be nice to support lower refresh rates on the472	 * panels to reduce power consumption, and perhaps match the473	 * user's requested refresh rate.474	 */475 476	return 0;477}478 479/*480 * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.481 */482static int intel_lvds_get_modes(struct drm_connector *_connector)483{484	struct intel_connector *connector = to_intel_connector(_connector);485	const struct drm_edid *fixed_edid = connector->panel.fixed_edid;486 487	/* Use panel fixed edid if we have one */488	if (!IS_ERR_OR_NULL(fixed_edid)) {489		drm_edid_connector_update(&connector->base, fixed_edid);490 491		return drm_edid_connector_add_modes(&connector->base);492	}493 494	return intel_panel_get_modes(connector);495}496 497static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = {498	.get_modes = intel_lvds_get_modes,499	.mode_valid = intel_lvds_mode_valid,500	.atomic_check = intel_digital_connector_atomic_check,501};502 503static const struct drm_connector_funcs intel_lvds_connector_funcs = {504	.detect = intel_panel_detect,505	.fill_modes = drm_helper_probe_single_connector_modes,506	.atomic_get_property = intel_digital_connector_atomic_get_property,507	.atomic_set_property = intel_digital_connector_atomic_set_property,508	.late_register = intel_connector_register,509	.early_unregister = intel_connector_unregister,510	.destroy = intel_connector_destroy,511	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,512	.atomic_duplicate_state = intel_digital_connector_duplicate_state,513};514 515static const struct drm_encoder_funcs intel_lvds_enc_funcs = {516	.destroy = intel_encoder_destroy,517};518 519static int intel_no_lvds_dmi_callback(const struct dmi_system_id *id)520{521	DRM_INFO("Skipping LVDS initialization for %s\n", id->ident);522	return 1;523}524 525/* These systems claim to have LVDS, but really don't */526static const struct dmi_system_id intel_no_lvds[] = {527	{528		.callback = intel_no_lvds_dmi_callback,529		.ident = "Apple Mac Mini (Core series)",530		.matches = {531			DMI_MATCH(DMI_SYS_VENDOR, "Apple"),532			DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"),533		},534	},535	{536		.callback = intel_no_lvds_dmi_callback,537		.ident = "Apple Mac Mini (Core 2 series)",538		.matches = {539			DMI_MATCH(DMI_SYS_VENDOR, "Apple"),540			DMI_MATCH(DMI_PRODUCT_NAME, "Macmini2,1"),541		},542	},543	{544		.callback = intel_no_lvds_dmi_callback,545		.ident = "MSI IM-945GSE-A",546		.matches = {547			DMI_MATCH(DMI_SYS_VENDOR, "MSI"),548			DMI_MATCH(DMI_PRODUCT_NAME, "A9830IMS"),549		},550	},551	{552		.callback = intel_no_lvds_dmi_callback,553		.ident = "Dell Studio Hybrid",554		.matches = {555			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),556			DMI_MATCH(DMI_PRODUCT_NAME, "Studio Hybrid 140g"),557		},558	},559	{560		.callback = intel_no_lvds_dmi_callback,561		.ident = "Dell OptiPlex FX170",562		.matches = {563			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),564			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex FX170"),565		},566	},567	{568		.callback = intel_no_lvds_dmi_callback,569		.ident = "AOpen Mini PC",570		.matches = {571			DMI_MATCH(DMI_SYS_VENDOR, "AOpen"),572			DMI_MATCH(DMI_PRODUCT_NAME, "i965GMx-IF"),573		},574	},575	{576		.callback = intel_no_lvds_dmi_callback,577		.ident = "AOpen Mini PC MP915",578		.matches = {579			DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),580			DMI_MATCH(DMI_BOARD_NAME, "i915GMx-F"),581		},582	},583	{584		.callback = intel_no_lvds_dmi_callback,585		.ident = "AOpen i915GMm-HFS",586		.matches = {587			DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),588			DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),589		},590	},591	{592		.callback = intel_no_lvds_dmi_callback,593		.ident = "AOpen i45GMx-I",594		.matches = {595			DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),596			DMI_MATCH(DMI_BOARD_NAME, "i45GMx-I"),597		},598	},599	{600		.callback = intel_no_lvds_dmi_callback,601		.ident = "Aopen i945GTt-VFA",602		.matches = {603			DMI_MATCH(DMI_PRODUCT_VERSION, "AO00001JW"),604		},605	},606	{607		.callback = intel_no_lvds_dmi_callback,608		.ident = "Clientron U800",609		.matches = {610			DMI_MATCH(DMI_SYS_VENDOR, "Clientron"),611			DMI_MATCH(DMI_PRODUCT_NAME, "U800"),612		},613	},614	{615		.callback = intel_no_lvds_dmi_callback,616		.ident = "Clientron E830",617		.matches = {618			DMI_MATCH(DMI_SYS_VENDOR, "Clientron"),619			DMI_MATCH(DMI_PRODUCT_NAME, "E830"),620		},621	},622	{623		.callback = intel_no_lvds_dmi_callback,624		.ident = "Asus EeeBox PC EB1007",625		.matches = {626			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."),627			DMI_MATCH(DMI_PRODUCT_NAME, "EB1007"),628		},629	},630	{631		.callback = intel_no_lvds_dmi_callback,632		.ident = "Asus AT5NM10T-I",633		.matches = {634			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),635			DMI_MATCH(DMI_BOARD_NAME, "AT5NM10T-I"),636		},637	},638	{639		.callback = intel_no_lvds_dmi_callback,640		.ident = "Hewlett-Packard HP t5740",641		.matches = {642			DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),643			DMI_MATCH(DMI_PRODUCT_NAME, " t5740"),644		},645	},646	{647		.callback = intel_no_lvds_dmi_callback,648		.ident = "Hewlett-Packard t5745",649		.matches = {650			DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),651			DMI_MATCH(DMI_PRODUCT_NAME, "hp t5745"),652		},653	},654	{655		.callback = intel_no_lvds_dmi_callback,656		.ident = "Hewlett-Packard st5747",657		.matches = {658			DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),659			DMI_MATCH(DMI_PRODUCT_NAME, "hp st5747"),660		},661	},662	{663		.callback = intel_no_lvds_dmi_callback,664		.ident = "MSI Wind Box DC500",665		.matches = {666			DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),667			DMI_MATCH(DMI_BOARD_NAME, "MS-7469"),668		},669	},670	{671		.callback = intel_no_lvds_dmi_callback,672		.ident = "Gigabyte GA-D525TUD",673		.matches = {674			DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),675			DMI_MATCH(DMI_BOARD_NAME, "D525TUD"),676		},677	},678	{679		.callback = intel_no_lvds_dmi_callback,680		.ident = "Supermicro X7SPA-H",681		.matches = {682			DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),683			DMI_MATCH(DMI_PRODUCT_NAME, "X7SPA-H"),684		},685	},686	{687		.callback = intel_no_lvds_dmi_callback,688		.ident = "Fujitsu Esprimo Q900",689		.matches = {690			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),691			DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Q900"),692		},693	},694	{695		.callback = intel_no_lvds_dmi_callback,696		.ident = "Intel D410PT",697		.matches = {698			DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),699			DMI_MATCH(DMI_BOARD_NAME, "D410PT"),700		},701	},702	{703		.callback = intel_no_lvds_dmi_callback,704		.ident = "Intel D425KT",705		.matches = {706			DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),707			DMI_EXACT_MATCH(DMI_BOARD_NAME, "D425KT"),708		},709	},710	{711		.callback = intel_no_lvds_dmi_callback,712		.ident = "Intel D510MO",713		.matches = {714			DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),715			DMI_EXACT_MATCH(DMI_BOARD_NAME, "D510MO"),716		},717	},718	{719		.callback = intel_no_lvds_dmi_callback,720		.ident = "Intel D525MW",721		.matches = {722			DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),723			DMI_EXACT_MATCH(DMI_BOARD_NAME, "D525MW"),724		},725	},726	{727		.callback = intel_no_lvds_dmi_callback,728		.ident = "Radiant P845",729		.matches = {730			DMI_MATCH(DMI_SYS_VENDOR, "Radiant Systems Inc"),731			DMI_MATCH(DMI_PRODUCT_NAME, "P845"),732		},733	},734 735	{ }	/* terminating entry */736};737 738static int intel_dual_link_lvds_callback(const struct dmi_system_id *id)739{740	DRM_INFO("Forcing lvds to dual link mode on %s\n", id->ident);741	return 1;742}743 744static const struct dmi_system_id intel_dual_link_lvds[] = {745	{746		.callback = intel_dual_link_lvds_callback,747		.ident = "Apple MacBook Pro 15\" (2010)",748		.matches = {749			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),750			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro6,2"),751		},752	},753	{754		.callback = intel_dual_link_lvds_callback,755		.ident = "Apple MacBook Pro 15\" (2011)",756		.matches = {757			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),758			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro8,2"),759		},760	},761	{762		.callback = intel_dual_link_lvds_callback,763		.ident = "Apple MacBook Pro 15\" (2012)",764		.matches = {765			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),766			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro9,1"),767		},768	},769	{ }	/* terminating entry */770};771 772struct intel_encoder *intel_get_lvds_encoder(struct drm_i915_private *i915)773{774	struct intel_encoder *encoder;775 776	for_each_intel_encoder(&i915->drm, encoder) {777		if (encoder->type == INTEL_OUTPUT_LVDS)778			return encoder;779	}780 781	return NULL;782}783 784bool intel_is_dual_link_lvds(struct drm_i915_private *i915)785{786	struct intel_encoder *encoder = intel_get_lvds_encoder(i915);787 788	return encoder && to_lvds_encoder(encoder)->is_dual_link;789}790 791static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder)792{793	struct drm_i915_private *i915 = to_i915(lvds_encoder->base.base.dev);794	struct intel_connector *connector = lvds_encoder->attached_connector;795	const struct drm_display_mode *fixed_mode =796		intel_panel_preferred_fixed_mode(connector);797	unsigned int val;798 799	/* use the module option value if specified */800	if (i915->display.params.lvds_channel_mode > 0)801		return i915->display.params.lvds_channel_mode == 2;802 803	/* single channel LVDS is limited to 112 MHz */804	if (fixed_mode->clock > 112999)805		return true;806 807	if (dmi_check_system(intel_dual_link_lvds))808		return true;809 810	/*811	 * BIOS should set the proper LVDS register value at boot, but812	 * in reality, it doesn't set the value when the lid is closed;813	 * we need to check "the value to be set" in VBT when LVDS814	 * register is uninitialized.815	 */816	val = intel_de_read(i915, lvds_encoder->reg);817	if (HAS_PCH_CPT(i915))818		val &= ~(LVDS_DETECTED | LVDS_PIPE_SEL_MASK_CPT);819	else820		val &= ~(LVDS_DETECTED | LVDS_PIPE_SEL_MASK);821	if (val == 0)822		val = connector->panel.vbt.bios_lvds_val;823 824	return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP;825}826 827static void intel_lvds_add_properties(struct drm_connector *connector)828{829	intel_attach_scaling_mode_property(connector);830}831 832/**833 * intel_lvds_init - setup LVDS connectors on this device834 * @i915: i915 device835 *836 * Create the connector, register the LVDS DDC bus, and try to figure out what837 * modes we can display on the LVDS panel (if present).838 */839void intel_lvds_init(struct drm_i915_private *i915)840{841	struct intel_display *display = &i915->display;842	struct intel_lvds_encoder *lvds_encoder;843	struct intel_connector *connector;844	const struct drm_edid *drm_edid;845	struct intel_encoder *encoder;846	i915_reg_t lvds_reg;847	u32 lvds;848	u8 ddc_pin;849 850	/* Skip init on machines we know falsely report LVDS */851	if (dmi_check_system(intel_no_lvds)) {852		drm_WARN(&i915->drm, !i915->display.vbt.int_lvds_support,853			 "Useless DMI match. Internal LVDS support disabled by VBT\n");854		return;855	}856 857	if (!i915->display.vbt.int_lvds_support) {858		drm_dbg_kms(&i915->drm,859			    "Internal LVDS support disabled by VBT\n");860		return;861	}862 863	if (HAS_PCH_SPLIT(i915))864		lvds_reg = PCH_LVDS;865	else866		lvds_reg = LVDS;867 868	lvds = intel_de_read(i915, lvds_reg);869 870	if (HAS_PCH_SPLIT(i915)) {871		if ((lvds & LVDS_DETECTED) == 0)872			return;873	}874 875	ddc_pin = GMBUS_PIN_PANEL;876	if (!intel_bios_is_lvds_present(display, &ddc_pin)) {877		if ((lvds & LVDS_PORT_EN) == 0) {878			drm_dbg_kms(&i915->drm,879				    "LVDS is not present in VBT\n");880			return;881		}882		drm_dbg_kms(&i915->drm,883			    "LVDS is not present in VBT, but enabled anyway\n");884	}885 886	lvds_encoder = kzalloc(sizeof(*lvds_encoder), GFP_KERNEL);887	if (!lvds_encoder)888		return;889 890	connector = intel_connector_alloc();891	if (!connector) {892		kfree(lvds_encoder);893		return;894	}895 896	lvds_encoder->attached_connector = connector;897	encoder = &lvds_encoder->base;898 899	drm_connector_init_with_ddc(&i915->drm, &connector->base,900				    &intel_lvds_connector_funcs,901				    DRM_MODE_CONNECTOR_LVDS,902				    intel_gmbus_get_adapter(i915, ddc_pin));903 904	drm_encoder_init(&i915->drm, &encoder->base, &intel_lvds_enc_funcs,905			 DRM_MODE_ENCODER_LVDS, "LVDS");906 907	encoder->enable = intel_enable_lvds;908	encoder->pre_enable = intel_pre_enable_lvds;909	encoder->compute_config = intel_lvds_compute_config;910	if (HAS_PCH_SPLIT(i915)) {911		encoder->disable = pch_disable_lvds;912		encoder->post_disable = pch_post_disable_lvds;913	} else {914		encoder->disable = gmch_disable_lvds;915	}916	encoder->get_hw_state = intel_lvds_get_hw_state;917	encoder->get_config = intel_lvds_get_config;918	encoder->update_pipe = intel_backlight_update;919	encoder->shutdown = intel_lvds_shutdown;920	connector->get_hw_state = intel_connector_get_hw_state;921 922	intel_connector_attach_encoder(connector, encoder);923 924	encoder->type = INTEL_OUTPUT_LVDS;925	encoder->power_domain = POWER_DOMAIN_PORT_OTHER;926	encoder->port = PORT_NONE;927	encoder->cloneable = 0;928	if (DISPLAY_VER(i915) < 4)929		encoder->pipe_mask = BIT(PIPE_B);930	else931		encoder->pipe_mask = ~0;932 933	drm_connector_helper_add(&connector->base, &intel_lvds_connector_helper_funcs);934	connector->base.display_info.subpixel_order = SubPixelHorizontalRGB;935 936	lvds_encoder->reg = lvds_reg;937 938	intel_lvds_add_properties(&connector->base);939 940	intel_lvds_pps_get_hw_state(i915, &lvds_encoder->init_pps);941	lvds_encoder->init_lvds_val = lvds;942 943	/*944	 * LVDS discovery:945	 * 1) check for EDID on DDC946	 * 2) check for VBT data947	 * 3) check to see if LVDS is already on948	 *    if none of the above, no panel949	 */950 951	/*952	 * Attempt to get the fixed panel mode from DDC.  Assume that the953	 * preferred mode is the right one.954	 */955	mutex_lock(&i915->drm.mode_config.mutex);956	if (vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC)957		drm_edid = drm_edid_read_switcheroo(&connector->base, connector->base.ddc);958	else959		drm_edid = drm_edid_read_ddc(&connector->base, connector->base.ddc);960	if (drm_edid) {961		if (drm_edid_connector_update(&connector->base, drm_edid) ||962		    !drm_edid_connector_add_modes(&connector->base)) {963			drm_edid_connector_update(&connector->base, NULL);964			drm_edid_free(drm_edid);965			drm_edid = ERR_PTR(-EINVAL);966		}967	} else {968		drm_edid = ERR_PTR(-ENOENT);969	}970	intel_bios_init_panel_late(display, &connector->panel, NULL,971				   IS_ERR(drm_edid) ? NULL : drm_edid);972 973	/* Try EDID first */974	intel_panel_add_edid_fixed_modes(connector, true);975 976	/* Failed to get EDID, what about VBT? */977	if (!intel_panel_preferred_fixed_mode(connector))978		intel_panel_add_vbt_lfp_fixed_mode(connector);979 980	/*981	 * If we didn't get a fixed mode from EDID or VBT, try checking982	 * if the panel is already turned on.  If so, assume that983	 * whatever is currently programmed is the correct mode.984	 */985	if (!intel_panel_preferred_fixed_mode(connector))986		intel_panel_add_encoder_fixed_mode(connector, encoder);987 988	mutex_unlock(&i915->drm.mode_config.mutex);989 990	/* If we still don't have a mode after all that, give up. */991	if (!intel_panel_preferred_fixed_mode(connector))992		goto failed;993 994	intel_panel_init(connector, drm_edid);995 996	intel_backlight_setup(connector, INVALID_PIPE);997 998	lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder);999	drm_dbg_kms(&i915->drm, "detected %s-link lvds configuration\n",1000		    lvds_encoder->is_dual_link ? "dual" : "single");1001 1002	lvds_encoder->a3_power = lvds & LVDS_A3_POWER_MASK;1003 1004	return;1005 1006failed:1007	drm_dbg_kms(&i915->drm, "No LVDS modes found, disabling.\n");1008	drm_connector_cleanup(&connector->base);1009	drm_encoder_cleanup(&encoder->base);1010	kfree(lvds_encoder);1011	intel_connector_free(connector);1012	return;1013}1014