brintos

brintos / linux-shallow public Read only

0
0
Text · 18.2 KiB · de8ccfe Raw
668 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright © 2009 Intel Corporation4 */5 6#include <linux/delay.h>7#include <linux/i2c.h>8#include <linux/pm_runtime.h>9 10#include <drm/drm_fourcc.h>11#include <drm/drm_framebuffer.h>12#include <drm/drm_modeset_helper_vtables.h>13 14#include "framebuffer.h"15#include "gem.h"16#include "gma_display.h"17#include "power.h"18#include "psb_drv.h"19#include "psb_intel_drv.h"20#include "psb_intel_reg.h"21 22#define MRST_LIMIT_LVDS_100L	023#define MRST_LIMIT_LVDS_83	124#define MRST_LIMIT_LVDS_100	225#define MRST_LIMIT_SDVO		326 27#define MRST_DOT_MIN		  1975028#define MRST_DOT_MAX		  12000029#define MRST_M_MIN_100L		    2030#define MRST_M_MIN_100		    1031#define MRST_M_MIN_83		    1232#define MRST_M_MAX_100L		    3433#define MRST_M_MAX_100		    1734#define MRST_M_MAX_83		    2035#define MRST_P1_MIN		    236#define MRST_P1_MAX_0		    737#define MRST_P1_MAX_1		    838 39static bool mrst_lvds_find_best_pll(const struct gma_limit_t *limit,40				    struct drm_crtc *crtc, int target,41				    int refclk, struct gma_clock_t *best_clock);42 43static bool mrst_sdvo_find_best_pll(const struct gma_limit_t *limit,44				    struct drm_crtc *crtc, int target,45				    int refclk, struct gma_clock_t *best_clock);46 47static const struct gma_limit_t mrst_limits[] = {48	{			/* MRST_LIMIT_LVDS_100L */49	 .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX},50	 .m = {.min = MRST_M_MIN_100L, .max = MRST_M_MAX_100L},51	 .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_1},52	 .find_pll = mrst_lvds_find_best_pll,53	 },54	{			/* MRST_LIMIT_LVDS_83L */55	 .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX},56	 .m = {.min = MRST_M_MIN_83, .max = MRST_M_MAX_83},57	 .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_0},58	 .find_pll = mrst_lvds_find_best_pll,59	 },60	{			/* MRST_LIMIT_LVDS_100 */61	 .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX},62	 .m = {.min = MRST_M_MIN_100, .max = MRST_M_MAX_100},63	 .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_1},64	 .find_pll = mrst_lvds_find_best_pll,65	 },66	{			/* MRST_LIMIT_SDVO */67	 .vco = {.min = 1400000, .max = 2800000},68	 .n = {.min = 3, .max = 7},69	 .m = {.min = 80, .max = 137},70	 .p1 = {.min = 1, .max = 2},71	 .p2 = {.dot_limit = 200000, .p2_slow = 10, .p2_fast = 10},72	 .find_pll = mrst_sdvo_find_best_pll,73	 },74};75 76#define MRST_M_MIN	    1077static const u32 oaktrail_m_converts[] = {78	0x2B, 0x15, 0x2A, 0x35, 0x1A, 0x0D, 0x26, 0x33, 0x19, 0x2C,79	0x36, 0x3B, 0x1D, 0x2E, 0x37, 0x1B, 0x2D, 0x16, 0x0B, 0x25,80	0x12, 0x09, 0x24, 0x32, 0x39, 0x1c,81};82 83static const struct gma_limit_t *mrst_limit(struct drm_crtc *crtc,84					    int refclk)85{86	const struct gma_limit_t *limit = NULL;87	struct drm_device *dev = crtc->dev;88	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);89 90	if (gma_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)91	    || gma_pipe_has_type(crtc, INTEL_OUTPUT_MIPI)) {92		switch (dev_priv->core_freq) {93		case 100:94			limit = &mrst_limits[MRST_LIMIT_LVDS_100L];95			break;96		case 166:97			limit = &mrst_limits[MRST_LIMIT_LVDS_83];98			break;99		case 200:100			limit = &mrst_limits[MRST_LIMIT_LVDS_100];101			break;102		}103	} else if (gma_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) {104		limit = &mrst_limits[MRST_LIMIT_SDVO];105	} else {106		limit = NULL;107		dev_err(dev->dev, "mrst_limit Wrong display type.\n");108	}109 110	return limit;111}112 113/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */114static void mrst_lvds_clock(int refclk, struct gma_clock_t *clock)115{116	clock->dot = (refclk * clock->m) / (14 * clock->p1);117}118 119static void mrst_print_pll(struct gma_clock_t *clock)120{121	DRM_DEBUG_DRIVER("dotclock=%d,  m=%d, m1=%d, m2=%d, n=%d, p1=%d, p2=%d\n",122			 clock->dot, clock->m, clock->m1, clock->m2, clock->n,123			 clock->p1, clock->p2);124}125 126static bool mrst_sdvo_find_best_pll(const struct gma_limit_t *limit,127				    struct drm_crtc *crtc, int target,128				    int refclk, struct gma_clock_t *best_clock)129{130	struct gma_clock_t clock;131	u32 target_vco, actual_freq;132	s32 freq_error, min_error = 100000;133 134	memset(best_clock, 0, sizeof(*best_clock));135	memset(&clock, 0, sizeof(clock));136 137	for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) {138		for (clock.n = limit->n.min; clock.n <= limit->n.max;139		     clock.n++) {140			for (clock.p1 = limit->p1.min;141			     clock.p1 <= limit->p1.max; clock.p1++) {142				/* p2 value always stored in p2_slow on SDVO */143				clock.p = clock.p1 * limit->p2.p2_slow;144				target_vco = target * clock.p;145 146				/* VCO will increase at this point so break */147				if (target_vco > limit->vco.max)148					break;149 150				if (target_vco < limit->vco.min)151					continue;152 153				actual_freq = (refclk * clock.m) /154					      (clock.n * clock.p);155				freq_error = 10000 -156					     ((target * 10000) / actual_freq);157 158				if (freq_error < -min_error) {159					/* freq_error will start to decrease at160					   this point so break */161					break;162				}163 164				if (freq_error < 0)165					freq_error = -freq_error;166 167				if (freq_error < min_error) {168					min_error = freq_error;169					*best_clock = clock;170				}171			}172		}173		if (min_error == 0)174			break;175	}176 177	return min_error == 0;178}179 180/*181 * Returns a set of divisors for the desired target clock with the given refclk,182 * or FALSE.  Divisor values are the actual divisors for183 */184static bool mrst_lvds_find_best_pll(const struct gma_limit_t *limit,185				    struct drm_crtc *crtc, int target,186				    int refclk, struct gma_clock_t *best_clock)187{188	struct gma_clock_t clock;189	int err = target;190 191	memset(best_clock, 0, sizeof(*best_clock));192	memset(&clock, 0, sizeof(clock));193 194	for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) {195		for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max;196		     clock.p1++) {197			int this_err;198 199			mrst_lvds_clock(refclk, &clock);200 201			this_err = abs(clock.dot - target);202			if (this_err < err) {203				*best_clock = clock;204				err = this_err;205			}206		}207	}208	return err != target;209}210 211/*212 * Sets the power management mode of the pipe and plane.213 *214 * This code should probably grow support for turning the cursor off and back215 * on appropriately at the same time as we're turning the pipe off/on.216 */217static void oaktrail_crtc_dpms(struct drm_crtc *crtc, int mode)218{219	struct drm_device *dev = crtc->dev;220	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);221	struct gma_crtc *gma_crtc = to_gma_crtc(crtc);222	int pipe = gma_crtc->pipe;223	const struct psb_offset *map = &dev_priv->regmap[pipe];224	u32 temp;225	int i;226	int need_aux = gma_pipe_has_type(crtc, INTEL_OUTPUT_SDVO) ? 1 : 0;227 228	if (gma_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) {229		oaktrail_crtc_hdmi_dpms(crtc, mode);230		return;231	}232 233	if (!gma_power_begin(dev, true))234		return;235 236	/* XXX: When our outputs are all unaware of DPMS modes other than off237	 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.238	 */239	switch (mode) {240	case DRM_MODE_DPMS_ON:241	case DRM_MODE_DPMS_STANDBY:242	case DRM_MODE_DPMS_SUSPEND:243		for (i = 0; i <= need_aux; i++) {244			/* Enable the DPLL */245			temp = REG_READ_WITH_AUX(map->dpll, i);246			if ((temp & DPLL_VCO_ENABLE) == 0) {247				REG_WRITE_WITH_AUX(map->dpll, temp, i);248				REG_READ_WITH_AUX(map->dpll, i);249				/* Wait for the clocks to stabilize. */250				udelay(150);251				REG_WRITE_WITH_AUX(map->dpll,252						   temp | DPLL_VCO_ENABLE, i);253				REG_READ_WITH_AUX(map->dpll, i);254				/* Wait for the clocks to stabilize. */255				udelay(150);256				REG_WRITE_WITH_AUX(map->dpll,257						   temp | DPLL_VCO_ENABLE, i);258				REG_READ_WITH_AUX(map->dpll, i);259				/* Wait for the clocks to stabilize. */260				udelay(150);261			}262 263			/* Enable the pipe */264			temp = REG_READ_WITH_AUX(map->conf, i);265			if ((temp & PIPEACONF_ENABLE) == 0) {266				REG_WRITE_WITH_AUX(map->conf,267						   temp | PIPEACONF_ENABLE, i);268			}269 270			/* Enable the plane */271			temp = REG_READ_WITH_AUX(map->cntr, i);272			if ((temp & DISPLAY_PLANE_ENABLE) == 0) {273				REG_WRITE_WITH_AUX(map->cntr,274						   temp | DISPLAY_PLANE_ENABLE,275						   i);276				/* Flush the plane changes */277				REG_WRITE_WITH_AUX(map->base,278					REG_READ_WITH_AUX(map->base, i), i);279			}280 281		}282		gma_crtc_load_lut(crtc);283 284		/* Give the overlay scaler a chance to enable285		   if it's on this pipe */286		/* psb_intel_crtc_dpms_video(crtc, true); TODO */287		break;288	case DRM_MODE_DPMS_OFF:289		/* Give the overlay scaler a chance to disable290		 * if it's on this pipe */291		/* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */292 293		for (i = 0; i <= need_aux; i++) {294			/* Disable the VGA plane that we never use */295			REG_WRITE_WITH_AUX(VGACNTRL, VGA_DISP_DISABLE, i);296			/* Disable display plane */297			temp = REG_READ_WITH_AUX(map->cntr, i);298			if ((temp & DISPLAY_PLANE_ENABLE) != 0) {299				REG_WRITE_WITH_AUX(map->cntr,300					temp & ~DISPLAY_PLANE_ENABLE, i);301				/* Flush the plane changes */302				REG_WRITE_WITH_AUX(map->base,303						   REG_READ(map->base), i);304				REG_READ_WITH_AUX(map->base, i);305			}306 307			/* Next, disable display pipes */308			temp = REG_READ_WITH_AUX(map->conf, i);309			if ((temp & PIPEACONF_ENABLE) != 0) {310				REG_WRITE_WITH_AUX(map->conf,311						   temp & ~PIPEACONF_ENABLE, i);312				REG_READ_WITH_AUX(map->conf, i);313			}314			/* Wait for the pipe disable to take effect. */315			gma_wait_for_vblank(dev);316 317			temp = REG_READ_WITH_AUX(map->dpll, i);318			if ((temp & DPLL_VCO_ENABLE) != 0) {319				REG_WRITE_WITH_AUX(map->dpll,320						   temp & ~DPLL_VCO_ENABLE, i);321				REG_READ_WITH_AUX(map->dpll, i);322			}323 324			/* Wait for the clocks to turn off. */325			udelay(150);326		}327		break;328	}329 330	/* Set FIFO Watermarks (values taken from EMGD) */331	REG_WRITE(DSPARB, 0x3f80);332	REG_WRITE(DSPFW1, 0x3f8f0404);333	REG_WRITE(DSPFW2, 0x04040f04);334	REG_WRITE(DSPFW3, 0x0);335	REG_WRITE(DSPFW4, 0x04040404);336	REG_WRITE(DSPFW5, 0x04040404);337	REG_WRITE(DSPFW6, 0x78);338	REG_WRITE(DSPCHICKENBIT, REG_READ(DSPCHICKENBIT) | 0xc040);339 340	gma_power_end(dev);341}342 343/*344 * Return the pipe currently connected to the panel fitter,345 * or -1 if the panel fitter is not present or not in use346 */347static int oaktrail_panel_fitter_pipe(struct drm_device *dev)348{349	u32 pfit_control;350 351	pfit_control = REG_READ(PFIT_CONTROL);352 353	/* See if the panel fitter is in use */354	if ((pfit_control & PFIT_ENABLE) == 0)355		return -1;356	return (pfit_control >> 29) & 3;357}358 359static int oaktrail_crtc_mode_set(struct drm_crtc *crtc,360			      struct drm_display_mode *mode,361			      struct drm_display_mode *adjusted_mode,362			      int x, int y,363			      struct drm_framebuffer *old_fb)364{365	struct drm_device *dev = crtc->dev;366	struct gma_crtc *gma_crtc = to_gma_crtc(crtc);367	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);368	int pipe = gma_crtc->pipe;369	const struct psb_offset *map = &dev_priv->regmap[pipe];370	int refclk = 0;371	struct gma_clock_t clock;372	const struct gma_limit_t *limit;373	u32 dpll = 0, fp = 0, dspcntr, pipeconf;374	bool ok, is_sdvo = false;375	bool is_lvds = false;376	bool is_mipi = false;377	struct gma_encoder *gma_encoder = NULL;378	uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN;379	struct drm_connector_list_iter conn_iter;380	struct drm_connector *connector;381	int i;382	int need_aux = gma_pipe_has_type(crtc, INTEL_OUTPUT_SDVO) ? 1 : 0;383 384	if (gma_pipe_has_type(crtc, INTEL_OUTPUT_HDMI))385		return oaktrail_crtc_hdmi_mode_set(crtc, mode, adjusted_mode, x, y, old_fb);386 387	if (!gma_power_begin(dev, true))388		return 0;389 390	drm_mode_copy(&gma_crtc->saved_mode, mode);391	drm_mode_copy(&gma_crtc->saved_adjusted_mode, adjusted_mode);392 393	drm_connector_list_iter_begin(dev, &conn_iter);394	drm_for_each_connector_iter(connector, &conn_iter) {395		if (!connector->encoder || connector->encoder->crtc != crtc)396			continue;397 398		gma_encoder = gma_attached_encoder(connector);399 400		switch (gma_encoder->type) {401		case INTEL_OUTPUT_LVDS:402			is_lvds = true;403			break;404		case INTEL_OUTPUT_SDVO:405			is_sdvo = true;406			break;407		case INTEL_OUTPUT_MIPI:408			is_mipi = true;409			break;410		}411 412		break;413	}414 415	if (gma_encoder)416		drm_object_property_get_value(&connector->base,417			dev->mode_config.scaling_mode_property, &scalingType);418 419	drm_connector_list_iter_end(&conn_iter);420 421	/* Disable the VGA plane that we never use */422	for (i = 0; i <= need_aux; i++)423		REG_WRITE_WITH_AUX(VGACNTRL, VGA_DISP_DISABLE, i);424 425	/* Disable the panel fitter if it was on our pipe */426	if (oaktrail_panel_fitter_pipe(dev) == pipe)427		REG_WRITE(PFIT_CONTROL, 0);428 429	for (i = 0; i <= need_aux; i++) {430		REG_WRITE_WITH_AUX(map->src, ((mode->crtc_hdisplay - 1) << 16) |431					     (mode->crtc_vdisplay - 1), i);432	}433 434	if (scalingType == DRM_MODE_SCALE_NO_SCALE) {435		/* Moorestown doesn't have register support for centering so436		 * we need to mess with the h/vblank and h/vsync start and437		 * ends to get centering */438		int offsetX = 0, offsetY = 0;439 440		offsetX = (adjusted_mode->crtc_hdisplay -441			   mode->crtc_hdisplay) / 2;442		offsetY = (adjusted_mode->crtc_vdisplay -443			   mode->crtc_vdisplay) / 2;444 445		for (i = 0; i <= need_aux; i++) {446			REG_WRITE_WITH_AUX(map->htotal, (mode->crtc_hdisplay - 1) |447				((adjusted_mode->crtc_htotal - 1) << 16), i);448			REG_WRITE_WITH_AUX(map->vtotal, (mode->crtc_vdisplay - 1) |449				((adjusted_mode->crtc_vtotal - 1) << 16), i);450			REG_WRITE_WITH_AUX(map->hblank,451				(adjusted_mode->crtc_hblank_start - offsetX - 1) |452				((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16), i);453			REG_WRITE_WITH_AUX(map->hsync,454				(adjusted_mode->crtc_hsync_start - offsetX - 1) |455				((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16), i);456			REG_WRITE_WITH_AUX(map->vblank,457				(adjusted_mode->crtc_vblank_start - offsetY - 1) |458				((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16), i);459			REG_WRITE_WITH_AUX(map->vsync,460				(adjusted_mode->crtc_vsync_start - offsetY - 1) |461				((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16), i);462		}463	} else {464		for (i = 0; i <= need_aux; i++) {465			REG_WRITE_WITH_AUX(map->htotal, (adjusted_mode->crtc_hdisplay - 1) |466				((adjusted_mode->crtc_htotal - 1) << 16), i);467			REG_WRITE_WITH_AUX(map->vtotal, (adjusted_mode->crtc_vdisplay - 1) |468				((adjusted_mode->crtc_vtotal - 1) << 16), i);469			REG_WRITE_WITH_AUX(map->hblank, (adjusted_mode->crtc_hblank_start - 1) |470				((adjusted_mode->crtc_hblank_end - 1) << 16), i);471			REG_WRITE_WITH_AUX(map->hsync, (adjusted_mode->crtc_hsync_start - 1) |472				((adjusted_mode->crtc_hsync_end - 1) << 16), i);473			REG_WRITE_WITH_AUX(map->vblank, (adjusted_mode->crtc_vblank_start - 1) |474				((adjusted_mode->crtc_vblank_end - 1) << 16), i);475			REG_WRITE_WITH_AUX(map->vsync, (adjusted_mode->crtc_vsync_start - 1) |476				((adjusted_mode->crtc_vsync_end - 1) << 16), i);477		}478	}479 480	/* Flush the plane changes */481	{482		const struct drm_crtc_helper_funcs *crtc_funcs =483		    crtc->helper_private;484		crtc_funcs->mode_set_base(crtc, x, y, old_fb);485	}486 487	/* setup pipeconf */488	pipeconf = REG_READ(map->conf);489 490	/* Set up the display plane register */491	dspcntr = REG_READ(map->cntr);492	dspcntr |= DISPPLANE_GAMMA_ENABLE;493 494	if (pipe == 0)495		dspcntr |= DISPPLANE_SEL_PIPE_A;496	else497		dspcntr |= DISPPLANE_SEL_PIPE_B;498 499	if (is_mipi)500		goto oaktrail_crtc_mode_set_exit;501 502 503	dpll = 0;		/*BIT16 = 0 for 100MHz reference */504 505	refclk = is_sdvo ? 96000 : dev_priv->core_freq * 1000;506	limit = mrst_limit(crtc, refclk);507	ok = limit->find_pll(limit, crtc, adjusted_mode->clock,508			     refclk, &clock);509 510	if (is_sdvo) {511		/* Convert calculated values to register values */512		clock.p1 = (1L << (clock.p1 - 1));513		clock.m -= 2;514		clock.n = (1L << (clock.n - 1));515	}516 517	if (!ok)518		DRM_ERROR("Failed to find proper PLL settings");519 520	mrst_print_pll(&clock);521 522	if (is_sdvo)523		fp = clock.n << 16 | clock.m;524	else525		fp = oaktrail_m_converts[(clock.m - MRST_M_MIN)] << 8;526 527	dpll |= DPLL_VGA_MODE_DIS;528 529 530	dpll |= DPLL_VCO_ENABLE;531 532	if (is_lvds)533		dpll |= DPLLA_MODE_LVDS;534	else535		dpll |= DPLLB_MODE_DAC_SERIAL;536 537	if (is_sdvo) {538		int sdvo_pixel_multiply =539		    adjusted_mode->clock / mode->clock;540 541		dpll |= DPLL_DVO_HIGH_SPEED;542		dpll |=543		    (sdvo_pixel_multiply -544		     1) << SDVO_MULTIPLIER_SHIFT_HIRES;545	}546 547 548	/* compute bitmask from p1 value */549	if (is_sdvo)550		dpll |= clock.p1 << 16; // dpll |= (1 << (clock.p1 - 1)) << 16;551	else552		dpll |= (1 << (clock.p1 - 2)) << 17;553 554	dpll |= DPLL_VCO_ENABLE;555 556	if (dpll & DPLL_VCO_ENABLE) {557		for (i = 0; i <= need_aux; i++) {558			REG_WRITE_WITH_AUX(map->fp0, fp, i);559			REG_WRITE_WITH_AUX(map->dpll, dpll & ~DPLL_VCO_ENABLE, i);560			REG_READ_WITH_AUX(map->dpll, i);561			/* Check the DPLLA lock bit PIPEACONF[29] */562			udelay(150);563		}564	}565 566	for (i = 0; i <= need_aux; i++) {567		REG_WRITE_WITH_AUX(map->fp0, fp, i);568		REG_WRITE_WITH_AUX(map->dpll, dpll, i);569		REG_READ_WITH_AUX(map->dpll, i);570		/* Wait for the clocks to stabilize. */571		udelay(150);572 573		/* write it again -- the BIOS does, after all */574		REG_WRITE_WITH_AUX(map->dpll, dpll, i);575		REG_READ_WITH_AUX(map->dpll, i);576		/* Wait for the clocks to stabilize. */577		udelay(150);578 579		REG_WRITE_WITH_AUX(map->conf, pipeconf, i);580		REG_READ_WITH_AUX(map->conf, i);581		gma_wait_for_vblank(dev);582 583		REG_WRITE_WITH_AUX(map->cntr, dspcntr, i);584		gma_wait_for_vblank(dev);585	}586 587oaktrail_crtc_mode_set_exit:588	gma_power_end(dev);589	return 0;590}591 592static int oaktrail_pipe_set_base(struct drm_crtc *crtc,593			    int x, int y, struct drm_framebuffer *old_fb)594{595	struct drm_device *dev = crtc->dev;596	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);597	struct gma_crtc *gma_crtc = to_gma_crtc(crtc);598	struct drm_framebuffer *fb = crtc->primary->fb;599	int pipe = gma_crtc->pipe;600	const struct psb_offset *map = &dev_priv->regmap[pipe];601	unsigned long start, offset;602 603	u32 dspcntr;604	int ret = 0;605 606	/* no fb bound */607	if (!fb) {608		dev_dbg(dev->dev, "No FB bound\n");609		return 0;610	}611 612	if (!gma_power_begin(dev, true))613		return 0;614 615	start = to_psb_gem_object(fb->obj[0])->offset;616	offset = y * fb->pitches[0] + x * fb->format->cpp[0];617 618	REG_WRITE(map->stride, fb->pitches[0]);619 620	dspcntr = REG_READ(map->cntr);621	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;622 623	switch (fb->format->cpp[0] * 8) {624	case 8:625		dspcntr |= DISPPLANE_8BPP;626		break;627	case 16:628		if (fb->format->depth == 15)629			dspcntr |= DISPPLANE_15_16BPP;630		else631			dspcntr |= DISPPLANE_16BPP;632		break;633	case 24:634	case 32:635		dspcntr |= DISPPLANE_32BPP_NO_ALPHA;636		break;637	default:638		dev_err(dev->dev, "Unknown color depth\n");639		ret = -EINVAL;640		goto pipe_set_base_exit;641	}642	REG_WRITE(map->cntr, dspcntr);643 644	REG_WRITE(map->base, offset);645	REG_READ(map->base);646	REG_WRITE(map->surf, start);647	REG_READ(map->surf);648 649pipe_set_base_exit:650	gma_power_end(dev);651	return ret;652}653 654const struct drm_crtc_helper_funcs oaktrail_helper_funcs = {655	.dpms = oaktrail_crtc_dpms,656	.mode_set = oaktrail_crtc_mode_set,657	.mode_set_base = oaktrail_pipe_set_base,658	.prepare = gma_crtc_prepare,659	.commit = gma_crtc_commit,660};661 662/* Not used yet */663const struct gma_clock_funcs mrst_clock_funcs = {664	.clock = mrst_lvds_clock,665	.limit = mrst_limit,666	.pll_is_valid = gma_pll_is_valid,667};668