brintos

brintos / linux-shallow public Read only

0
0
Text · 17.7 KiB · f3a4517 Raw
668 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright © 2006-2011 Intel Corporation4 *5 * Authors:6 *	Eric Anholt <eric@anholt.net>7 *	Dave Airlie <airlied@linux.ie>8 *	Jesse Barnes <jesse.barnes@intel.com>9 */10 11#include <linux/dmi.h>12#include <linux/i2c.h>13#include <linux/pm_runtime.h>14 15#include <drm/drm_crtc_helper.h>16#include <drm/drm_modeset_helper_vtables.h>17#include <drm/drm_simple_kms_helper.h>18 19#include "cdv_device.h"20#include "intel_bios.h"21#include "power.h"22#include "psb_drv.h"23#include "psb_intel_drv.h"24#include "psb_intel_reg.h"25 26/*27 * LVDS I2C backlight control macros28 */29#define BRIGHTNESS_MAX_LEVEL 10030#define BRIGHTNESS_MASK 0xFF31#define BLC_I2C_TYPE	0x0132#define BLC_PWM_TYPT	0x0233 34#define BLC_POLARITY_NORMAL 035#define BLC_POLARITY_INVERSE 136 37#define PSB_BLC_MAX_PWM_REG_FREQ       (0xFFFE)38#define PSB_BLC_MIN_PWM_REG_FREQ	(0x2)39#define PSB_BLC_PWM_PRECISION_FACTOR	(10)40#define PSB_BACKLIGHT_PWM_CTL_SHIFT	(16)41#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)42 43struct cdv_intel_lvds_priv {44	/**45	 * Saved LVDO output states46	 */47	uint32_t savePP_ON;48	uint32_t savePP_OFF;49	uint32_t saveLVDS;50	uint32_t savePP_CONTROL;51	uint32_t savePP_CYCLE;52	uint32_t savePFIT_CONTROL;53	uint32_t savePFIT_PGM_RATIOS;54	uint32_t saveBLC_PWM_CTL;55};56 57/*58 * Returns the maximum level of the backlight duty cycle field.59 */60static u32 cdv_intel_lvds_get_max_backlight(struct drm_device *dev)61{62	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);63	u32 retval;64 65	if (gma_power_begin(dev, false)) {66		retval = ((REG_READ(BLC_PWM_CTL) &67			  BACKLIGHT_MODULATION_FREQ_MASK) >>68			  BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;69 70		gma_power_end(dev);71	} else72		retval = ((dev_priv->regs.saveBLC_PWM_CTL &73			  BACKLIGHT_MODULATION_FREQ_MASK) >>74			  BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;75 76	return retval;77}78 79/*80 * Sets the backlight level.81 *82 * level backlight level, from 0 to cdv_intel_lvds_get_max_backlight().83 */84static void cdv_intel_lvds_set_backlight(struct drm_device *dev, int level)85{86	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);87	u32 blc_pwm_ctl;88 89	if (gma_power_begin(dev, false)) {90		blc_pwm_ctl =91			REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;92		REG_WRITE(BLC_PWM_CTL,93				(blc_pwm_ctl |94				(level << BACKLIGHT_DUTY_CYCLE_SHIFT)));95		gma_power_end(dev);96	} else {97		blc_pwm_ctl = dev_priv->regs.saveBLC_PWM_CTL &98				~BACKLIGHT_DUTY_CYCLE_MASK;99		dev_priv->regs.saveBLC_PWM_CTL = (blc_pwm_ctl |100					(level << BACKLIGHT_DUTY_CYCLE_SHIFT));101	}102}103 104/*105 * Sets the power state for the panel.106 */107static void cdv_intel_lvds_set_power(struct drm_device *dev,108				     struct drm_encoder *encoder, bool on)109{110	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);111	u32 pp_status;112 113	if (!gma_power_begin(dev, true))114		return;115 116	if (on) {117		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |118			  POWER_TARGET_ON);119		do {120			pp_status = REG_READ(PP_STATUS);121		} while ((pp_status & PP_ON) == 0);122 123		cdv_intel_lvds_set_backlight(dev,124				dev_priv->mode_dev.backlight_duty_cycle);125	} else {126		cdv_intel_lvds_set_backlight(dev, 0);127 128		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &129			  ~POWER_TARGET_ON);130		do {131			pp_status = REG_READ(PP_STATUS);132		} while (pp_status & PP_ON);133	}134	gma_power_end(dev);135}136 137static void cdv_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode)138{139	struct drm_device *dev = encoder->dev;140	if (mode == DRM_MODE_DPMS_ON)141		cdv_intel_lvds_set_power(dev, encoder, true);142	else143		cdv_intel_lvds_set_power(dev, encoder, false);144	/* XXX: We never power down the LVDS pairs. */145}146 147static void cdv_intel_lvds_save(struct drm_connector *connector)148{149}150 151static void cdv_intel_lvds_restore(struct drm_connector *connector)152{153}154 155static enum drm_mode_status cdv_intel_lvds_mode_valid(struct drm_connector *connector,156			      struct drm_display_mode *mode)157{158	struct drm_device *dev = connector->dev;159	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);160	struct drm_display_mode *fixed_mode =161					dev_priv->mode_dev.panel_fixed_mode;162 163	/* just in case */164	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)165		return MODE_NO_DBLESCAN;166 167	/* just in case */168	if (mode->flags & DRM_MODE_FLAG_INTERLACE)169		return MODE_NO_INTERLACE;170 171	if (fixed_mode) {172		if (mode->hdisplay > fixed_mode->hdisplay)173			return MODE_PANEL;174		if (mode->vdisplay > fixed_mode->vdisplay)175			return MODE_PANEL;176	}177	return MODE_OK;178}179 180static bool cdv_intel_lvds_mode_fixup(struct drm_encoder *encoder,181				  const struct drm_display_mode *mode,182				  struct drm_display_mode *adjusted_mode)183{184	struct drm_device *dev = encoder->dev;185	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);186	struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;187	struct drm_encoder *tmp_encoder;188	struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode;189 190	/* Should never happen!! */191	list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list,192			    head) {193		if (tmp_encoder != encoder194		    && tmp_encoder->crtc == encoder->crtc) {195			pr_err("Can't enable LVDS and another encoder on the same pipe\n");196			return false;197		}198	}199 200	/*201	 * If we have timings from the BIOS for the panel, put them in202	 * to the adjusted mode.  The CRTC will be set up for this mode,203	 * with the panel scaling set up to source from the H/VDisplay204	 * of the original mode.205	 */206	if (panel_fixed_mode != NULL) {207		adjusted_mode->hdisplay = panel_fixed_mode->hdisplay;208		adjusted_mode->hsync_start = panel_fixed_mode->hsync_start;209		adjusted_mode->hsync_end = panel_fixed_mode->hsync_end;210		adjusted_mode->htotal = panel_fixed_mode->htotal;211		adjusted_mode->vdisplay = panel_fixed_mode->vdisplay;212		adjusted_mode->vsync_start = panel_fixed_mode->vsync_start;213		adjusted_mode->vsync_end = panel_fixed_mode->vsync_end;214		adjusted_mode->vtotal = panel_fixed_mode->vtotal;215		adjusted_mode->clock = panel_fixed_mode->clock;216		drm_mode_set_crtcinfo(adjusted_mode,217				      CRTC_INTERLACE_HALVE_V);218	}219 220	/*221	 * XXX: It would be nice to support lower refresh rates on the222	 * panels to reduce power consumption, and perhaps match the223	 * user's requested refresh rate.224	 */225 226	return true;227}228 229static void cdv_intel_lvds_prepare(struct drm_encoder *encoder)230{231	struct drm_device *dev = encoder->dev;232	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);233	struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;234 235	if (!gma_power_begin(dev, true))236		return;237 238	mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);239	mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL &240					  BACKLIGHT_DUTY_CYCLE_MASK);241 242	cdv_intel_lvds_set_power(dev, encoder, false);243 244	gma_power_end(dev);245}246 247static void cdv_intel_lvds_commit(struct drm_encoder *encoder)248{249	struct drm_device *dev = encoder->dev;250	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);251	struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;252 253	if (mode_dev->backlight_duty_cycle == 0)254		mode_dev->backlight_duty_cycle =255		    cdv_intel_lvds_get_max_backlight(dev);256 257	cdv_intel_lvds_set_power(dev, encoder, true);258}259 260static void cdv_intel_lvds_mode_set(struct drm_encoder *encoder,261				struct drm_display_mode *mode,262				struct drm_display_mode *adjusted_mode)263{264	struct drm_device *dev = encoder->dev;265	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);266	struct gma_crtc *gma_crtc = to_gma_crtc(encoder->crtc);267	u32 pfit_control;268 269	/*270	 * The LVDS pin pair will already have been turned on in the271	 * cdv_intel_crtc_mode_set since it has a large impact on the DPLL272	 * settings.273	 */274 275	/*276	 * Enable automatic panel scaling so that non-native modes fill the277	 * screen.  Should be enabled before the pipe is enabled, according to278	 * register description and PRM.279	 */280	if (mode->hdisplay != adjusted_mode->hdisplay ||281	    mode->vdisplay != adjusted_mode->vdisplay)282		pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE |283				HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR |284				HORIZ_INTERP_BILINEAR);285	else286		pfit_control = 0;287 288	pfit_control |= gma_crtc->pipe << PFIT_PIPE_SHIFT;289 290	if (dev_priv->lvds_dither)291		pfit_control |= PANEL_8TO6_DITHER_ENABLE;292 293	REG_WRITE(PFIT_CONTROL, pfit_control);294}295 296/*297 * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.298 */299static int cdv_intel_lvds_get_modes(struct drm_connector *connector)300{301	struct drm_device *dev = connector->dev;302	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);303	struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;304	int ret;305 306	ret = psb_intel_ddc_get_modes(connector, connector->ddc);307 308	if (ret)309		return ret;310 311	if (mode_dev->panel_fixed_mode != NULL) {312		struct drm_display_mode *mode =313		    drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);314		if (!mode)315			return 0;316 317		drm_mode_probed_add(connector, mode);318		return 1;319	}320 321	return 0;322}323 324static void cdv_intel_lvds_destroy(struct drm_connector *connector)325{326	struct gma_connector *gma_connector = to_gma_connector(connector);327	struct gma_encoder *gma_encoder = gma_attached_encoder(connector);328 329	gma_i2c_destroy(to_gma_i2c_chan(connector->ddc));330	gma_i2c_destroy(gma_encoder->i2c_bus);331	drm_connector_cleanup(connector);332	kfree(gma_connector);333}334 335static int cdv_intel_lvds_set_property(struct drm_connector *connector,336				       struct drm_property *property,337				       uint64_t value)338{339	struct drm_encoder *encoder = connector->encoder;340 341	if (!strcmp(property->name, "scaling mode") && encoder) {342		struct gma_crtc *crtc = to_gma_crtc(encoder->crtc);343		uint64_t curValue;344 345		if (!crtc)346			return -1;347 348		switch (value) {349		case DRM_MODE_SCALE_FULLSCREEN:350			break;351		case DRM_MODE_SCALE_NO_SCALE:352			break;353		case DRM_MODE_SCALE_ASPECT:354			break;355		default:356			return -1;357		}358 359		if (drm_object_property_get_value(&connector->base,360						     property,361						     &curValue))362			return -1;363 364		if (curValue == value)365			return 0;366 367		if (drm_object_property_set_value(&connector->base,368							property,369							value))370			return -1;371 372		if (crtc->saved_mode.hdisplay != 0 &&373		    crtc->saved_mode.vdisplay != 0) {374			if (!drm_crtc_helper_set_mode(encoder->crtc,375						      &crtc->saved_mode,376						      encoder->crtc->x,377						      encoder->crtc->y,378						      encoder->crtc->primary->fb))379				return -1;380		}381	} else if (!strcmp(property->name, "backlight") && encoder) {382		if (drm_object_property_set_value(&connector->base,383							property,384							value))385			return -1;386		else387                        gma_backlight_set(encoder->dev, value);388	} else if (!strcmp(property->name, "DPMS") && encoder) {389		const struct drm_encoder_helper_funcs *helpers =390					encoder->helper_private;391		helpers->dpms(encoder, value);392	}393	return 0;394}395 396static const struct drm_encoder_helper_funcs397					cdv_intel_lvds_helper_funcs = {398	.dpms = cdv_intel_lvds_encoder_dpms,399	.mode_fixup = cdv_intel_lvds_mode_fixup,400	.prepare = cdv_intel_lvds_prepare,401	.mode_set = cdv_intel_lvds_mode_set,402	.commit = cdv_intel_lvds_commit,403};404 405static const struct drm_connector_helper_funcs406				cdv_intel_lvds_connector_helper_funcs = {407	.get_modes = cdv_intel_lvds_get_modes,408	.mode_valid = cdv_intel_lvds_mode_valid,409	.best_encoder = gma_best_encoder,410};411 412static const struct drm_connector_funcs cdv_intel_lvds_connector_funcs = {413	.dpms = drm_helper_connector_dpms,414	.fill_modes = drm_helper_probe_single_connector_modes,415	.set_property = cdv_intel_lvds_set_property,416	.destroy = cdv_intel_lvds_destroy,417};418 419/*420 * Enumerate the child dev array parsed from VBT to check whether421 * the LVDS is present.422 * If it is present, return 1.423 * If it is not present, return false.424 * If no child dev is parsed from VBT, it assumes that the LVDS is present.425 */426static bool lvds_is_present_in_vbt(struct drm_device *dev,427				   u8 *i2c_pin)428{429	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);430	int i;431 432	if (!dev_priv->child_dev_num)433		return true;434 435	for (i = 0; i < dev_priv->child_dev_num; i++) {436		struct child_device_config *child = dev_priv->child_dev + i;437 438		/* If the device type is not LFP, continue.439		 * We have to check both the new identifiers as well as the440		 * old for compatibility with some BIOSes.441		 */442		if (child->device_type != DEVICE_TYPE_INT_LFP &&443		    child->device_type != DEVICE_TYPE_LFP)444			continue;445 446		if (child->i2c_pin)447		    *i2c_pin = child->i2c_pin;448 449		/* However, we cannot trust the BIOS writers to populate450		 * the VBT correctly.  Since LVDS requires additional451		 * information from AIM blocks, a non-zero addin offset is452		 * a good indicator that the LVDS is actually present.453		 */454		if (child->addin_offset)455			return true;456 457		/* But even then some BIOS writers perform some black magic458		 * and instantiate the device without reference to any459		 * additional data.  Trust that if the VBT was written into460		 * the OpRegion then they have validated the LVDS's existence.461		 */462		if (dev_priv->opregion.vbt)463			return true;464	}465 466	return false;467}468 469/**470 * cdv_intel_lvds_init - setup LVDS connectors on this device471 * @dev: drm device472 * @mode_dev: PSB mode device473 *474 * Create the connector, register the LVDS DDC bus, and try to figure out what475 * modes we can display on the LVDS panel (if present).476 */477void cdv_intel_lvds_init(struct drm_device *dev,478		     struct psb_intel_mode_device *mode_dev)479{480	struct gma_encoder *gma_encoder;481	struct gma_connector *gma_connector;482	struct cdv_intel_lvds_priv *lvds_priv;483	struct drm_connector *connector;484	struct drm_encoder *encoder;485	struct drm_display_mode *scan;486	struct drm_crtc *crtc;487	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);488	struct gma_i2c_chan *ddc_bus;489	u32 lvds;490	int pipe;491	int ret;492	u8 pin;493 494	if (!dev_priv->lvds_enabled_in_vbt)495		return;496 497	pin = GMBUS_PORT_PANEL;498	if (!lvds_is_present_in_vbt(dev, &pin)) {499		DRM_DEBUG_KMS("LVDS is not present in VBT\n");500		return;501	}502 503	gma_encoder = kzalloc(sizeof(struct gma_encoder),504				    GFP_KERNEL);505	if (!gma_encoder)506		return;507 508	gma_connector = kzalloc(sizeof(struct gma_connector),509				      GFP_KERNEL);510	if (!gma_connector)511		goto err_free_encoder;512 513	lvds_priv = kzalloc(sizeof(struct cdv_intel_lvds_priv), GFP_KERNEL);514	if (!lvds_priv)515		goto err_free_connector;516 517	gma_encoder->dev_priv = lvds_priv;518 519	connector = &gma_connector->base;520	gma_connector->save = cdv_intel_lvds_save;521	gma_connector->restore = cdv_intel_lvds_restore;522	encoder = &gma_encoder->base;523 524	/* Set up the DDC bus. */525	ddc_bus = gma_i2c_create(dev, GPIOC, "LVDSDDC_C");526	if (!ddc_bus) {527		dev_printk(KERN_ERR, dev->dev,528			   "DDC bus registration " "failed.\n");529		goto err_free_lvds_priv;530	}531 532	ret = drm_connector_init_with_ddc(dev, connector,533					  &cdv_intel_lvds_connector_funcs,534					  DRM_MODE_CONNECTOR_LVDS,535					  &ddc_bus->base);536	if (ret)537		goto err_destroy_ddc;538 539	ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_LVDS);540	if (ret)541		goto err_connector_cleanup;542 543	gma_connector_attach_encoder(gma_connector, gma_encoder);544	gma_encoder->type = INTEL_OUTPUT_LVDS;545 546	drm_encoder_helper_add(encoder, &cdv_intel_lvds_helper_funcs);547	drm_connector_helper_add(connector,548				 &cdv_intel_lvds_connector_helper_funcs);549	connector->display_info.subpixel_order = SubPixelHorizontalRGB;550	connector->interlace_allowed = false;551	connector->doublescan_allowed = false;552 553	/*Attach connector properties*/554	drm_object_attach_property(&connector->base,555				      dev->mode_config.scaling_mode_property,556				      DRM_MODE_SCALE_FULLSCREEN);557	drm_object_attach_property(&connector->base,558				      dev_priv->backlight_property,559				      BRIGHTNESS_MAX_LEVEL);560 561	/**562	 * Set up I2C bus563	 * FIXME: distroy i2c_bus when exit564	 */565	gma_encoder->i2c_bus = gma_i2c_create(dev, GPIOB, "LVDSBLC_B");566	if (!gma_encoder->i2c_bus) {567		dev_printk(KERN_ERR,568			dev->dev, "I2C bus registration failed.\n");569		goto err_encoder_cleanup;570	}571	gma_encoder->i2c_bus->target_addr = 0x2C;572	dev_priv->lvds_i2c_bus = gma_encoder->i2c_bus;573 574	/*575	 * LVDS discovery:576	 * 1) check for EDID on DDC577	 * 2) check for VBT data578	 * 3) check to see if LVDS is already on579	 *    if none of the above, no panel580	 * 4) make sure lid is open581	 *    if closed, act like it's not there for now582	 */583 584	/*585	 * Attempt to get the fixed panel mode from DDC.  Assume that the586	 * preferred mode is the right one.587	 */588	mutex_lock(&dev->mode_config.mutex);589	psb_intel_ddc_get_modes(connector, &ddc_bus->base);590 591	list_for_each_entry(scan, &connector->probed_modes, head) {592		if (scan->type & DRM_MODE_TYPE_PREFERRED) {593			mode_dev->panel_fixed_mode =594			    drm_mode_duplicate(dev, scan);595			goto out;	/* FIXME: check for quirks */596		}597	}598 599	/* Failed to get EDID, what about VBT? do we need this?*/600	if (dev_priv->lfp_lvds_vbt_mode) {601		mode_dev->panel_fixed_mode =602			drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);603		if (mode_dev->panel_fixed_mode) {604			mode_dev->panel_fixed_mode->type |=605				DRM_MODE_TYPE_PREFERRED;606			goto out;	/* FIXME: check for quirks */607		}608	}609	/*610	 * If we didn't get EDID, try checking if the panel is already turned611	 * on.	If so, assume that whatever is currently programmed is the612	 * correct mode.613	 */614	lvds = REG_READ(LVDS);615	pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;616	crtc = psb_intel_get_crtc_from_pipe(dev, pipe);617 618	if (crtc && (lvds & LVDS_PORT_EN)) {619		mode_dev->panel_fixed_mode =620		    cdv_intel_crtc_mode_get(dev, crtc);621		if (mode_dev->panel_fixed_mode) {622			mode_dev->panel_fixed_mode->type |=623			    DRM_MODE_TYPE_PREFERRED;624			goto out;	/* FIXME: check for quirks */625		}626	}627 628	/* If we still don't have a mode after all that, give up. */629	if (!mode_dev->panel_fixed_mode) {630		DRM_DEBUG631			("Found no modes on the lvds, ignoring the LVDS\n");632		goto err_unlock;633	}634 635	/* setup PWM */636	{637		u32 pwm;638 639		pwm = REG_READ(BLC_PWM_CTL2);640		if (pipe == 1)641			pwm |= PWM_PIPE_B;642		else643			pwm &= ~PWM_PIPE_B;644		pwm |= PWM_ENABLE;645		REG_WRITE(BLC_PWM_CTL2, pwm);646	}647 648out:649	mutex_unlock(&dev->mode_config.mutex);650	return;651 652err_unlock:653	mutex_unlock(&dev->mode_config.mutex);654	gma_i2c_destroy(gma_encoder->i2c_bus);655err_encoder_cleanup:656	drm_encoder_cleanup(encoder);657err_connector_cleanup:658	drm_connector_cleanup(connector);659err_destroy_ddc:660	gma_i2c_destroy(ddc_bus);661err_free_lvds_priv:662	kfree(lvds_priv);663err_free_connector:664	kfree(gma_connector);665err_free_encoder:666	kfree(gma_encoder);667}668