189c78134cc54dff016c83367912eb055637fa50cAlan Cox/* 289c78134cc54dff016c83367912eb055637fa50cAlan Cox * Copyright © 2006-2011 Intel Corporation 389c78134cc54dff016c83367912eb055637fa50cAlan Cox * 489c78134cc54dff016c83367912eb055637fa50cAlan Cox * This program is free software; you can redistribute it and/or modify it 589c78134cc54dff016c83367912eb055637fa50cAlan Cox * under the terms and conditions of the GNU General Public License, 689c78134cc54dff016c83367912eb055637fa50cAlan Cox * version 2, as published by the Free Software Foundation. 789c78134cc54dff016c83367912eb055637fa50cAlan Cox * 889c78134cc54dff016c83367912eb055637fa50cAlan Cox * This program is distributed in the hope it will be useful, but WITHOUT 989c78134cc54dff016c83367912eb055637fa50cAlan Cox * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1089c78134cc54dff016c83367912eb055637fa50cAlan Cox * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 1189c78134cc54dff016c83367912eb055637fa50cAlan Cox * more details. 1289c78134cc54dff016c83367912eb055637fa50cAlan Cox * 1389c78134cc54dff016c83367912eb055637fa50cAlan Cox * You should have received a copy of the GNU General Public License along with 1489c78134cc54dff016c83367912eb055637fa50cAlan Cox * this program; if not, write to the Free Software Foundation, Inc., 1589c78134cc54dff016c83367912eb055637fa50cAlan Cox * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 1689c78134cc54dff016c83367912eb055637fa50cAlan Cox * 1789c78134cc54dff016c83367912eb055637fa50cAlan Cox * Authors: 1889c78134cc54dff016c83367912eb055637fa50cAlan Cox * Eric Anholt <eric@anholt.net> 1989c78134cc54dff016c83367912eb055637fa50cAlan Cox */ 2089c78134cc54dff016c83367912eb055637fa50cAlan Cox 2189c78134cc54dff016c83367912eb055637fa50cAlan Cox#include <linux/i2c.h> 2289c78134cc54dff016c83367912eb055637fa50cAlan Cox#include <linux/pm_runtime.h> 2389c78134cc54dff016c83367912eb055637fa50cAlan Cox 2489c78134cc54dff016c83367912eb055637fa50cAlan Cox#include <drm/drmP.h> 2589c78134cc54dff016c83367912eb055637fa50cAlan Cox#include "framebuffer.h" 2689c78134cc54dff016c83367912eb055637fa50cAlan Cox#include "psb_drv.h" 2789c78134cc54dff016c83367912eb055637fa50cAlan Cox#include "psb_intel_drv.h" 2889c78134cc54dff016c83367912eb055637fa50cAlan Cox#include "psb_intel_reg.h" 2989c78134cc54dff016c83367912eb055637fa50cAlan Cox#include "psb_intel_display.h" 3089c78134cc54dff016c83367912eb055637fa50cAlan Cox#include "power.h" 3189c78134cc54dff016c83367912eb055637fa50cAlan Cox 3289c78134cc54dff016c83367912eb055637fa50cAlan Coxstruct psb_intel_clock_t { 3389c78134cc54dff016c83367912eb055637fa50cAlan Cox /* given values */ 3489c78134cc54dff016c83367912eb055637fa50cAlan Cox int n; 3589c78134cc54dff016c83367912eb055637fa50cAlan Cox int m1, m2; 3689c78134cc54dff016c83367912eb055637fa50cAlan Cox int p1, p2; 3789c78134cc54dff016c83367912eb055637fa50cAlan Cox /* derived values */ 3889c78134cc54dff016c83367912eb055637fa50cAlan Cox int dot; 3989c78134cc54dff016c83367912eb055637fa50cAlan Cox int vco; 4089c78134cc54dff016c83367912eb055637fa50cAlan Cox int m; 4189c78134cc54dff016c83367912eb055637fa50cAlan Cox int p; 4289c78134cc54dff016c83367912eb055637fa50cAlan Cox}; 4389c78134cc54dff016c83367912eb055637fa50cAlan Cox 4489c78134cc54dff016c83367912eb055637fa50cAlan Coxstruct psb_intel_range_t { 4589c78134cc54dff016c83367912eb055637fa50cAlan Cox int min, max; 4689c78134cc54dff016c83367912eb055637fa50cAlan Cox}; 4789c78134cc54dff016c83367912eb055637fa50cAlan Cox 4889c78134cc54dff016c83367912eb055637fa50cAlan Coxstruct psb_intel_p2_t { 4989c78134cc54dff016c83367912eb055637fa50cAlan Cox int dot_limit; 5089c78134cc54dff016c83367912eb055637fa50cAlan Cox int p2_slow, p2_fast; 5189c78134cc54dff016c83367912eb055637fa50cAlan Cox}; 5289c78134cc54dff016c83367912eb055637fa50cAlan Cox 5389c78134cc54dff016c83367912eb055637fa50cAlan Cox#define INTEL_P2_NUM 2 5489c78134cc54dff016c83367912eb055637fa50cAlan Cox 5589c78134cc54dff016c83367912eb055637fa50cAlan Coxstruct psb_intel_limit_t { 5689c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_range_t dot, vco, n, m, m1, m2, p, p1; 5789c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_p2_t p2; 5889c78134cc54dff016c83367912eb055637fa50cAlan Cox}; 5989c78134cc54dff016c83367912eb055637fa50cAlan Cox 6089c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I8XX_DOT_MIN 25000 6189c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I8XX_DOT_MAX 350000 6289c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I8XX_VCO_MIN 930000 6389c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I8XX_VCO_MAX 1400000 6489c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I8XX_N_MIN 3 6589c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I8XX_N_MAX 16 6689c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I8XX_M_MIN 96 6789c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I8XX_M_MAX 140 6889c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I8XX_M1_MIN 18 6989c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I8XX_M1_MAX 26 7089c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I8XX_M2_MIN 6 7189c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I8XX_M2_MAX 16 7289c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I8XX_P_MIN 4 7389c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I8XX_P_MAX 128 7489c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I8XX_P1_MIN 2 7589c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I8XX_P1_MAX 33 7689c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I8XX_P1_LVDS_MIN 1 7789c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I8XX_P1_LVDS_MAX 6 7889c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I8XX_P2_SLOW 4 7989c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I8XX_P2_FAST 2 8089c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I8XX_P2_LVDS_SLOW 14 8189c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I8XX_P2_LVDS_FAST 14 /* No fast option */ 8289c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I8XX_P2_SLOW_LIMIT 165000 8389c78134cc54dff016c83367912eb055637fa50cAlan Cox 8489c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I9XX_DOT_MIN 20000 8589c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I9XX_DOT_MAX 400000 8689c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I9XX_VCO_MIN 1400000 8789c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I9XX_VCO_MAX 2800000 8889c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I9XX_N_MIN 3 8989c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I9XX_N_MAX 8 9089c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I9XX_M_MIN 70 9189c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I9XX_M_MAX 120 9289c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I9XX_M1_MIN 10 9389c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I9XX_M1_MAX 20 9489c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I9XX_M2_MIN 5 9589c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I9XX_M2_MAX 9 9689c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I9XX_P_SDVO_DAC_MIN 5 9789c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I9XX_P_SDVO_DAC_MAX 80 9889c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I9XX_P_LVDS_MIN 7 9989c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I9XX_P_LVDS_MAX 98 10089c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I9XX_P1_MIN 1 10189c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I9XX_P1_MAX 8 10289c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I9XX_P2_SDVO_DAC_SLOW 10 10389c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I9XX_P2_SDVO_DAC_FAST 5 10489c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I9XX_P2_SDVO_DAC_SLOW_LIMIT 200000 10589c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I9XX_P2_LVDS_SLOW 14 10689c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I9XX_P2_LVDS_FAST 7 10789c78134cc54dff016c83367912eb055637fa50cAlan Cox#define I9XX_P2_LVDS_SLOW_LIMIT 112000 10889c78134cc54dff016c83367912eb055637fa50cAlan Cox 10989c78134cc54dff016c83367912eb055637fa50cAlan Cox#define INTEL_LIMIT_I8XX_DVO_DAC 0 11089c78134cc54dff016c83367912eb055637fa50cAlan Cox#define INTEL_LIMIT_I8XX_LVDS 1 11189c78134cc54dff016c83367912eb055637fa50cAlan Cox#define INTEL_LIMIT_I9XX_SDVO_DAC 2 11289c78134cc54dff016c83367912eb055637fa50cAlan Cox#define INTEL_LIMIT_I9XX_LVDS 3 11389c78134cc54dff016c83367912eb055637fa50cAlan Cox 11489c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic const struct psb_intel_limit_t psb_intel_limits[] = { 11589c78134cc54dff016c83367912eb055637fa50cAlan Cox { /* INTEL_LIMIT_I8XX_DVO_DAC */ 11689c78134cc54dff016c83367912eb055637fa50cAlan Cox .dot = {.min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX}, 11789c78134cc54dff016c83367912eb055637fa50cAlan Cox .vco = {.min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX}, 11889c78134cc54dff016c83367912eb055637fa50cAlan Cox .n = {.min = I8XX_N_MIN, .max = I8XX_N_MAX}, 11989c78134cc54dff016c83367912eb055637fa50cAlan Cox .m = {.min = I8XX_M_MIN, .max = I8XX_M_MAX}, 12089c78134cc54dff016c83367912eb055637fa50cAlan Cox .m1 = {.min = I8XX_M1_MIN, .max = I8XX_M1_MAX}, 12189c78134cc54dff016c83367912eb055637fa50cAlan Cox .m2 = {.min = I8XX_M2_MIN, .max = I8XX_M2_MAX}, 12289c78134cc54dff016c83367912eb055637fa50cAlan Cox .p = {.min = I8XX_P_MIN, .max = I8XX_P_MAX}, 12389c78134cc54dff016c83367912eb055637fa50cAlan Cox .p1 = {.min = I8XX_P1_MIN, .max = I8XX_P1_MAX}, 12489c78134cc54dff016c83367912eb055637fa50cAlan Cox .p2 = {.dot_limit = I8XX_P2_SLOW_LIMIT, 12589c78134cc54dff016c83367912eb055637fa50cAlan Cox .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST}, 12689c78134cc54dff016c83367912eb055637fa50cAlan Cox }, 12789c78134cc54dff016c83367912eb055637fa50cAlan Cox { /* INTEL_LIMIT_I8XX_LVDS */ 12889c78134cc54dff016c83367912eb055637fa50cAlan Cox .dot = {.min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX}, 12989c78134cc54dff016c83367912eb055637fa50cAlan Cox .vco = {.min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX}, 13089c78134cc54dff016c83367912eb055637fa50cAlan Cox .n = {.min = I8XX_N_MIN, .max = I8XX_N_MAX}, 13189c78134cc54dff016c83367912eb055637fa50cAlan Cox .m = {.min = I8XX_M_MIN, .max = I8XX_M_MAX}, 13289c78134cc54dff016c83367912eb055637fa50cAlan Cox .m1 = {.min = I8XX_M1_MIN, .max = I8XX_M1_MAX}, 13389c78134cc54dff016c83367912eb055637fa50cAlan Cox .m2 = {.min = I8XX_M2_MIN, .max = I8XX_M2_MAX}, 13489c78134cc54dff016c83367912eb055637fa50cAlan Cox .p = {.min = I8XX_P_MIN, .max = I8XX_P_MAX}, 13589c78134cc54dff016c83367912eb055637fa50cAlan Cox .p1 = {.min = I8XX_P1_LVDS_MIN, .max = I8XX_P1_LVDS_MAX}, 13689c78134cc54dff016c83367912eb055637fa50cAlan Cox .p2 = {.dot_limit = I8XX_P2_SLOW_LIMIT, 13789c78134cc54dff016c83367912eb055637fa50cAlan Cox .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST}, 13889c78134cc54dff016c83367912eb055637fa50cAlan Cox }, 13989c78134cc54dff016c83367912eb055637fa50cAlan Cox { /* INTEL_LIMIT_I9XX_SDVO_DAC */ 14089c78134cc54dff016c83367912eb055637fa50cAlan Cox .dot = {.min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, 14189c78134cc54dff016c83367912eb055637fa50cAlan Cox .vco = {.min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX}, 14289c78134cc54dff016c83367912eb055637fa50cAlan Cox .n = {.min = I9XX_N_MIN, .max = I9XX_N_MAX}, 14389c78134cc54dff016c83367912eb055637fa50cAlan Cox .m = {.min = I9XX_M_MIN, .max = I9XX_M_MAX}, 14489c78134cc54dff016c83367912eb055637fa50cAlan Cox .m1 = {.min = I9XX_M1_MIN, .max = I9XX_M1_MAX}, 14589c78134cc54dff016c83367912eb055637fa50cAlan Cox .m2 = {.min = I9XX_M2_MIN, .max = I9XX_M2_MAX}, 14689c78134cc54dff016c83367912eb055637fa50cAlan Cox .p = {.min = I9XX_P_SDVO_DAC_MIN, .max = I9XX_P_SDVO_DAC_MAX}, 14789c78134cc54dff016c83367912eb055637fa50cAlan Cox .p1 = {.min = I9XX_P1_MIN, .max = I9XX_P1_MAX}, 14889c78134cc54dff016c83367912eb055637fa50cAlan Cox .p2 = {.dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, 14989c78134cc54dff016c83367912eb055637fa50cAlan Cox .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = 15089c78134cc54dff016c83367912eb055637fa50cAlan Cox I9XX_P2_SDVO_DAC_FAST}, 15189c78134cc54dff016c83367912eb055637fa50cAlan Cox }, 15289c78134cc54dff016c83367912eb055637fa50cAlan Cox { /* INTEL_LIMIT_I9XX_LVDS */ 15389c78134cc54dff016c83367912eb055637fa50cAlan Cox .dot = {.min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, 15489c78134cc54dff016c83367912eb055637fa50cAlan Cox .vco = {.min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX}, 15589c78134cc54dff016c83367912eb055637fa50cAlan Cox .n = {.min = I9XX_N_MIN, .max = I9XX_N_MAX}, 15689c78134cc54dff016c83367912eb055637fa50cAlan Cox .m = {.min = I9XX_M_MIN, .max = I9XX_M_MAX}, 15789c78134cc54dff016c83367912eb055637fa50cAlan Cox .m1 = {.min = I9XX_M1_MIN, .max = I9XX_M1_MAX}, 15889c78134cc54dff016c83367912eb055637fa50cAlan Cox .m2 = {.min = I9XX_M2_MIN, .max = I9XX_M2_MAX}, 15989c78134cc54dff016c83367912eb055637fa50cAlan Cox .p = {.min = I9XX_P_LVDS_MIN, .max = I9XX_P_LVDS_MAX}, 16089c78134cc54dff016c83367912eb055637fa50cAlan Cox .p1 = {.min = I9XX_P1_MIN, .max = I9XX_P1_MAX}, 16189c78134cc54dff016c83367912eb055637fa50cAlan Cox /* The single-channel range is 25-112Mhz, and dual-channel 16289c78134cc54dff016c83367912eb055637fa50cAlan Cox * is 80-224Mhz. Prefer single channel as much as possible. 16389c78134cc54dff016c83367912eb055637fa50cAlan Cox */ 16489c78134cc54dff016c83367912eb055637fa50cAlan Cox .p2 = {.dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, 16589c78134cc54dff016c83367912eb055637fa50cAlan Cox .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST}, 16689c78134cc54dff016c83367912eb055637fa50cAlan Cox }, 16789c78134cc54dff016c83367912eb055637fa50cAlan Cox}; 16889c78134cc54dff016c83367912eb055637fa50cAlan Cox 16989c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic const struct psb_intel_limit_t *psb_intel_limit(struct drm_crtc *crtc) 17089c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 17189c78134cc54dff016c83367912eb055637fa50cAlan Cox const struct psb_intel_limit_t *limit; 17289c78134cc54dff016c83367912eb055637fa50cAlan Cox 17389c78134cc54dff016c83367912eb055637fa50cAlan Cox if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) 17489c78134cc54dff016c83367912eb055637fa50cAlan Cox limit = &psb_intel_limits[INTEL_LIMIT_I9XX_LVDS]; 17589c78134cc54dff016c83367912eb055637fa50cAlan Cox else 17689c78134cc54dff016c83367912eb055637fa50cAlan Cox limit = &psb_intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; 17789c78134cc54dff016c83367912eb055637fa50cAlan Cox return limit; 17889c78134cc54dff016c83367912eb055637fa50cAlan Cox} 17989c78134cc54dff016c83367912eb055637fa50cAlan Cox 18089c78134cc54dff016c83367912eb055637fa50cAlan Cox/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ 18189c78134cc54dff016c83367912eb055637fa50cAlan Cox 18289c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic void i8xx_clock(int refclk, struct psb_intel_clock_t *clock) 18389c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 18489c78134cc54dff016c83367912eb055637fa50cAlan Cox clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); 18589c78134cc54dff016c83367912eb055637fa50cAlan Cox clock->p = clock->p1 * clock->p2; 18689c78134cc54dff016c83367912eb055637fa50cAlan Cox clock->vco = refclk * clock->m / (clock->n + 2); 18789c78134cc54dff016c83367912eb055637fa50cAlan Cox clock->dot = clock->vco / clock->p; 18889c78134cc54dff016c83367912eb055637fa50cAlan Cox} 18989c78134cc54dff016c83367912eb055637fa50cAlan Cox 19089c78134cc54dff016c83367912eb055637fa50cAlan Cox/** Derive the pixel clock for the given refclk and divisors for 9xx chips. */ 19189c78134cc54dff016c83367912eb055637fa50cAlan Cox 19289c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic void i9xx_clock(int refclk, struct psb_intel_clock_t *clock) 19389c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 19489c78134cc54dff016c83367912eb055637fa50cAlan Cox clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); 19589c78134cc54dff016c83367912eb055637fa50cAlan Cox clock->p = clock->p1 * clock->p2; 19689c78134cc54dff016c83367912eb055637fa50cAlan Cox clock->vco = refclk * clock->m / (clock->n + 2); 19789c78134cc54dff016c83367912eb055637fa50cAlan Cox clock->dot = clock->vco / clock->p; 19889c78134cc54dff016c83367912eb055637fa50cAlan Cox} 19989c78134cc54dff016c83367912eb055637fa50cAlan Cox 20089c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic void psb_intel_clock(struct drm_device *dev, int refclk, 20189c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_clock_t *clock) 20289c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 20389c78134cc54dff016c83367912eb055637fa50cAlan Cox return i9xx_clock(refclk, clock); 20489c78134cc54dff016c83367912eb055637fa50cAlan Cox} 20589c78134cc54dff016c83367912eb055637fa50cAlan Cox 20689c78134cc54dff016c83367912eb055637fa50cAlan Cox/** 20789c78134cc54dff016c83367912eb055637fa50cAlan Cox * Returns whether any output on the specified pipe is of the specified type 20889c78134cc54dff016c83367912eb055637fa50cAlan Cox */ 20989c78134cc54dff016c83367912eb055637fa50cAlan Coxbool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type) 21089c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 21189c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_device *dev = crtc->dev; 21289c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_mode_config *mode_config = &dev->mode_config; 21389c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_connector *l_entry; 21489c78134cc54dff016c83367912eb055637fa50cAlan Cox 21589c78134cc54dff016c83367912eb055637fa50cAlan Cox list_for_each_entry(l_entry, &mode_config->connector_list, head) { 21689c78134cc54dff016c83367912eb055637fa50cAlan Cox if (l_entry->encoder && l_entry->encoder->crtc == crtc) { 2171730f89bfcff353484672cdcefbef13b2f374176Patrik Jakobsson struct psb_intel_encoder *psb_intel_encoder = 2181730f89bfcff353484672cdcefbef13b2f374176Patrik Jakobsson psb_intel_attached_encoder(l_entry); 2191730f89bfcff353484672cdcefbef13b2f374176Patrik Jakobsson if (psb_intel_encoder->type == type) 22089c78134cc54dff016c83367912eb055637fa50cAlan Cox return true; 22189c78134cc54dff016c83367912eb055637fa50cAlan Cox } 22289c78134cc54dff016c83367912eb055637fa50cAlan Cox } 22389c78134cc54dff016c83367912eb055637fa50cAlan Cox return false; 22489c78134cc54dff016c83367912eb055637fa50cAlan Cox} 22589c78134cc54dff016c83367912eb055637fa50cAlan Cox 22689c78134cc54dff016c83367912eb055637fa50cAlan Cox#define INTELPllInvalid(s) { /* ErrorF (s) */; return false; } 22789c78134cc54dff016c83367912eb055637fa50cAlan Cox/** 22889c78134cc54dff016c83367912eb055637fa50cAlan Cox * Returns whether the given set of divisors are valid for a given refclk with 22989c78134cc54dff016c83367912eb055637fa50cAlan Cox * the given connectors. 23089c78134cc54dff016c83367912eb055637fa50cAlan Cox */ 23189c78134cc54dff016c83367912eb055637fa50cAlan Cox 23289c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic bool psb_intel_PLL_is_valid(struct drm_crtc *crtc, 23389c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_clock_t *clock) 23489c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 23589c78134cc54dff016c83367912eb055637fa50cAlan Cox const struct psb_intel_limit_t *limit = psb_intel_limit(crtc); 23689c78134cc54dff016c83367912eb055637fa50cAlan Cox 23789c78134cc54dff016c83367912eb055637fa50cAlan Cox if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1) 23889c78134cc54dff016c83367912eb055637fa50cAlan Cox INTELPllInvalid("p1 out of range\n"); 23989c78134cc54dff016c83367912eb055637fa50cAlan Cox if (clock->p < limit->p.min || limit->p.max < clock->p) 24089c78134cc54dff016c83367912eb055637fa50cAlan Cox INTELPllInvalid("p out of range\n"); 24189c78134cc54dff016c83367912eb055637fa50cAlan Cox if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2) 24289c78134cc54dff016c83367912eb055637fa50cAlan Cox INTELPllInvalid("m2 out of range\n"); 24389c78134cc54dff016c83367912eb055637fa50cAlan Cox if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1) 24489c78134cc54dff016c83367912eb055637fa50cAlan Cox INTELPllInvalid("m1 out of range\n"); 24589c78134cc54dff016c83367912eb055637fa50cAlan Cox if (clock->m1 <= clock->m2) 24689c78134cc54dff016c83367912eb055637fa50cAlan Cox INTELPllInvalid("m1 <= m2\n"); 24789c78134cc54dff016c83367912eb055637fa50cAlan Cox if (clock->m < limit->m.min || limit->m.max < clock->m) 24889c78134cc54dff016c83367912eb055637fa50cAlan Cox INTELPllInvalid("m out of range\n"); 24989c78134cc54dff016c83367912eb055637fa50cAlan Cox if (clock->n < limit->n.min || limit->n.max < clock->n) 25089c78134cc54dff016c83367912eb055637fa50cAlan Cox INTELPllInvalid("n out of range\n"); 25189c78134cc54dff016c83367912eb055637fa50cAlan Cox if (clock->vco < limit->vco.min || limit->vco.max < clock->vco) 25289c78134cc54dff016c83367912eb055637fa50cAlan Cox INTELPllInvalid("vco out of range\n"); 25389c78134cc54dff016c83367912eb055637fa50cAlan Cox /* XXX: We may need to be checking "Dot clock" 25489c78134cc54dff016c83367912eb055637fa50cAlan Cox * depending on the multiplier, connector, etc., 25589c78134cc54dff016c83367912eb055637fa50cAlan Cox * rather than just a single range. 25689c78134cc54dff016c83367912eb055637fa50cAlan Cox */ 25789c78134cc54dff016c83367912eb055637fa50cAlan Cox if (clock->dot < limit->dot.min || limit->dot.max < clock->dot) 25889c78134cc54dff016c83367912eb055637fa50cAlan Cox INTELPllInvalid("dot out of range\n"); 25989c78134cc54dff016c83367912eb055637fa50cAlan Cox 26089c78134cc54dff016c83367912eb055637fa50cAlan Cox return true; 26189c78134cc54dff016c83367912eb055637fa50cAlan Cox} 26289c78134cc54dff016c83367912eb055637fa50cAlan Cox 26389c78134cc54dff016c83367912eb055637fa50cAlan Cox/** 26489c78134cc54dff016c83367912eb055637fa50cAlan Cox * Returns a set of divisors for the desired target clock with the given 26589c78134cc54dff016c83367912eb055637fa50cAlan Cox * refclk, or FALSE. The returned values represent the clock equation: 26689c78134cc54dff016c83367912eb055637fa50cAlan Cox * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. 26789c78134cc54dff016c83367912eb055637fa50cAlan Cox */ 26889c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic bool psb_intel_find_best_PLL(struct drm_crtc *crtc, int target, 26989c78134cc54dff016c83367912eb055637fa50cAlan Cox int refclk, 27089c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_clock_t *best_clock) 27189c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 27289c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_device *dev = crtc->dev; 27389c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_clock_t clock; 27489c78134cc54dff016c83367912eb055637fa50cAlan Cox const struct psb_intel_limit_t *limit = psb_intel_limit(crtc); 27589c78134cc54dff016c83367912eb055637fa50cAlan Cox int err = target; 27689c78134cc54dff016c83367912eb055637fa50cAlan Cox 27789c78134cc54dff016c83367912eb055637fa50cAlan Cox if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && 27889c78134cc54dff016c83367912eb055637fa50cAlan Cox (REG_READ(LVDS) & LVDS_PORT_EN) != 0) { 27989c78134cc54dff016c83367912eb055637fa50cAlan Cox /* 28089c78134cc54dff016c83367912eb055637fa50cAlan Cox * For LVDS, if the panel is on, just rely on its current 28189c78134cc54dff016c83367912eb055637fa50cAlan Cox * settings for dual-channel. We haven't figured out how to 28289c78134cc54dff016c83367912eb055637fa50cAlan Cox * reliably set up different single/dual channel state, if we 28389c78134cc54dff016c83367912eb055637fa50cAlan Cox * even can. 28489c78134cc54dff016c83367912eb055637fa50cAlan Cox */ 28589c78134cc54dff016c83367912eb055637fa50cAlan Cox if ((REG_READ(LVDS) & LVDS_CLKB_POWER_MASK) == 28689c78134cc54dff016c83367912eb055637fa50cAlan Cox LVDS_CLKB_POWER_UP) 28789c78134cc54dff016c83367912eb055637fa50cAlan Cox clock.p2 = limit->p2.p2_fast; 28889c78134cc54dff016c83367912eb055637fa50cAlan Cox else 28989c78134cc54dff016c83367912eb055637fa50cAlan Cox clock.p2 = limit->p2.p2_slow; 29089c78134cc54dff016c83367912eb055637fa50cAlan Cox } else { 29189c78134cc54dff016c83367912eb055637fa50cAlan Cox if (target < limit->p2.dot_limit) 29289c78134cc54dff016c83367912eb055637fa50cAlan Cox clock.p2 = limit->p2.p2_slow; 29389c78134cc54dff016c83367912eb055637fa50cAlan Cox else 29489c78134cc54dff016c83367912eb055637fa50cAlan Cox clock.p2 = limit->p2.p2_fast; 29589c78134cc54dff016c83367912eb055637fa50cAlan Cox } 29689c78134cc54dff016c83367912eb055637fa50cAlan Cox 29789c78134cc54dff016c83367912eb055637fa50cAlan Cox memset(best_clock, 0, sizeof(*best_clock)); 29889c78134cc54dff016c83367912eb055637fa50cAlan Cox 29989c78134cc54dff016c83367912eb055637fa50cAlan Cox for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; 30089c78134cc54dff016c83367912eb055637fa50cAlan Cox clock.m1++) { 30189c78134cc54dff016c83367912eb055637fa50cAlan Cox for (clock.m2 = limit->m2.min; 30289c78134cc54dff016c83367912eb055637fa50cAlan Cox clock.m2 < clock.m1 && clock.m2 <= limit->m2.max; 30389c78134cc54dff016c83367912eb055637fa50cAlan Cox clock.m2++) { 30489c78134cc54dff016c83367912eb055637fa50cAlan Cox for (clock.n = limit->n.min; 30589c78134cc54dff016c83367912eb055637fa50cAlan Cox clock.n <= limit->n.max; clock.n++) { 30689c78134cc54dff016c83367912eb055637fa50cAlan Cox for (clock.p1 = limit->p1.min; 30789c78134cc54dff016c83367912eb055637fa50cAlan Cox clock.p1 <= limit->p1.max; 30889c78134cc54dff016c83367912eb055637fa50cAlan Cox clock.p1++) { 30989c78134cc54dff016c83367912eb055637fa50cAlan Cox int this_err; 31089c78134cc54dff016c83367912eb055637fa50cAlan Cox 31189c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_clock(dev, refclk, &clock); 31289c78134cc54dff016c83367912eb055637fa50cAlan Cox 31389c78134cc54dff016c83367912eb055637fa50cAlan Cox if (!psb_intel_PLL_is_valid 31489c78134cc54dff016c83367912eb055637fa50cAlan Cox (crtc, &clock)) 31589c78134cc54dff016c83367912eb055637fa50cAlan Cox continue; 31689c78134cc54dff016c83367912eb055637fa50cAlan Cox 31789c78134cc54dff016c83367912eb055637fa50cAlan Cox this_err = abs(clock.dot - target); 31889c78134cc54dff016c83367912eb055637fa50cAlan Cox if (this_err < err) { 31989c78134cc54dff016c83367912eb055637fa50cAlan Cox *best_clock = clock; 32089c78134cc54dff016c83367912eb055637fa50cAlan Cox err = this_err; 32189c78134cc54dff016c83367912eb055637fa50cAlan Cox } 32289c78134cc54dff016c83367912eb055637fa50cAlan Cox } 32389c78134cc54dff016c83367912eb055637fa50cAlan Cox } 32489c78134cc54dff016c83367912eb055637fa50cAlan Cox } 32589c78134cc54dff016c83367912eb055637fa50cAlan Cox } 32689c78134cc54dff016c83367912eb055637fa50cAlan Cox 32789c78134cc54dff016c83367912eb055637fa50cAlan Cox return err != target; 32889c78134cc54dff016c83367912eb055637fa50cAlan Cox} 32989c78134cc54dff016c83367912eb055637fa50cAlan Cox 33089c78134cc54dff016c83367912eb055637fa50cAlan Coxvoid psb_intel_wait_for_vblank(struct drm_device *dev) 33189c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 33289c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Wait for 20ms, i.e. one cycle at 50hz. */ 33389c78134cc54dff016c83367912eb055637fa50cAlan Cox mdelay(20); 33489c78134cc54dff016c83367912eb055637fa50cAlan Cox} 33589c78134cc54dff016c83367912eb055637fa50cAlan Cox 3363c1d08d7af81b4dbd77530cb4f21f28cd4035f40Kirill A. Shutemovstatic int psb_intel_pipe_set_base(struct drm_crtc *crtc, 33789c78134cc54dff016c83367912eb055637fa50cAlan Cox int x, int y, struct drm_framebuffer *old_fb) 33889c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 33989c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_device *dev = crtc->dev; 34089c78134cc54dff016c83367912eb055637fa50cAlan Cox /* struct drm_i915_master_private *master_priv; */ 34189c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 34289c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); 34389c78134cc54dff016c83367912eb055637fa50cAlan Cox int pipe = psb_intel_crtc->pipe; 34489c78134cc54dff016c83367912eb055637fa50cAlan Cox unsigned long start, offset; 34589c78134cc54dff016c83367912eb055637fa50cAlan Cox int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE); 34689c78134cc54dff016c83367912eb055637fa50cAlan Cox int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); 34789c78134cc54dff016c83367912eb055637fa50cAlan Cox int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; 34889c78134cc54dff016c83367912eb055637fa50cAlan Cox int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; 34989c78134cc54dff016c83367912eb055637fa50cAlan Cox u32 dspcntr; 35089c78134cc54dff016c83367912eb055637fa50cAlan Cox int ret = 0; 35189c78134cc54dff016c83367912eb055637fa50cAlan Cox 35289c78134cc54dff016c83367912eb055637fa50cAlan Cox if (!gma_power_begin(dev, true)) 35389c78134cc54dff016c83367912eb055637fa50cAlan Cox return 0; 35489c78134cc54dff016c83367912eb055637fa50cAlan Cox 35589c78134cc54dff016c83367912eb055637fa50cAlan Cox /* no fb bound */ 35689c78134cc54dff016c83367912eb055637fa50cAlan Cox if (!crtc->fb) { 35789c78134cc54dff016c83367912eb055637fa50cAlan Cox dev_dbg(dev->dev, "No FB bound\n"); 35889c78134cc54dff016c83367912eb055637fa50cAlan Cox goto psb_intel_pipe_cleaner; 35989c78134cc54dff016c83367912eb055637fa50cAlan Cox } 36089c78134cc54dff016c83367912eb055637fa50cAlan Cox 36189c78134cc54dff016c83367912eb055637fa50cAlan Cox /* We are displaying this buffer, make sure it is actually loaded 36289c78134cc54dff016c83367912eb055637fa50cAlan Cox into the GTT */ 36389c78134cc54dff016c83367912eb055637fa50cAlan Cox ret = psb_gtt_pin(psbfb->gtt); 36489c78134cc54dff016c83367912eb055637fa50cAlan Cox if (ret < 0) 36589c78134cc54dff016c83367912eb055637fa50cAlan Cox goto psb_intel_pipe_set_base_exit; 36689c78134cc54dff016c83367912eb055637fa50cAlan Cox start = psbfb->gtt->offset; 36789c78134cc54dff016c83367912eb055637fa50cAlan Cox 36801f2c7730e188077026c5f766f85f329c7000c54Ville Syrjälä offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8); 36989c78134cc54dff016c83367912eb055637fa50cAlan Cox 37001f2c7730e188077026c5f766f85f329c7000c54Ville Syrjälä REG_WRITE(dspstride, crtc->fb->pitches[0]); 37189c78134cc54dff016c83367912eb055637fa50cAlan Cox 37289c78134cc54dff016c83367912eb055637fa50cAlan Cox dspcntr = REG_READ(dspcntr_reg); 37389c78134cc54dff016c83367912eb055637fa50cAlan Cox dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; 37489c78134cc54dff016c83367912eb055637fa50cAlan Cox 37589c78134cc54dff016c83367912eb055637fa50cAlan Cox switch (crtc->fb->bits_per_pixel) { 37689c78134cc54dff016c83367912eb055637fa50cAlan Cox case 8: 37789c78134cc54dff016c83367912eb055637fa50cAlan Cox dspcntr |= DISPPLANE_8BPP; 37889c78134cc54dff016c83367912eb055637fa50cAlan Cox break; 37989c78134cc54dff016c83367912eb055637fa50cAlan Cox case 16: 38089c78134cc54dff016c83367912eb055637fa50cAlan Cox if (crtc->fb->depth == 15) 38189c78134cc54dff016c83367912eb055637fa50cAlan Cox dspcntr |= DISPPLANE_15_16BPP; 38289c78134cc54dff016c83367912eb055637fa50cAlan Cox else 38389c78134cc54dff016c83367912eb055637fa50cAlan Cox dspcntr |= DISPPLANE_16BPP; 38489c78134cc54dff016c83367912eb055637fa50cAlan Cox break; 38589c78134cc54dff016c83367912eb055637fa50cAlan Cox case 24: 38689c78134cc54dff016c83367912eb055637fa50cAlan Cox case 32: 38789c78134cc54dff016c83367912eb055637fa50cAlan Cox dspcntr |= DISPPLANE_32BPP_NO_ALPHA; 38889c78134cc54dff016c83367912eb055637fa50cAlan Cox break; 38989c78134cc54dff016c83367912eb055637fa50cAlan Cox default: 39089c78134cc54dff016c83367912eb055637fa50cAlan Cox dev_err(dev->dev, "Unknown color depth\n"); 39189c78134cc54dff016c83367912eb055637fa50cAlan Cox ret = -EINVAL; 39289c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_gtt_unpin(psbfb->gtt); 39389c78134cc54dff016c83367912eb055637fa50cAlan Cox goto psb_intel_pipe_set_base_exit; 39489c78134cc54dff016c83367912eb055637fa50cAlan Cox } 39589c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(dspcntr_reg, dspcntr); 39689c78134cc54dff016c83367912eb055637fa50cAlan Cox 39789c78134cc54dff016c83367912eb055637fa50cAlan Cox 39889c78134cc54dff016c83367912eb055637fa50cAlan Cox if (0 /* FIXMEAC - check what PSB needs */) { 39989c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(dspbase, offset); 40089c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_READ(dspbase); 40189c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(dspsurf, start); 40289c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_READ(dspsurf); 40389c78134cc54dff016c83367912eb055637fa50cAlan Cox } else { 40489c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(dspbase, start + offset); 40589c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_READ(dspbase); 40689c78134cc54dff016c83367912eb055637fa50cAlan Cox } 40789c78134cc54dff016c83367912eb055637fa50cAlan Cox 40889c78134cc54dff016c83367912eb055637fa50cAlan Coxpsb_intel_pipe_cleaner: 40989c78134cc54dff016c83367912eb055637fa50cAlan Cox /* If there was a previous display we can now unpin it */ 41089c78134cc54dff016c83367912eb055637fa50cAlan Cox if (old_fb) 41189c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_gtt_unpin(to_psb_fb(old_fb)->gtt); 41289c78134cc54dff016c83367912eb055637fa50cAlan Cox 41389c78134cc54dff016c83367912eb055637fa50cAlan Coxpsb_intel_pipe_set_base_exit: 41489c78134cc54dff016c83367912eb055637fa50cAlan Cox gma_power_end(dev); 41589c78134cc54dff016c83367912eb055637fa50cAlan Cox return ret; 41689c78134cc54dff016c83367912eb055637fa50cAlan Cox} 41789c78134cc54dff016c83367912eb055637fa50cAlan Cox 41889c78134cc54dff016c83367912eb055637fa50cAlan Cox/** 41989c78134cc54dff016c83367912eb055637fa50cAlan Cox * Sets the power management mode of the pipe and plane. 42089c78134cc54dff016c83367912eb055637fa50cAlan Cox * 42189c78134cc54dff016c83367912eb055637fa50cAlan Cox * This code should probably grow support for turning the cursor off and back 42289c78134cc54dff016c83367912eb055637fa50cAlan Cox * on appropriately at the same time as we're turning the pipe off/on. 42389c78134cc54dff016c83367912eb055637fa50cAlan Cox */ 42489c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic void psb_intel_crtc_dpms(struct drm_crtc *crtc, int mode) 42589c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 42689c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_device *dev = crtc->dev; 42789c78134cc54dff016c83367912eb055637fa50cAlan Cox /* struct drm_i915_master_private *master_priv; */ 42889c78134cc54dff016c83367912eb055637fa50cAlan Cox /* struct drm_i915_private *dev_priv = dev->dev_private; */ 42989c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 43089c78134cc54dff016c83367912eb055637fa50cAlan Cox int pipe = psb_intel_crtc->pipe; 43189c78134cc54dff016c83367912eb055637fa50cAlan Cox int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; 43289c78134cc54dff016c83367912eb055637fa50cAlan Cox int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; 43389c78134cc54dff016c83367912eb055637fa50cAlan Cox int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE; 43489c78134cc54dff016c83367912eb055637fa50cAlan Cox int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; 43589c78134cc54dff016c83367912eb055637fa50cAlan Cox u32 temp; 43689c78134cc54dff016c83367912eb055637fa50cAlan Cox 43789c78134cc54dff016c83367912eb055637fa50cAlan Cox /* XXX: When our outputs are all unaware of DPMS modes other than off 43889c78134cc54dff016c83367912eb055637fa50cAlan Cox * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. 43989c78134cc54dff016c83367912eb055637fa50cAlan Cox */ 44089c78134cc54dff016c83367912eb055637fa50cAlan Cox switch (mode) { 44189c78134cc54dff016c83367912eb055637fa50cAlan Cox case DRM_MODE_DPMS_ON: 44289c78134cc54dff016c83367912eb055637fa50cAlan Cox case DRM_MODE_DPMS_STANDBY: 44389c78134cc54dff016c83367912eb055637fa50cAlan Cox case DRM_MODE_DPMS_SUSPEND: 44489c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Enable the DPLL */ 44589c78134cc54dff016c83367912eb055637fa50cAlan Cox temp = REG_READ(dpll_reg); 44689c78134cc54dff016c83367912eb055637fa50cAlan Cox if ((temp & DPLL_VCO_ENABLE) == 0) { 44789c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(dpll_reg, temp); 44889c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_READ(dpll_reg); 44989c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Wait for the clocks to stabilize. */ 45089c78134cc54dff016c83367912eb055637fa50cAlan Cox udelay(150); 45189c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); 45289c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_READ(dpll_reg); 45389c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Wait for the clocks to stabilize. */ 45489c78134cc54dff016c83367912eb055637fa50cAlan Cox udelay(150); 45589c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); 45689c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_READ(dpll_reg); 45789c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Wait for the clocks to stabilize. */ 45889c78134cc54dff016c83367912eb055637fa50cAlan Cox udelay(150); 45989c78134cc54dff016c83367912eb055637fa50cAlan Cox } 46089c78134cc54dff016c83367912eb055637fa50cAlan Cox 46189c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Enable the pipe */ 46289c78134cc54dff016c83367912eb055637fa50cAlan Cox temp = REG_READ(pipeconf_reg); 46389c78134cc54dff016c83367912eb055637fa50cAlan Cox if ((temp & PIPEACONF_ENABLE) == 0) 46489c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); 46589c78134cc54dff016c83367912eb055637fa50cAlan Cox 46689c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Enable the plane */ 46789c78134cc54dff016c83367912eb055637fa50cAlan Cox temp = REG_READ(dspcntr_reg); 46889c78134cc54dff016c83367912eb055637fa50cAlan Cox if ((temp & DISPLAY_PLANE_ENABLE) == 0) { 46989c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(dspcntr_reg, 47089c78134cc54dff016c83367912eb055637fa50cAlan Cox temp | DISPLAY_PLANE_ENABLE); 47189c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Flush the plane changes */ 47289c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); 47389c78134cc54dff016c83367912eb055637fa50cAlan Cox } 47489c78134cc54dff016c83367912eb055637fa50cAlan Cox 47589c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc_load_lut(crtc); 47689c78134cc54dff016c83367912eb055637fa50cAlan Cox 47789c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Give the overlay scaler a chance to enable 47889c78134cc54dff016c83367912eb055637fa50cAlan Cox * if it's on this pipe */ 47989c78134cc54dff016c83367912eb055637fa50cAlan Cox /* psb_intel_crtc_dpms_video(crtc, true); TODO */ 48089c78134cc54dff016c83367912eb055637fa50cAlan Cox break; 48189c78134cc54dff016c83367912eb055637fa50cAlan Cox case DRM_MODE_DPMS_OFF: 48289c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Give the overlay scaler a chance to disable 48389c78134cc54dff016c83367912eb055637fa50cAlan Cox * if it's on this pipe */ 48489c78134cc54dff016c83367912eb055637fa50cAlan Cox /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */ 48589c78134cc54dff016c83367912eb055637fa50cAlan Cox 48689c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Disable the VGA plane that we never use */ 48789c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); 48889c78134cc54dff016c83367912eb055637fa50cAlan Cox 48989c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Disable display plane */ 49089c78134cc54dff016c83367912eb055637fa50cAlan Cox temp = REG_READ(dspcntr_reg); 49189c78134cc54dff016c83367912eb055637fa50cAlan Cox if ((temp & DISPLAY_PLANE_ENABLE) != 0) { 49289c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(dspcntr_reg, 49389c78134cc54dff016c83367912eb055637fa50cAlan Cox temp & ~DISPLAY_PLANE_ENABLE); 49489c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Flush the plane changes */ 49589c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); 49689c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_READ(dspbase_reg); 49789c78134cc54dff016c83367912eb055637fa50cAlan Cox } 49889c78134cc54dff016c83367912eb055637fa50cAlan Cox 49989c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Next, disable display pipes */ 50089c78134cc54dff016c83367912eb055637fa50cAlan Cox temp = REG_READ(pipeconf_reg); 50189c78134cc54dff016c83367912eb055637fa50cAlan Cox if ((temp & PIPEACONF_ENABLE) != 0) { 50289c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); 50389c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_READ(pipeconf_reg); 50489c78134cc54dff016c83367912eb055637fa50cAlan Cox } 50589c78134cc54dff016c83367912eb055637fa50cAlan Cox 50689c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Wait for vblank for the disable to take effect. */ 50789c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_wait_for_vblank(dev); 50889c78134cc54dff016c83367912eb055637fa50cAlan Cox 50989c78134cc54dff016c83367912eb055637fa50cAlan Cox temp = REG_READ(dpll_reg); 51089c78134cc54dff016c83367912eb055637fa50cAlan Cox if ((temp & DPLL_VCO_ENABLE) != 0) { 51189c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); 51289c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_READ(dpll_reg); 51389c78134cc54dff016c83367912eb055637fa50cAlan Cox } 51489c78134cc54dff016c83367912eb055637fa50cAlan Cox 51589c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Wait for the clocks to turn off. */ 51689c78134cc54dff016c83367912eb055637fa50cAlan Cox udelay(150); 51789c78134cc54dff016c83367912eb055637fa50cAlan Cox break; 51889c78134cc54dff016c83367912eb055637fa50cAlan Cox } 51989c78134cc54dff016c83367912eb055637fa50cAlan Cox 52089c78134cc54dff016c83367912eb055637fa50cAlan Cox /*Set FIFO Watermarks*/ 52189c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(DSPARB, 0x3F3E); 52289c78134cc54dff016c83367912eb055637fa50cAlan Cox} 52389c78134cc54dff016c83367912eb055637fa50cAlan Cox 52489c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic void psb_intel_crtc_prepare(struct drm_crtc *crtc) 52589c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 52689c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 52789c78134cc54dff016c83367912eb055637fa50cAlan Cox crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); 52889c78134cc54dff016c83367912eb055637fa50cAlan Cox} 52989c78134cc54dff016c83367912eb055637fa50cAlan Cox 53089c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic void psb_intel_crtc_commit(struct drm_crtc *crtc) 53189c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 53289c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 53389c78134cc54dff016c83367912eb055637fa50cAlan Cox crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); 53489c78134cc54dff016c83367912eb055637fa50cAlan Cox} 53589c78134cc54dff016c83367912eb055637fa50cAlan Cox 53689c78134cc54dff016c83367912eb055637fa50cAlan Coxvoid psb_intel_encoder_prepare(struct drm_encoder *encoder) 53789c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 53889c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_encoder_helper_funcs *encoder_funcs = 53989c78134cc54dff016c83367912eb055637fa50cAlan Cox encoder->helper_private; 54089c78134cc54dff016c83367912eb055637fa50cAlan Cox /* lvds has its own version of prepare see psb_intel_lvds_prepare */ 54189c78134cc54dff016c83367912eb055637fa50cAlan Cox encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF); 54289c78134cc54dff016c83367912eb055637fa50cAlan Cox} 54389c78134cc54dff016c83367912eb055637fa50cAlan Cox 54489c78134cc54dff016c83367912eb055637fa50cAlan Coxvoid psb_intel_encoder_commit(struct drm_encoder *encoder) 54589c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 54689c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_encoder_helper_funcs *encoder_funcs = 54789c78134cc54dff016c83367912eb055637fa50cAlan Cox encoder->helper_private; 54889c78134cc54dff016c83367912eb055637fa50cAlan Cox /* lvds has its own version of commit see psb_intel_lvds_commit */ 54989c78134cc54dff016c83367912eb055637fa50cAlan Cox encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); 55089c78134cc54dff016c83367912eb055637fa50cAlan Cox} 55189c78134cc54dff016c83367912eb055637fa50cAlan Cox 5525736995b473b8853d5ee048c7dfb9c1d20ebf0eaPatrik Jakobssonvoid psb_intel_encoder_destroy(struct drm_encoder *encoder) 5535736995b473b8853d5ee048c7dfb9c1d20ebf0eaPatrik Jakobsson{ 5545736995b473b8853d5ee048c7dfb9c1d20ebf0eaPatrik Jakobsson struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder); 5555736995b473b8853d5ee048c7dfb9c1d20ebf0eaPatrik Jakobsson 5565736995b473b8853d5ee048c7dfb9c1d20ebf0eaPatrik Jakobsson drm_encoder_cleanup(encoder); 5575736995b473b8853d5ee048c7dfb9c1d20ebf0eaPatrik Jakobsson kfree(intel_encoder); 5585736995b473b8853d5ee048c7dfb9c1d20ebf0eaPatrik Jakobsson} 5595736995b473b8853d5ee048c7dfb9c1d20ebf0eaPatrik Jakobsson 56089c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc, 56189c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_display_mode *mode, 56289c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_display_mode *adjusted_mode) 56389c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 56489c78134cc54dff016c83367912eb055637fa50cAlan Cox return true; 56589c78134cc54dff016c83367912eb055637fa50cAlan Cox} 56689c78134cc54dff016c83367912eb055637fa50cAlan Cox 56789c78134cc54dff016c83367912eb055637fa50cAlan Cox 56889c78134cc54dff016c83367912eb055637fa50cAlan Cox/** 56989c78134cc54dff016c83367912eb055637fa50cAlan Cox * Return the pipe currently connected to the panel fitter, 57089c78134cc54dff016c83367912eb055637fa50cAlan Cox * or -1 if the panel fitter is not present or not in use 57189c78134cc54dff016c83367912eb055637fa50cAlan Cox */ 57289c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic int psb_intel_panel_fitter_pipe(struct drm_device *dev) 57389c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 57489c78134cc54dff016c83367912eb055637fa50cAlan Cox u32 pfit_control; 57589c78134cc54dff016c83367912eb055637fa50cAlan Cox 57689c78134cc54dff016c83367912eb055637fa50cAlan Cox pfit_control = REG_READ(PFIT_CONTROL); 57789c78134cc54dff016c83367912eb055637fa50cAlan Cox 57889c78134cc54dff016c83367912eb055637fa50cAlan Cox /* See if the panel fitter is in use */ 57989c78134cc54dff016c83367912eb055637fa50cAlan Cox if ((pfit_control & PFIT_ENABLE) == 0) 58089c78134cc54dff016c83367912eb055637fa50cAlan Cox return -1; 58189c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Must be on PIPE 1 for PSB */ 58289c78134cc54dff016c83367912eb055637fa50cAlan Cox return 1; 58389c78134cc54dff016c83367912eb055637fa50cAlan Cox} 58489c78134cc54dff016c83367912eb055637fa50cAlan Cox 58589c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic int psb_intel_crtc_mode_set(struct drm_crtc *crtc, 58689c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_display_mode *mode, 58789c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_display_mode *adjusted_mode, 58889c78134cc54dff016c83367912eb055637fa50cAlan Cox int x, int y, 58989c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_framebuffer *old_fb) 59089c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 59189c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_device *dev = crtc->dev; 59289c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 59389c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 59489c78134cc54dff016c83367912eb055637fa50cAlan Cox int pipe = psb_intel_crtc->pipe; 59589c78134cc54dff016c83367912eb055637fa50cAlan Cox int fp_reg = (pipe == 0) ? FPA0 : FPB0; 59689c78134cc54dff016c83367912eb055637fa50cAlan Cox int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; 59789c78134cc54dff016c83367912eb055637fa50cAlan Cox int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; 59889c78134cc54dff016c83367912eb055637fa50cAlan Cox int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; 59989c78134cc54dff016c83367912eb055637fa50cAlan Cox int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; 60089c78134cc54dff016c83367912eb055637fa50cAlan Cox int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; 60189c78134cc54dff016c83367912eb055637fa50cAlan Cox int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; 60289c78134cc54dff016c83367912eb055637fa50cAlan Cox int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; 60389c78134cc54dff016c83367912eb055637fa50cAlan Cox int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; 60489c78134cc54dff016c83367912eb055637fa50cAlan Cox int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; 60589c78134cc54dff016c83367912eb055637fa50cAlan Cox int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; 60689c78134cc54dff016c83367912eb055637fa50cAlan Cox int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; 60789c78134cc54dff016c83367912eb055637fa50cAlan Cox int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; 60889c78134cc54dff016c83367912eb055637fa50cAlan Cox int refclk; 60989c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_clock_t clock; 61089c78134cc54dff016c83367912eb055637fa50cAlan Cox u32 dpll = 0, fp = 0, dspcntr, pipeconf; 6112e33d6b92ff3298c06e87661040c5401e1099ea5Kirill A. Shutemov bool ok, is_sdvo = false; 6122e33d6b92ff3298c06e87661040c5401e1099ea5Kirill A. Shutemov bool is_lvds = false, is_tv = false; 61389c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_mode_config *mode_config = &dev->mode_config; 61489c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_connector *connector; 61589c78134cc54dff016c83367912eb055637fa50cAlan Cox 61689c78134cc54dff016c83367912eb055637fa50cAlan Cox /* No scan out no play */ 61789c78134cc54dff016c83367912eb055637fa50cAlan Cox if (crtc->fb == NULL) { 61889c78134cc54dff016c83367912eb055637fa50cAlan Cox crtc_funcs->mode_set_base(crtc, x, y, old_fb); 61989c78134cc54dff016c83367912eb055637fa50cAlan Cox return 0; 62089c78134cc54dff016c83367912eb055637fa50cAlan Cox } 62189c78134cc54dff016c83367912eb055637fa50cAlan Cox 62289c78134cc54dff016c83367912eb055637fa50cAlan Cox list_for_each_entry(connector, &mode_config->connector_list, head) { 6231730f89bfcff353484672cdcefbef13b2f374176Patrik Jakobsson struct psb_intel_encoder *psb_intel_encoder = 6241730f89bfcff353484672cdcefbef13b2f374176Patrik Jakobsson psb_intel_attached_encoder(connector); 62589c78134cc54dff016c83367912eb055637fa50cAlan Cox 62689c78134cc54dff016c83367912eb055637fa50cAlan Cox if (!connector->encoder 62789c78134cc54dff016c83367912eb055637fa50cAlan Cox || connector->encoder->crtc != crtc) 62889c78134cc54dff016c83367912eb055637fa50cAlan Cox continue; 62989c78134cc54dff016c83367912eb055637fa50cAlan Cox 6301730f89bfcff353484672cdcefbef13b2f374176Patrik Jakobsson switch (psb_intel_encoder->type) { 63189c78134cc54dff016c83367912eb055637fa50cAlan Cox case INTEL_OUTPUT_LVDS: 63289c78134cc54dff016c83367912eb055637fa50cAlan Cox is_lvds = true; 63389c78134cc54dff016c83367912eb055637fa50cAlan Cox break; 63489c78134cc54dff016c83367912eb055637fa50cAlan Cox case INTEL_OUTPUT_SDVO: 63589c78134cc54dff016c83367912eb055637fa50cAlan Cox is_sdvo = true; 63689c78134cc54dff016c83367912eb055637fa50cAlan Cox break; 63789c78134cc54dff016c83367912eb055637fa50cAlan Cox case INTEL_OUTPUT_TVOUT: 63889c78134cc54dff016c83367912eb055637fa50cAlan Cox is_tv = true; 63989c78134cc54dff016c83367912eb055637fa50cAlan Cox break; 64089c78134cc54dff016c83367912eb055637fa50cAlan Cox } 64189c78134cc54dff016c83367912eb055637fa50cAlan Cox } 64289c78134cc54dff016c83367912eb055637fa50cAlan Cox 64389c78134cc54dff016c83367912eb055637fa50cAlan Cox refclk = 96000; 64489c78134cc54dff016c83367912eb055637fa50cAlan Cox 64589c78134cc54dff016c83367912eb055637fa50cAlan Cox ok = psb_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, 64689c78134cc54dff016c83367912eb055637fa50cAlan Cox &clock); 64789c78134cc54dff016c83367912eb055637fa50cAlan Cox if (!ok) { 64889c78134cc54dff016c83367912eb055637fa50cAlan Cox dev_err(dev->dev, "Couldn't find PLL settings for mode!\n"); 64989c78134cc54dff016c83367912eb055637fa50cAlan Cox return 0; 65089c78134cc54dff016c83367912eb055637fa50cAlan Cox } 65189c78134cc54dff016c83367912eb055637fa50cAlan Cox 65289c78134cc54dff016c83367912eb055637fa50cAlan Cox fp = clock.n << 16 | clock.m1 << 8 | clock.m2; 65389c78134cc54dff016c83367912eb055637fa50cAlan Cox 65489c78134cc54dff016c83367912eb055637fa50cAlan Cox dpll = DPLL_VGA_MODE_DIS; 65589c78134cc54dff016c83367912eb055637fa50cAlan Cox if (is_lvds) { 65689c78134cc54dff016c83367912eb055637fa50cAlan Cox dpll |= DPLLB_MODE_LVDS; 65789c78134cc54dff016c83367912eb055637fa50cAlan Cox dpll |= DPLL_DVO_HIGH_SPEED; 65889c78134cc54dff016c83367912eb055637fa50cAlan Cox } else 65989c78134cc54dff016c83367912eb055637fa50cAlan Cox dpll |= DPLLB_MODE_DAC_SERIAL; 66089c78134cc54dff016c83367912eb055637fa50cAlan Cox if (is_sdvo) { 66189c78134cc54dff016c83367912eb055637fa50cAlan Cox int sdvo_pixel_multiply = 66289c78134cc54dff016c83367912eb055637fa50cAlan Cox adjusted_mode->clock / mode->clock; 66389c78134cc54dff016c83367912eb055637fa50cAlan Cox dpll |= DPLL_DVO_HIGH_SPEED; 66489c78134cc54dff016c83367912eb055637fa50cAlan Cox dpll |= 66589c78134cc54dff016c83367912eb055637fa50cAlan Cox (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; 66689c78134cc54dff016c83367912eb055637fa50cAlan Cox } 66789c78134cc54dff016c83367912eb055637fa50cAlan Cox 66889c78134cc54dff016c83367912eb055637fa50cAlan Cox /* compute bitmask from p1 value */ 66989c78134cc54dff016c83367912eb055637fa50cAlan Cox dpll |= (1 << (clock.p1 - 1)) << 16; 67089c78134cc54dff016c83367912eb055637fa50cAlan Cox switch (clock.p2) { 67189c78134cc54dff016c83367912eb055637fa50cAlan Cox case 5: 67289c78134cc54dff016c83367912eb055637fa50cAlan Cox dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; 67389c78134cc54dff016c83367912eb055637fa50cAlan Cox break; 67489c78134cc54dff016c83367912eb055637fa50cAlan Cox case 7: 67589c78134cc54dff016c83367912eb055637fa50cAlan Cox dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7; 67689c78134cc54dff016c83367912eb055637fa50cAlan Cox break; 67789c78134cc54dff016c83367912eb055637fa50cAlan Cox case 10: 67889c78134cc54dff016c83367912eb055637fa50cAlan Cox dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10; 67989c78134cc54dff016c83367912eb055637fa50cAlan Cox break; 68089c78134cc54dff016c83367912eb055637fa50cAlan Cox case 14: 68189c78134cc54dff016c83367912eb055637fa50cAlan Cox dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; 68289c78134cc54dff016c83367912eb055637fa50cAlan Cox break; 68389c78134cc54dff016c83367912eb055637fa50cAlan Cox } 68489c78134cc54dff016c83367912eb055637fa50cAlan Cox 68589c78134cc54dff016c83367912eb055637fa50cAlan Cox if (is_tv) { 68689c78134cc54dff016c83367912eb055637fa50cAlan Cox /* XXX: just matching BIOS for now */ 68789c78134cc54dff016c83367912eb055637fa50cAlan Cox/* dpll |= PLL_REF_INPUT_TVCLKINBC; */ 68889c78134cc54dff016c83367912eb055637fa50cAlan Cox dpll |= 3; 68989c78134cc54dff016c83367912eb055637fa50cAlan Cox } 69089c78134cc54dff016c83367912eb055637fa50cAlan Cox dpll |= PLL_REF_INPUT_DREFCLK; 69189c78134cc54dff016c83367912eb055637fa50cAlan Cox 69289c78134cc54dff016c83367912eb055637fa50cAlan Cox /* setup pipeconf */ 69389c78134cc54dff016c83367912eb055637fa50cAlan Cox pipeconf = REG_READ(pipeconf_reg); 69489c78134cc54dff016c83367912eb055637fa50cAlan Cox 69589c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Set up the display plane register */ 69689c78134cc54dff016c83367912eb055637fa50cAlan Cox dspcntr = DISPPLANE_GAMMA_ENABLE; 69789c78134cc54dff016c83367912eb055637fa50cAlan Cox 69889c78134cc54dff016c83367912eb055637fa50cAlan Cox if (pipe == 0) 69989c78134cc54dff016c83367912eb055637fa50cAlan Cox dspcntr |= DISPPLANE_SEL_PIPE_A; 70089c78134cc54dff016c83367912eb055637fa50cAlan Cox else 70189c78134cc54dff016c83367912eb055637fa50cAlan Cox dspcntr |= DISPPLANE_SEL_PIPE_B; 70289c78134cc54dff016c83367912eb055637fa50cAlan Cox 70389c78134cc54dff016c83367912eb055637fa50cAlan Cox dspcntr |= DISPLAY_PLANE_ENABLE; 70489c78134cc54dff016c83367912eb055637fa50cAlan Cox pipeconf |= PIPEACONF_ENABLE; 70589c78134cc54dff016c83367912eb055637fa50cAlan Cox dpll |= DPLL_VCO_ENABLE; 70689c78134cc54dff016c83367912eb055637fa50cAlan Cox 70789c78134cc54dff016c83367912eb055637fa50cAlan Cox 70889c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Disable the panel fitter if it was on our pipe */ 70989c78134cc54dff016c83367912eb055637fa50cAlan Cox if (psb_intel_panel_fitter_pipe(dev) == pipe) 71089c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(PFIT_CONTROL, 0); 71189c78134cc54dff016c83367912eb055637fa50cAlan Cox 71289c78134cc54dff016c83367912eb055637fa50cAlan Cox drm_mode_debug_printmodeline(mode); 71389c78134cc54dff016c83367912eb055637fa50cAlan Cox 71489c78134cc54dff016c83367912eb055637fa50cAlan Cox if (dpll & DPLL_VCO_ENABLE) { 71589c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(fp_reg, fp); 71689c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); 71789c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_READ(dpll_reg); 71889c78134cc54dff016c83367912eb055637fa50cAlan Cox udelay(150); 71989c78134cc54dff016c83367912eb055637fa50cAlan Cox } 72089c78134cc54dff016c83367912eb055637fa50cAlan Cox 72189c78134cc54dff016c83367912eb055637fa50cAlan Cox /* The LVDS pin pair needs to be on before the DPLLs are enabled. 72289c78134cc54dff016c83367912eb055637fa50cAlan Cox * This is an exception to the general rule that mode_set doesn't turn 72389c78134cc54dff016c83367912eb055637fa50cAlan Cox * things on. 72489c78134cc54dff016c83367912eb055637fa50cAlan Cox */ 72589c78134cc54dff016c83367912eb055637fa50cAlan Cox if (is_lvds) { 72689c78134cc54dff016c83367912eb055637fa50cAlan Cox u32 lvds = REG_READ(LVDS); 72789c78134cc54dff016c83367912eb055637fa50cAlan Cox 72889c78134cc54dff016c83367912eb055637fa50cAlan Cox lvds &= ~LVDS_PIPEB_SELECT; 72989c78134cc54dff016c83367912eb055637fa50cAlan Cox if (pipe == 1) 73089c78134cc54dff016c83367912eb055637fa50cAlan Cox lvds |= LVDS_PIPEB_SELECT; 73189c78134cc54dff016c83367912eb055637fa50cAlan Cox 73289c78134cc54dff016c83367912eb055637fa50cAlan Cox lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; 73389c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Set the B0-B3 data pairs corresponding to 73489c78134cc54dff016c83367912eb055637fa50cAlan Cox * whether we're going to 73589c78134cc54dff016c83367912eb055637fa50cAlan Cox * set the DPLLs for dual-channel mode or not. 73689c78134cc54dff016c83367912eb055637fa50cAlan Cox */ 73789c78134cc54dff016c83367912eb055637fa50cAlan Cox lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); 73889c78134cc54dff016c83367912eb055637fa50cAlan Cox if (clock.p2 == 7) 73989c78134cc54dff016c83367912eb055637fa50cAlan Cox lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; 74089c78134cc54dff016c83367912eb055637fa50cAlan Cox 74189c78134cc54dff016c83367912eb055637fa50cAlan Cox /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP) 74289c78134cc54dff016c83367912eb055637fa50cAlan Cox * appropriately here, but we need to look more 74389c78134cc54dff016c83367912eb055637fa50cAlan Cox * thoroughly into how panels behave in the two modes. 74489c78134cc54dff016c83367912eb055637fa50cAlan Cox */ 74589c78134cc54dff016c83367912eb055637fa50cAlan Cox 74689c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(LVDS, lvds); 74789c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_READ(LVDS); 74889c78134cc54dff016c83367912eb055637fa50cAlan Cox } 74989c78134cc54dff016c83367912eb055637fa50cAlan Cox 75089c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(fp_reg, fp); 75189c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(dpll_reg, dpll); 75289c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_READ(dpll_reg); 75389c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Wait for the clocks to stabilize. */ 75489c78134cc54dff016c83367912eb055637fa50cAlan Cox udelay(150); 75589c78134cc54dff016c83367912eb055637fa50cAlan Cox 75689c78134cc54dff016c83367912eb055637fa50cAlan Cox /* write it again -- the BIOS does, after all */ 75789c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(dpll_reg, dpll); 75889c78134cc54dff016c83367912eb055637fa50cAlan Cox 75989c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_READ(dpll_reg); 76089c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Wait for the clocks to stabilize. */ 76189c78134cc54dff016c83367912eb055637fa50cAlan Cox udelay(150); 76289c78134cc54dff016c83367912eb055637fa50cAlan Cox 76389c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | 76489c78134cc54dff016c83367912eb055637fa50cAlan Cox ((adjusted_mode->crtc_htotal - 1) << 16)); 76589c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | 76689c78134cc54dff016c83367912eb055637fa50cAlan Cox ((adjusted_mode->crtc_hblank_end - 1) << 16)); 76789c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | 76889c78134cc54dff016c83367912eb055637fa50cAlan Cox ((adjusted_mode->crtc_hsync_end - 1) << 16)); 76989c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | 77089c78134cc54dff016c83367912eb055637fa50cAlan Cox ((adjusted_mode->crtc_vtotal - 1) << 16)); 77189c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | 77289c78134cc54dff016c83367912eb055637fa50cAlan Cox ((adjusted_mode->crtc_vblank_end - 1) << 16)); 77389c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | 77489c78134cc54dff016c83367912eb055637fa50cAlan Cox ((adjusted_mode->crtc_vsync_end - 1) << 16)); 77589c78134cc54dff016c83367912eb055637fa50cAlan Cox /* pipesrc and dspsize control the size that is scaled from, 77689c78134cc54dff016c83367912eb055637fa50cAlan Cox * which should always be the user's requested size. 77789c78134cc54dff016c83367912eb055637fa50cAlan Cox */ 77889c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(dspsize_reg, 77989c78134cc54dff016c83367912eb055637fa50cAlan Cox ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); 78089c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(dsppos_reg, 0); 78189c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(pipesrc_reg, 78289c78134cc54dff016c83367912eb055637fa50cAlan Cox ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); 78389c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(pipeconf_reg, pipeconf); 78489c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_READ(pipeconf_reg); 78589c78134cc54dff016c83367912eb055637fa50cAlan Cox 78689c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_wait_for_vblank(dev); 78789c78134cc54dff016c83367912eb055637fa50cAlan Cox 78889c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(dspcntr_reg, dspcntr); 78989c78134cc54dff016c83367912eb055637fa50cAlan Cox 79089c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Flush the plane changes */ 79189c78134cc54dff016c83367912eb055637fa50cAlan Cox crtc_funcs->mode_set_base(crtc, x, y, old_fb); 79289c78134cc54dff016c83367912eb055637fa50cAlan Cox 79389c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_wait_for_vblank(dev); 79489c78134cc54dff016c83367912eb055637fa50cAlan Cox 79589c78134cc54dff016c83367912eb055637fa50cAlan Cox return 0; 79689c78134cc54dff016c83367912eb055637fa50cAlan Cox} 79789c78134cc54dff016c83367912eb055637fa50cAlan Cox 79889c78134cc54dff016c83367912eb055637fa50cAlan Cox/** Loads the palette/gamma unit for the CRTC with the prepared values */ 79989c78134cc54dff016c83367912eb055637fa50cAlan Coxvoid psb_intel_crtc_load_lut(struct drm_crtc *crtc) 80089c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 80189c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_device *dev = crtc->dev; 80289c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_psb_private *dev_priv = 80389c78134cc54dff016c83367912eb055637fa50cAlan Cox (struct drm_psb_private *)dev->dev_private; 80489c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 80589c78134cc54dff016c83367912eb055637fa50cAlan Cox int palreg = PALETTE_A; 80689c78134cc54dff016c83367912eb055637fa50cAlan Cox int i; 80789c78134cc54dff016c83367912eb055637fa50cAlan Cox 80889c78134cc54dff016c83367912eb055637fa50cAlan Cox /* The clocks have to be on to load the palette. */ 80989c78134cc54dff016c83367912eb055637fa50cAlan Cox if (!crtc->enabled) 81089c78134cc54dff016c83367912eb055637fa50cAlan Cox return; 81189c78134cc54dff016c83367912eb055637fa50cAlan Cox 81289c78134cc54dff016c83367912eb055637fa50cAlan Cox switch (psb_intel_crtc->pipe) { 81389c78134cc54dff016c83367912eb055637fa50cAlan Cox case 0: 81489c78134cc54dff016c83367912eb055637fa50cAlan Cox break; 81589c78134cc54dff016c83367912eb055637fa50cAlan Cox case 1: 81689c78134cc54dff016c83367912eb055637fa50cAlan Cox palreg = PALETTE_B; 81789c78134cc54dff016c83367912eb055637fa50cAlan Cox break; 81889c78134cc54dff016c83367912eb055637fa50cAlan Cox case 2: 81989c78134cc54dff016c83367912eb055637fa50cAlan Cox palreg = PALETTE_C; 82089c78134cc54dff016c83367912eb055637fa50cAlan Cox break; 82189c78134cc54dff016c83367912eb055637fa50cAlan Cox default: 82289c78134cc54dff016c83367912eb055637fa50cAlan Cox dev_err(dev->dev, "Illegal Pipe Number.\n"); 82389c78134cc54dff016c83367912eb055637fa50cAlan Cox return; 82489c78134cc54dff016c83367912eb055637fa50cAlan Cox } 82589c78134cc54dff016c83367912eb055637fa50cAlan Cox 82689c78134cc54dff016c83367912eb055637fa50cAlan Cox if (gma_power_begin(dev, false)) { 82789c78134cc54dff016c83367912eb055637fa50cAlan Cox for (i = 0; i < 256; i++) { 82889c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(palreg + 4 * i, 82989c78134cc54dff016c83367912eb055637fa50cAlan Cox ((psb_intel_crtc->lut_r[i] + 83089c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc->lut_adj[i]) << 16) | 83189c78134cc54dff016c83367912eb055637fa50cAlan Cox ((psb_intel_crtc->lut_g[i] + 83289c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc->lut_adj[i]) << 8) | 83389c78134cc54dff016c83367912eb055637fa50cAlan Cox (psb_intel_crtc->lut_b[i] + 83489c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc->lut_adj[i])); 83589c78134cc54dff016c83367912eb055637fa50cAlan Cox } 83689c78134cc54dff016c83367912eb055637fa50cAlan Cox gma_power_end(dev); 83789c78134cc54dff016c83367912eb055637fa50cAlan Cox } else { 83889c78134cc54dff016c83367912eb055637fa50cAlan Cox for (i = 0; i < 256; i++) { 839c6265ff593467d472814aa9f16f89f6c1dc90a5dAlan Cox dev_priv->regs.psb.save_palette_a[i] = 84089c78134cc54dff016c83367912eb055637fa50cAlan Cox ((psb_intel_crtc->lut_r[i] + 84189c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc->lut_adj[i]) << 16) | 84289c78134cc54dff016c83367912eb055637fa50cAlan Cox ((psb_intel_crtc->lut_g[i] + 84389c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc->lut_adj[i]) << 8) | 84489c78134cc54dff016c83367912eb055637fa50cAlan Cox (psb_intel_crtc->lut_b[i] + 84589c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc->lut_adj[i]); 84689c78134cc54dff016c83367912eb055637fa50cAlan Cox } 84789c78134cc54dff016c83367912eb055637fa50cAlan Cox 84889c78134cc54dff016c83367912eb055637fa50cAlan Cox } 84989c78134cc54dff016c83367912eb055637fa50cAlan Cox} 85089c78134cc54dff016c83367912eb055637fa50cAlan Cox 85189c78134cc54dff016c83367912eb055637fa50cAlan Cox/** 85289c78134cc54dff016c83367912eb055637fa50cAlan Cox * Save HW states of giving crtc 85389c78134cc54dff016c83367912eb055637fa50cAlan Cox */ 85489c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic void psb_intel_crtc_save(struct drm_crtc *crtc) 85589c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 85689c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_device *dev = crtc->dev; 85789c78134cc54dff016c83367912eb055637fa50cAlan Cox /* struct drm_psb_private *dev_priv = 85889c78134cc54dff016c83367912eb055637fa50cAlan Cox (struct drm_psb_private *)dev->dev_private; */ 85989c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 86089c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state; 86189c78134cc54dff016c83367912eb055637fa50cAlan Cox int pipeA = (psb_intel_crtc->pipe == 0); 86289c78134cc54dff016c83367912eb055637fa50cAlan Cox uint32_t paletteReg; 86389c78134cc54dff016c83367912eb055637fa50cAlan Cox int i; 86489c78134cc54dff016c83367912eb055637fa50cAlan Cox 86589c78134cc54dff016c83367912eb055637fa50cAlan Cox if (!crtc_state) { 86689c78134cc54dff016c83367912eb055637fa50cAlan Cox dev_err(dev->dev, "No CRTC state found\n"); 86789c78134cc54dff016c83367912eb055637fa50cAlan Cox return; 86889c78134cc54dff016c83367912eb055637fa50cAlan Cox } 86989c78134cc54dff016c83367912eb055637fa50cAlan Cox 87089c78134cc54dff016c83367912eb055637fa50cAlan Cox crtc_state->saveDSPCNTR = REG_READ(pipeA ? DSPACNTR : DSPBCNTR); 87189c78134cc54dff016c83367912eb055637fa50cAlan Cox crtc_state->savePIPECONF = REG_READ(pipeA ? PIPEACONF : PIPEBCONF); 87289c78134cc54dff016c83367912eb055637fa50cAlan Cox crtc_state->savePIPESRC = REG_READ(pipeA ? PIPEASRC : PIPEBSRC); 87389c78134cc54dff016c83367912eb055637fa50cAlan Cox crtc_state->saveFP0 = REG_READ(pipeA ? FPA0 : FPB0); 87489c78134cc54dff016c83367912eb055637fa50cAlan Cox crtc_state->saveFP1 = REG_READ(pipeA ? FPA1 : FPB1); 87589c78134cc54dff016c83367912eb055637fa50cAlan Cox crtc_state->saveDPLL = REG_READ(pipeA ? DPLL_A : DPLL_B); 87689c78134cc54dff016c83367912eb055637fa50cAlan Cox crtc_state->saveHTOTAL = REG_READ(pipeA ? HTOTAL_A : HTOTAL_B); 87789c78134cc54dff016c83367912eb055637fa50cAlan Cox crtc_state->saveHBLANK = REG_READ(pipeA ? HBLANK_A : HBLANK_B); 87889c78134cc54dff016c83367912eb055637fa50cAlan Cox crtc_state->saveHSYNC = REG_READ(pipeA ? HSYNC_A : HSYNC_B); 87989c78134cc54dff016c83367912eb055637fa50cAlan Cox crtc_state->saveVTOTAL = REG_READ(pipeA ? VTOTAL_A : VTOTAL_B); 88089c78134cc54dff016c83367912eb055637fa50cAlan Cox crtc_state->saveVBLANK = REG_READ(pipeA ? VBLANK_A : VBLANK_B); 88189c78134cc54dff016c83367912eb055637fa50cAlan Cox crtc_state->saveVSYNC = REG_READ(pipeA ? VSYNC_A : VSYNC_B); 88289c78134cc54dff016c83367912eb055637fa50cAlan Cox crtc_state->saveDSPSTRIDE = REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE); 88389c78134cc54dff016c83367912eb055637fa50cAlan Cox 88489c78134cc54dff016c83367912eb055637fa50cAlan Cox /*NOTE: DSPSIZE DSPPOS only for psb*/ 88589c78134cc54dff016c83367912eb055637fa50cAlan Cox crtc_state->saveDSPSIZE = REG_READ(pipeA ? DSPASIZE : DSPBSIZE); 88689c78134cc54dff016c83367912eb055637fa50cAlan Cox crtc_state->saveDSPPOS = REG_READ(pipeA ? DSPAPOS : DSPBPOS); 88789c78134cc54dff016c83367912eb055637fa50cAlan Cox 88889c78134cc54dff016c83367912eb055637fa50cAlan Cox crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE); 88989c78134cc54dff016c83367912eb055637fa50cAlan Cox 89089c78134cc54dff016c83367912eb055637fa50cAlan Cox paletteReg = pipeA ? PALETTE_A : PALETTE_B; 89189c78134cc54dff016c83367912eb055637fa50cAlan Cox for (i = 0; i < 256; ++i) 89289c78134cc54dff016c83367912eb055637fa50cAlan Cox crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2)); 89389c78134cc54dff016c83367912eb055637fa50cAlan Cox} 89489c78134cc54dff016c83367912eb055637fa50cAlan Cox 89589c78134cc54dff016c83367912eb055637fa50cAlan Cox/** 89689c78134cc54dff016c83367912eb055637fa50cAlan Cox * Restore HW states of giving crtc 89789c78134cc54dff016c83367912eb055637fa50cAlan Cox */ 89889c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic void psb_intel_crtc_restore(struct drm_crtc *crtc) 89989c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 90089c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_device *dev = crtc->dev; 90189c78134cc54dff016c83367912eb055637fa50cAlan Cox /* struct drm_psb_private * dev_priv = 90289c78134cc54dff016c83367912eb055637fa50cAlan Cox (struct drm_psb_private *)dev->dev_private; */ 90389c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 90489c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state; 90589c78134cc54dff016c83367912eb055637fa50cAlan Cox /* struct drm_crtc_helper_funcs * crtc_funcs = crtc->helper_private; */ 90689c78134cc54dff016c83367912eb055637fa50cAlan Cox int pipeA = (psb_intel_crtc->pipe == 0); 90789c78134cc54dff016c83367912eb055637fa50cAlan Cox uint32_t paletteReg; 90889c78134cc54dff016c83367912eb055637fa50cAlan Cox int i; 90989c78134cc54dff016c83367912eb055637fa50cAlan Cox 91089c78134cc54dff016c83367912eb055637fa50cAlan Cox if (!crtc_state) { 91189c78134cc54dff016c83367912eb055637fa50cAlan Cox dev_err(dev->dev, "No crtc state\n"); 91289c78134cc54dff016c83367912eb055637fa50cAlan Cox return; 91389c78134cc54dff016c83367912eb055637fa50cAlan Cox } 91489c78134cc54dff016c83367912eb055637fa50cAlan Cox 91589c78134cc54dff016c83367912eb055637fa50cAlan Cox if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) { 91689c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(pipeA ? DPLL_A : DPLL_B, 91789c78134cc54dff016c83367912eb055637fa50cAlan Cox crtc_state->saveDPLL & ~DPLL_VCO_ENABLE); 91889c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_READ(pipeA ? DPLL_A : DPLL_B); 91989c78134cc54dff016c83367912eb055637fa50cAlan Cox udelay(150); 92089c78134cc54dff016c83367912eb055637fa50cAlan Cox } 92189c78134cc54dff016c83367912eb055637fa50cAlan Cox 92289c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(pipeA ? FPA0 : FPB0, crtc_state->saveFP0); 92389c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_READ(pipeA ? FPA0 : FPB0); 92489c78134cc54dff016c83367912eb055637fa50cAlan Cox 92589c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(pipeA ? FPA1 : FPB1, crtc_state->saveFP1); 92689c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_READ(pipeA ? FPA1 : FPB1); 92789c78134cc54dff016c83367912eb055637fa50cAlan Cox 92889c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(pipeA ? DPLL_A : DPLL_B, crtc_state->saveDPLL); 92989c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_READ(pipeA ? DPLL_A : DPLL_B); 93089c78134cc54dff016c83367912eb055637fa50cAlan Cox udelay(150); 93189c78134cc54dff016c83367912eb055637fa50cAlan Cox 93289c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(pipeA ? HTOTAL_A : HTOTAL_B, crtc_state->saveHTOTAL); 93389c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(pipeA ? HBLANK_A : HBLANK_B, crtc_state->saveHBLANK); 93489c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(pipeA ? HSYNC_A : HSYNC_B, crtc_state->saveHSYNC); 93589c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(pipeA ? VTOTAL_A : VTOTAL_B, crtc_state->saveVTOTAL); 93689c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(pipeA ? VBLANK_A : VBLANK_B, crtc_state->saveVBLANK); 93789c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(pipeA ? VSYNC_A : VSYNC_B, crtc_state->saveVSYNC); 93889c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(pipeA ? DSPASTRIDE : DSPBSTRIDE, crtc_state->saveDSPSTRIDE); 93989c78134cc54dff016c83367912eb055637fa50cAlan Cox 94089c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(pipeA ? DSPASIZE : DSPBSIZE, crtc_state->saveDSPSIZE); 94189c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(pipeA ? DSPAPOS : DSPBPOS, crtc_state->saveDSPPOS); 94289c78134cc54dff016c83367912eb055637fa50cAlan Cox 94389c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(pipeA ? PIPEASRC : PIPEBSRC, crtc_state->savePIPESRC); 94489c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE); 94589c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(pipeA ? PIPEACONF : PIPEBCONF, crtc_state->savePIPECONF); 94689c78134cc54dff016c83367912eb055637fa50cAlan Cox 94789c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_wait_for_vblank(dev); 94889c78134cc54dff016c83367912eb055637fa50cAlan Cox 94989c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(pipeA ? DSPACNTR : DSPBCNTR, crtc_state->saveDSPCNTR); 95089c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE); 95189c78134cc54dff016c83367912eb055637fa50cAlan Cox 95289c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_wait_for_vblank(dev); 95389c78134cc54dff016c83367912eb055637fa50cAlan Cox 95489c78134cc54dff016c83367912eb055637fa50cAlan Cox paletteReg = pipeA ? PALETTE_A : PALETTE_B; 95589c78134cc54dff016c83367912eb055637fa50cAlan Cox for (i = 0; i < 256; ++i) 95689c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]); 95789c78134cc54dff016c83367912eb055637fa50cAlan Cox} 95889c78134cc54dff016c83367912eb055637fa50cAlan Cox 95989c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic int psb_intel_crtc_cursor_set(struct drm_crtc *crtc, 96089c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_file *file_priv, 96189c78134cc54dff016c83367912eb055637fa50cAlan Cox uint32_t handle, 96289c78134cc54dff016c83367912eb055637fa50cAlan Cox uint32_t width, uint32_t height) 96389c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 96489c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_device *dev = crtc->dev; 96589c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 96689c78134cc54dff016c83367912eb055637fa50cAlan Cox int pipe = psb_intel_crtc->pipe; 96789c78134cc54dff016c83367912eb055637fa50cAlan Cox uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; 96889c78134cc54dff016c83367912eb055637fa50cAlan Cox uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; 96989c78134cc54dff016c83367912eb055637fa50cAlan Cox uint32_t temp; 97089c78134cc54dff016c83367912eb055637fa50cAlan Cox size_t addr = 0; 97189c78134cc54dff016c83367912eb055637fa50cAlan Cox struct gtt_range *gt; 97289c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_gem_object *obj; 97389c78134cc54dff016c83367912eb055637fa50cAlan Cox int ret; 97489c78134cc54dff016c83367912eb055637fa50cAlan Cox 97589c78134cc54dff016c83367912eb055637fa50cAlan Cox /* if we want to turn of the cursor ignore width and height */ 97689c78134cc54dff016c83367912eb055637fa50cAlan Cox if (!handle) { 97789c78134cc54dff016c83367912eb055637fa50cAlan Cox /* turn off the cursor */ 97889c78134cc54dff016c83367912eb055637fa50cAlan Cox temp = CURSOR_MODE_DISABLE; 97989c78134cc54dff016c83367912eb055637fa50cAlan Cox 98089c78134cc54dff016c83367912eb055637fa50cAlan Cox if (gma_power_begin(dev, false)) { 98189c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(control, temp); 98289c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(base, 0); 98389c78134cc54dff016c83367912eb055637fa50cAlan Cox gma_power_end(dev); 98489c78134cc54dff016c83367912eb055637fa50cAlan Cox } 98589c78134cc54dff016c83367912eb055637fa50cAlan Cox 98689c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Unpin the old GEM object */ 98789c78134cc54dff016c83367912eb055637fa50cAlan Cox if (psb_intel_crtc->cursor_obj) { 98889c78134cc54dff016c83367912eb055637fa50cAlan Cox gt = container_of(psb_intel_crtc->cursor_obj, 98989c78134cc54dff016c83367912eb055637fa50cAlan Cox struct gtt_range, gem); 99089c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_gtt_unpin(gt); 99189c78134cc54dff016c83367912eb055637fa50cAlan Cox drm_gem_object_unreference(psb_intel_crtc->cursor_obj); 99289c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc->cursor_obj = NULL; 99389c78134cc54dff016c83367912eb055637fa50cAlan Cox } 99489c78134cc54dff016c83367912eb055637fa50cAlan Cox 99589c78134cc54dff016c83367912eb055637fa50cAlan Cox return 0; 99689c78134cc54dff016c83367912eb055637fa50cAlan Cox } 99789c78134cc54dff016c83367912eb055637fa50cAlan Cox 99889c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Currently we only support 64x64 cursors */ 99989c78134cc54dff016c83367912eb055637fa50cAlan Cox if (width != 64 || height != 64) { 100089c78134cc54dff016c83367912eb055637fa50cAlan Cox dev_dbg(dev->dev, "we currently only support 64x64 cursors\n"); 100189c78134cc54dff016c83367912eb055637fa50cAlan Cox return -EINVAL; 100289c78134cc54dff016c83367912eb055637fa50cAlan Cox } 100389c78134cc54dff016c83367912eb055637fa50cAlan Cox 100489c78134cc54dff016c83367912eb055637fa50cAlan Cox obj = drm_gem_object_lookup(dev, file_priv, handle); 100589c78134cc54dff016c83367912eb055637fa50cAlan Cox if (!obj) 100689c78134cc54dff016c83367912eb055637fa50cAlan Cox return -ENOENT; 100789c78134cc54dff016c83367912eb055637fa50cAlan Cox 100889c78134cc54dff016c83367912eb055637fa50cAlan Cox if (obj->size < width * height * 4) { 100989c78134cc54dff016c83367912eb055637fa50cAlan Cox dev_dbg(dev->dev, "buffer is to small\n"); 101089c78134cc54dff016c83367912eb055637fa50cAlan Cox return -ENOMEM; 101189c78134cc54dff016c83367912eb055637fa50cAlan Cox } 101289c78134cc54dff016c83367912eb055637fa50cAlan Cox 101389c78134cc54dff016c83367912eb055637fa50cAlan Cox gt = container_of(obj, struct gtt_range, gem); 101489c78134cc54dff016c83367912eb055637fa50cAlan Cox 101589c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Pin the memory into the GTT */ 101689c78134cc54dff016c83367912eb055637fa50cAlan Cox ret = psb_gtt_pin(gt); 101789c78134cc54dff016c83367912eb055637fa50cAlan Cox if (ret) { 101889c78134cc54dff016c83367912eb055637fa50cAlan Cox dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle); 101989c78134cc54dff016c83367912eb055637fa50cAlan Cox return ret; 102089c78134cc54dff016c83367912eb055637fa50cAlan Cox } 102189c78134cc54dff016c83367912eb055637fa50cAlan Cox 102289c78134cc54dff016c83367912eb055637fa50cAlan Cox 102389c78134cc54dff016c83367912eb055637fa50cAlan Cox addr = gt->offset; /* Or resource.start ??? */ 102489c78134cc54dff016c83367912eb055637fa50cAlan Cox 102589c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc->cursor_addr = addr; 102689c78134cc54dff016c83367912eb055637fa50cAlan Cox 102789c78134cc54dff016c83367912eb055637fa50cAlan Cox temp = 0; 102889c78134cc54dff016c83367912eb055637fa50cAlan Cox /* set the pipe for the cursor */ 102989c78134cc54dff016c83367912eb055637fa50cAlan Cox temp |= (pipe << 28); 103089c78134cc54dff016c83367912eb055637fa50cAlan Cox temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; 103189c78134cc54dff016c83367912eb055637fa50cAlan Cox 103289c78134cc54dff016c83367912eb055637fa50cAlan Cox if (gma_power_begin(dev, false)) { 103389c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(control, temp); 103489c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(base, addr); 103589c78134cc54dff016c83367912eb055637fa50cAlan Cox gma_power_end(dev); 103689c78134cc54dff016c83367912eb055637fa50cAlan Cox } 103789c78134cc54dff016c83367912eb055637fa50cAlan Cox 103889c78134cc54dff016c83367912eb055637fa50cAlan Cox /* unpin the old bo */ 103989c78134cc54dff016c83367912eb055637fa50cAlan Cox if (psb_intel_crtc->cursor_obj) { 104089c78134cc54dff016c83367912eb055637fa50cAlan Cox gt = container_of(psb_intel_crtc->cursor_obj, 104189c78134cc54dff016c83367912eb055637fa50cAlan Cox struct gtt_range, gem); 104289c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_gtt_unpin(gt); 104389c78134cc54dff016c83367912eb055637fa50cAlan Cox drm_gem_object_unreference(psb_intel_crtc->cursor_obj); 104489c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc->cursor_obj = obj; 104589c78134cc54dff016c83367912eb055637fa50cAlan Cox } 104689c78134cc54dff016c83367912eb055637fa50cAlan Cox return 0; 104789c78134cc54dff016c83367912eb055637fa50cAlan Cox} 104889c78134cc54dff016c83367912eb055637fa50cAlan Cox 104989c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic int psb_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) 105089c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 105189c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_device *dev = crtc->dev; 105289c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 105389c78134cc54dff016c83367912eb055637fa50cAlan Cox int pipe = psb_intel_crtc->pipe; 105489c78134cc54dff016c83367912eb055637fa50cAlan Cox uint32_t temp = 0; 105589c78134cc54dff016c83367912eb055637fa50cAlan Cox uint32_t addr; 105689c78134cc54dff016c83367912eb055637fa50cAlan Cox 105789c78134cc54dff016c83367912eb055637fa50cAlan Cox 105889c78134cc54dff016c83367912eb055637fa50cAlan Cox if (x < 0) { 105989c78134cc54dff016c83367912eb055637fa50cAlan Cox temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT); 106089c78134cc54dff016c83367912eb055637fa50cAlan Cox x = -x; 106189c78134cc54dff016c83367912eb055637fa50cAlan Cox } 106289c78134cc54dff016c83367912eb055637fa50cAlan Cox if (y < 0) { 106389c78134cc54dff016c83367912eb055637fa50cAlan Cox temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT); 106489c78134cc54dff016c83367912eb055637fa50cAlan Cox y = -y; 106589c78134cc54dff016c83367912eb055637fa50cAlan Cox } 106689c78134cc54dff016c83367912eb055637fa50cAlan Cox 106789c78134cc54dff016c83367912eb055637fa50cAlan Cox temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT); 106889c78134cc54dff016c83367912eb055637fa50cAlan Cox temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); 106989c78134cc54dff016c83367912eb055637fa50cAlan Cox 107089c78134cc54dff016c83367912eb055637fa50cAlan Cox addr = psb_intel_crtc->cursor_addr; 107189c78134cc54dff016c83367912eb055637fa50cAlan Cox 107289c78134cc54dff016c83367912eb055637fa50cAlan Cox if (gma_power_begin(dev, false)) { 107389c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp); 107489c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, addr); 107589c78134cc54dff016c83367912eb055637fa50cAlan Cox gma_power_end(dev); 107689c78134cc54dff016c83367912eb055637fa50cAlan Cox } 107789c78134cc54dff016c83367912eb055637fa50cAlan Cox return 0; 107889c78134cc54dff016c83367912eb055637fa50cAlan Cox} 107989c78134cc54dff016c83367912eb055637fa50cAlan Cox 108089c78134cc54dff016c83367912eb055637fa50cAlan Coxvoid psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, 108189c78134cc54dff016c83367912eb055637fa50cAlan Cox u16 *green, u16 *blue, uint32_t type, uint32_t size) 108289c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 108389c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 108489c78134cc54dff016c83367912eb055637fa50cAlan Cox int i; 108589c78134cc54dff016c83367912eb055637fa50cAlan Cox 108689c78134cc54dff016c83367912eb055637fa50cAlan Cox if (size != 256) 108789c78134cc54dff016c83367912eb055637fa50cAlan Cox return; 108889c78134cc54dff016c83367912eb055637fa50cAlan Cox 108989c78134cc54dff016c83367912eb055637fa50cAlan Cox for (i = 0; i < 256; i++) { 109089c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc->lut_r[i] = red[i] >> 8; 109189c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc->lut_g[i] = green[i] >> 8; 109289c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc->lut_b[i] = blue[i] >> 8; 109389c78134cc54dff016c83367912eb055637fa50cAlan Cox } 109489c78134cc54dff016c83367912eb055637fa50cAlan Cox 109589c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc_load_lut(crtc); 109689c78134cc54dff016c83367912eb055637fa50cAlan Cox} 109789c78134cc54dff016c83367912eb055637fa50cAlan Cox 109889c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic int psb_crtc_set_config(struct drm_mode_set *set) 109989c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 110089c78134cc54dff016c83367912eb055637fa50cAlan Cox int ret; 110189c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_device *dev = set->crtc->dev; 110289c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_psb_private *dev_priv = dev->dev_private; 110389c78134cc54dff016c83367912eb055637fa50cAlan Cox 110489c78134cc54dff016c83367912eb055637fa50cAlan Cox if (!dev_priv->rpm_enabled) 110589c78134cc54dff016c83367912eb055637fa50cAlan Cox return drm_crtc_helper_set_config(set); 110689c78134cc54dff016c83367912eb055637fa50cAlan Cox 110789c78134cc54dff016c83367912eb055637fa50cAlan Cox pm_runtime_forbid(&dev->pdev->dev); 110889c78134cc54dff016c83367912eb055637fa50cAlan Cox ret = drm_crtc_helper_set_config(set); 110989c78134cc54dff016c83367912eb055637fa50cAlan Cox pm_runtime_allow(&dev->pdev->dev); 111089c78134cc54dff016c83367912eb055637fa50cAlan Cox return ret; 111189c78134cc54dff016c83367912eb055637fa50cAlan Cox} 111289c78134cc54dff016c83367912eb055637fa50cAlan Cox 111389c78134cc54dff016c83367912eb055637fa50cAlan Cox/* Returns the clock of the currently programmed mode of the given pipe. */ 111489c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic int psb_intel_crtc_clock_get(struct drm_device *dev, 111589c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_crtc *crtc) 111689c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 111789c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 111889c78134cc54dff016c83367912eb055637fa50cAlan Cox int pipe = psb_intel_crtc->pipe; 111989c78134cc54dff016c83367912eb055637fa50cAlan Cox u32 dpll; 112089c78134cc54dff016c83367912eb055637fa50cAlan Cox u32 fp; 112189c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_clock_t clock; 112289c78134cc54dff016c83367912eb055637fa50cAlan Cox bool is_lvds; 112389c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_psb_private *dev_priv = dev->dev_private; 112489c78134cc54dff016c83367912eb055637fa50cAlan Cox 112589c78134cc54dff016c83367912eb055637fa50cAlan Cox if (gma_power_begin(dev, false)) { 112689c78134cc54dff016c83367912eb055637fa50cAlan Cox dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B); 112789c78134cc54dff016c83367912eb055637fa50cAlan Cox if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) 112889c78134cc54dff016c83367912eb055637fa50cAlan Cox fp = REG_READ((pipe == 0) ? FPA0 : FPB0); 112989c78134cc54dff016c83367912eb055637fa50cAlan Cox else 113089c78134cc54dff016c83367912eb055637fa50cAlan Cox fp = REG_READ((pipe == 0) ? FPA1 : FPB1); 113189c78134cc54dff016c83367912eb055637fa50cAlan Cox is_lvds = (pipe == 1) && (REG_READ(LVDS) & LVDS_PORT_EN); 113289c78134cc54dff016c83367912eb055637fa50cAlan Cox gma_power_end(dev); 113389c78134cc54dff016c83367912eb055637fa50cAlan Cox } else { 113489c78134cc54dff016c83367912eb055637fa50cAlan Cox dpll = (pipe == 0) ? 1135c6265ff593467d472814aa9f16f89f6c1dc90a5dAlan Cox dev_priv->regs.psb.saveDPLL_A : 1136c6265ff593467d472814aa9f16f89f6c1dc90a5dAlan Cox dev_priv->regs.psb.saveDPLL_B; 113789c78134cc54dff016c83367912eb055637fa50cAlan Cox 113889c78134cc54dff016c83367912eb055637fa50cAlan Cox if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) 113989c78134cc54dff016c83367912eb055637fa50cAlan Cox fp = (pipe == 0) ? 1140c6265ff593467d472814aa9f16f89f6c1dc90a5dAlan Cox dev_priv->regs.psb.saveFPA0 : 1141c6265ff593467d472814aa9f16f89f6c1dc90a5dAlan Cox dev_priv->regs.psb.saveFPB0; 114289c78134cc54dff016c83367912eb055637fa50cAlan Cox else 114389c78134cc54dff016c83367912eb055637fa50cAlan Cox fp = (pipe == 0) ? 1144c6265ff593467d472814aa9f16f89f6c1dc90a5dAlan Cox dev_priv->regs.psb.saveFPA1 : 1145c6265ff593467d472814aa9f16f89f6c1dc90a5dAlan Cox dev_priv->regs.psb.saveFPB1; 114689c78134cc54dff016c83367912eb055637fa50cAlan Cox 1147c6265ff593467d472814aa9f16f89f6c1dc90a5dAlan Cox is_lvds = (pipe == 1) && (dev_priv->regs.psb.saveLVDS & 1148648a8e342c5a754bdc62f003d3af90507c1abfdeAlan Cox LVDS_PORT_EN); 114989c78134cc54dff016c83367912eb055637fa50cAlan Cox } 115089c78134cc54dff016c83367912eb055637fa50cAlan Cox 115189c78134cc54dff016c83367912eb055637fa50cAlan Cox clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT; 115289c78134cc54dff016c83367912eb055637fa50cAlan Cox clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT; 115389c78134cc54dff016c83367912eb055637fa50cAlan Cox clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT; 115489c78134cc54dff016c83367912eb055637fa50cAlan Cox 115589c78134cc54dff016c83367912eb055637fa50cAlan Cox if (is_lvds) { 115689c78134cc54dff016c83367912eb055637fa50cAlan Cox clock.p1 = 115789c78134cc54dff016c83367912eb055637fa50cAlan Cox ffs((dpll & 115889c78134cc54dff016c83367912eb055637fa50cAlan Cox DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >> 115989c78134cc54dff016c83367912eb055637fa50cAlan Cox DPLL_FPA01_P1_POST_DIV_SHIFT); 116089c78134cc54dff016c83367912eb055637fa50cAlan Cox clock.p2 = 14; 116189c78134cc54dff016c83367912eb055637fa50cAlan Cox 116289c78134cc54dff016c83367912eb055637fa50cAlan Cox if ((dpll & PLL_REF_INPUT_MASK) == 116389c78134cc54dff016c83367912eb055637fa50cAlan Cox PLLB_REF_INPUT_SPREADSPECTRUMIN) { 116489c78134cc54dff016c83367912eb055637fa50cAlan Cox /* XXX: might not be 66MHz */ 116589c78134cc54dff016c83367912eb055637fa50cAlan Cox i8xx_clock(66000, &clock); 116689c78134cc54dff016c83367912eb055637fa50cAlan Cox } else 116789c78134cc54dff016c83367912eb055637fa50cAlan Cox i8xx_clock(48000, &clock); 116889c78134cc54dff016c83367912eb055637fa50cAlan Cox } else { 116989c78134cc54dff016c83367912eb055637fa50cAlan Cox if (dpll & PLL_P1_DIVIDE_BY_TWO) 117089c78134cc54dff016c83367912eb055637fa50cAlan Cox clock.p1 = 2; 117189c78134cc54dff016c83367912eb055637fa50cAlan Cox else { 117289c78134cc54dff016c83367912eb055637fa50cAlan Cox clock.p1 = 117389c78134cc54dff016c83367912eb055637fa50cAlan Cox ((dpll & 117489c78134cc54dff016c83367912eb055637fa50cAlan Cox DPLL_FPA01_P1_POST_DIV_MASK_I830) >> 117589c78134cc54dff016c83367912eb055637fa50cAlan Cox DPLL_FPA01_P1_POST_DIV_SHIFT) + 2; 117689c78134cc54dff016c83367912eb055637fa50cAlan Cox } 117789c78134cc54dff016c83367912eb055637fa50cAlan Cox if (dpll & PLL_P2_DIVIDE_BY_4) 117889c78134cc54dff016c83367912eb055637fa50cAlan Cox clock.p2 = 4; 117989c78134cc54dff016c83367912eb055637fa50cAlan Cox else 118089c78134cc54dff016c83367912eb055637fa50cAlan Cox clock.p2 = 2; 118189c78134cc54dff016c83367912eb055637fa50cAlan Cox 118289c78134cc54dff016c83367912eb055637fa50cAlan Cox i8xx_clock(48000, &clock); 118389c78134cc54dff016c83367912eb055637fa50cAlan Cox } 118489c78134cc54dff016c83367912eb055637fa50cAlan Cox 118589c78134cc54dff016c83367912eb055637fa50cAlan Cox /* XXX: It would be nice to validate the clocks, but we can't reuse 118689c78134cc54dff016c83367912eb055637fa50cAlan Cox * i830PllIsValid() because it relies on the xf86_config connector 118789c78134cc54dff016c83367912eb055637fa50cAlan Cox * configuration being accurate, which it isn't necessarily. 118889c78134cc54dff016c83367912eb055637fa50cAlan Cox */ 118989c78134cc54dff016c83367912eb055637fa50cAlan Cox 119089c78134cc54dff016c83367912eb055637fa50cAlan Cox return clock.dot; 119189c78134cc54dff016c83367912eb055637fa50cAlan Cox} 119289c78134cc54dff016c83367912eb055637fa50cAlan Cox 119389c78134cc54dff016c83367912eb055637fa50cAlan Cox/** Returns the currently programmed mode of the given pipe. */ 119489c78134cc54dff016c83367912eb055637fa50cAlan Coxstruct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev, 119589c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_crtc *crtc) 119689c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 119789c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 119889c78134cc54dff016c83367912eb055637fa50cAlan Cox int pipe = psb_intel_crtc->pipe; 119989c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_display_mode *mode; 120089c78134cc54dff016c83367912eb055637fa50cAlan Cox int htot; 120189c78134cc54dff016c83367912eb055637fa50cAlan Cox int hsync; 120289c78134cc54dff016c83367912eb055637fa50cAlan Cox int vtot; 120389c78134cc54dff016c83367912eb055637fa50cAlan Cox int vsync; 120489c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_psb_private *dev_priv = dev->dev_private; 120589c78134cc54dff016c83367912eb055637fa50cAlan Cox 120689c78134cc54dff016c83367912eb055637fa50cAlan Cox if (gma_power_begin(dev, false)) { 120789c78134cc54dff016c83367912eb055637fa50cAlan Cox htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B); 120889c78134cc54dff016c83367912eb055637fa50cAlan Cox hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B); 120989c78134cc54dff016c83367912eb055637fa50cAlan Cox vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B); 121089c78134cc54dff016c83367912eb055637fa50cAlan Cox vsync = REG_READ((pipe == 0) ? VSYNC_A : VSYNC_B); 121189c78134cc54dff016c83367912eb055637fa50cAlan Cox gma_power_end(dev); 121289c78134cc54dff016c83367912eb055637fa50cAlan Cox } else { 121389c78134cc54dff016c83367912eb055637fa50cAlan Cox htot = (pipe == 0) ? 1214c6265ff593467d472814aa9f16f89f6c1dc90a5dAlan Cox dev_priv->regs.psb.saveHTOTAL_A : 1215c6265ff593467d472814aa9f16f89f6c1dc90a5dAlan Cox dev_priv->regs.psb.saveHTOTAL_B; 121689c78134cc54dff016c83367912eb055637fa50cAlan Cox hsync = (pipe == 0) ? 1217c6265ff593467d472814aa9f16f89f6c1dc90a5dAlan Cox dev_priv->regs.psb.saveHSYNC_A : 1218c6265ff593467d472814aa9f16f89f6c1dc90a5dAlan Cox dev_priv->regs.psb.saveHSYNC_B; 121989c78134cc54dff016c83367912eb055637fa50cAlan Cox vtot = (pipe == 0) ? 1220c6265ff593467d472814aa9f16f89f6c1dc90a5dAlan Cox dev_priv->regs.psb.saveVTOTAL_A : 1221c6265ff593467d472814aa9f16f89f6c1dc90a5dAlan Cox dev_priv->regs.psb.saveVTOTAL_B; 122289c78134cc54dff016c83367912eb055637fa50cAlan Cox vsync = (pipe == 0) ? 1223c6265ff593467d472814aa9f16f89f6c1dc90a5dAlan Cox dev_priv->regs.psb.saveVSYNC_A : 1224c6265ff593467d472814aa9f16f89f6c1dc90a5dAlan Cox dev_priv->regs.psb.saveVSYNC_B; 122589c78134cc54dff016c83367912eb055637fa50cAlan Cox } 122689c78134cc54dff016c83367912eb055637fa50cAlan Cox 122789c78134cc54dff016c83367912eb055637fa50cAlan Cox mode = kzalloc(sizeof(*mode), GFP_KERNEL); 122889c78134cc54dff016c83367912eb055637fa50cAlan Cox if (!mode) 122989c78134cc54dff016c83367912eb055637fa50cAlan Cox return NULL; 123089c78134cc54dff016c83367912eb055637fa50cAlan Cox 123189c78134cc54dff016c83367912eb055637fa50cAlan Cox mode->clock = psb_intel_crtc_clock_get(dev, crtc); 123289c78134cc54dff016c83367912eb055637fa50cAlan Cox mode->hdisplay = (htot & 0xffff) + 1; 123389c78134cc54dff016c83367912eb055637fa50cAlan Cox mode->htotal = ((htot & 0xffff0000) >> 16) + 1; 123489c78134cc54dff016c83367912eb055637fa50cAlan Cox mode->hsync_start = (hsync & 0xffff) + 1; 123589c78134cc54dff016c83367912eb055637fa50cAlan Cox mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1; 123689c78134cc54dff016c83367912eb055637fa50cAlan Cox mode->vdisplay = (vtot & 0xffff) + 1; 123789c78134cc54dff016c83367912eb055637fa50cAlan Cox mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1; 123889c78134cc54dff016c83367912eb055637fa50cAlan Cox mode->vsync_start = (vsync & 0xffff) + 1; 123989c78134cc54dff016c83367912eb055637fa50cAlan Cox mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1; 124089c78134cc54dff016c83367912eb055637fa50cAlan Cox 124189c78134cc54dff016c83367912eb055637fa50cAlan Cox drm_mode_set_name(mode); 124289c78134cc54dff016c83367912eb055637fa50cAlan Cox drm_mode_set_crtcinfo(mode, 0); 124389c78134cc54dff016c83367912eb055637fa50cAlan Cox 124489c78134cc54dff016c83367912eb055637fa50cAlan Cox return mode; 124589c78134cc54dff016c83367912eb055637fa50cAlan Cox} 124689c78134cc54dff016c83367912eb055637fa50cAlan Cox 124789c78134cc54dff016c83367912eb055637fa50cAlan Coxvoid psb_intel_crtc_destroy(struct drm_crtc *crtc) 124889c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 124989c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 125089c78134cc54dff016c83367912eb055637fa50cAlan Cox struct gtt_range *gt; 125189c78134cc54dff016c83367912eb055637fa50cAlan Cox 125289c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Unpin the old GEM object */ 125389c78134cc54dff016c83367912eb055637fa50cAlan Cox if (psb_intel_crtc->cursor_obj) { 125489c78134cc54dff016c83367912eb055637fa50cAlan Cox gt = container_of(psb_intel_crtc->cursor_obj, 125589c78134cc54dff016c83367912eb055637fa50cAlan Cox struct gtt_range, gem); 125689c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_gtt_unpin(gt); 125789c78134cc54dff016c83367912eb055637fa50cAlan Cox drm_gem_object_unreference(psb_intel_crtc->cursor_obj); 125889c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc->cursor_obj = NULL; 125989c78134cc54dff016c83367912eb055637fa50cAlan Cox } 126089c78134cc54dff016c83367912eb055637fa50cAlan Cox kfree(psb_intel_crtc->crtc_state); 126189c78134cc54dff016c83367912eb055637fa50cAlan Cox drm_crtc_cleanup(crtc); 126289c78134cc54dff016c83367912eb055637fa50cAlan Cox kfree(psb_intel_crtc); 126389c78134cc54dff016c83367912eb055637fa50cAlan Cox} 126489c78134cc54dff016c83367912eb055637fa50cAlan Cox 126589c78134cc54dff016c83367912eb055637fa50cAlan Coxconst struct drm_crtc_helper_funcs psb_intel_helper_funcs = { 126689c78134cc54dff016c83367912eb055637fa50cAlan Cox .dpms = psb_intel_crtc_dpms, 126789c78134cc54dff016c83367912eb055637fa50cAlan Cox .mode_fixup = psb_intel_crtc_mode_fixup, 126889c78134cc54dff016c83367912eb055637fa50cAlan Cox .mode_set = psb_intel_crtc_mode_set, 126989c78134cc54dff016c83367912eb055637fa50cAlan Cox .mode_set_base = psb_intel_pipe_set_base, 127089c78134cc54dff016c83367912eb055637fa50cAlan Cox .prepare = psb_intel_crtc_prepare, 127189c78134cc54dff016c83367912eb055637fa50cAlan Cox .commit = psb_intel_crtc_commit, 127289c78134cc54dff016c83367912eb055637fa50cAlan Cox}; 127389c78134cc54dff016c83367912eb055637fa50cAlan Cox 127489c78134cc54dff016c83367912eb055637fa50cAlan Coxconst struct drm_crtc_funcs psb_intel_crtc_funcs = { 127589c78134cc54dff016c83367912eb055637fa50cAlan Cox .save = psb_intel_crtc_save, 127689c78134cc54dff016c83367912eb055637fa50cAlan Cox .restore = psb_intel_crtc_restore, 127789c78134cc54dff016c83367912eb055637fa50cAlan Cox .cursor_set = psb_intel_crtc_cursor_set, 127889c78134cc54dff016c83367912eb055637fa50cAlan Cox .cursor_move = psb_intel_crtc_cursor_move, 127989c78134cc54dff016c83367912eb055637fa50cAlan Cox .gamma_set = psb_intel_crtc_gamma_set, 128089c78134cc54dff016c83367912eb055637fa50cAlan Cox .set_config = psb_crtc_set_config, 128189c78134cc54dff016c83367912eb055637fa50cAlan Cox .destroy = psb_intel_crtc_destroy, 128289c78134cc54dff016c83367912eb055637fa50cAlan Cox}; 128389c78134cc54dff016c83367912eb055637fa50cAlan Cox 128489c78134cc54dff016c83367912eb055637fa50cAlan Cox/* 128589c78134cc54dff016c83367912eb055637fa50cAlan Cox * Set the default value of cursor control and base register 128689c78134cc54dff016c83367912eb055637fa50cAlan Cox * to zero. This is a workaround for h/w defect on Oaktrail 128789c78134cc54dff016c83367912eb055637fa50cAlan Cox */ 128889c78134cc54dff016c83367912eb055637fa50cAlan Coxstatic void psb_intel_cursor_init(struct drm_device *dev, int pipe) 128989c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 129089c78134cc54dff016c83367912eb055637fa50cAlan Cox u32 control[3] = { CURACNTR, CURBCNTR, CURCCNTR }; 129189c78134cc54dff016c83367912eb055637fa50cAlan Cox u32 base[3] = { CURABASE, CURBBASE, CURCBASE }; 129289c78134cc54dff016c83367912eb055637fa50cAlan Cox 129389c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(control[pipe], 0); 129489c78134cc54dff016c83367912eb055637fa50cAlan Cox REG_WRITE(base[pipe], 0); 129589c78134cc54dff016c83367912eb055637fa50cAlan Cox} 129689c78134cc54dff016c83367912eb055637fa50cAlan Cox 129789c78134cc54dff016c83367912eb055637fa50cAlan Coxvoid psb_intel_crtc_init(struct drm_device *dev, int pipe, 129889c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_mode_device *mode_dev) 129989c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 130089c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_psb_private *dev_priv = dev->dev_private; 130189c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_crtc *psb_intel_crtc; 130289c78134cc54dff016c83367912eb055637fa50cAlan Cox int i; 130389c78134cc54dff016c83367912eb055637fa50cAlan Cox uint16_t *r_base, *g_base, *b_base; 130489c78134cc54dff016c83367912eb055637fa50cAlan Cox 130589c78134cc54dff016c83367912eb055637fa50cAlan Cox /* We allocate a extra array of drm_connector pointers 130689c78134cc54dff016c83367912eb055637fa50cAlan Cox * for fbdev after the crtc */ 130789c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc = 130889c78134cc54dff016c83367912eb055637fa50cAlan Cox kzalloc(sizeof(struct psb_intel_crtc) + 130989c78134cc54dff016c83367912eb055637fa50cAlan Cox (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)), 131089c78134cc54dff016c83367912eb055637fa50cAlan Cox GFP_KERNEL); 131189c78134cc54dff016c83367912eb055637fa50cAlan Cox if (psb_intel_crtc == NULL) 131289c78134cc54dff016c83367912eb055637fa50cAlan Cox return; 131389c78134cc54dff016c83367912eb055637fa50cAlan Cox 131489c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc->crtc_state = 131589c78134cc54dff016c83367912eb055637fa50cAlan Cox kzalloc(sizeof(struct psb_intel_crtc_state), GFP_KERNEL); 131689c78134cc54dff016c83367912eb055637fa50cAlan Cox if (!psb_intel_crtc->crtc_state) { 131789c78134cc54dff016c83367912eb055637fa50cAlan Cox dev_err(dev->dev, "Crtc state error: No memory\n"); 131889c78134cc54dff016c83367912eb055637fa50cAlan Cox kfree(psb_intel_crtc); 131989c78134cc54dff016c83367912eb055637fa50cAlan Cox return; 132089c78134cc54dff016c83367912eb055637fa50cAlan Cox } 132189c78134cc54dff016c83367912eb055637fa50cAlan Cox 132289c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Set the CRTC operations from the chip specific data */ 132389c78134cc54dff016c83367912eb055637fa50cAlan Cox drm_crtc_init(dev, &psb_intel_crtc->base, dev_priv->ops->crtc_funcs); 132489c78134cc54dff016c83367912eb055637fa50cAlan Cox 132589c78134cc54dff016c83367912eb055637fa50cAlan Cox drm_mode_crtc_set_gamma_size(&psb_intel_crtc->base, 256); 132689c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc->pipe = pipe; 132789c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc->plane = pipe; 132889c78134cc54dff016c83367912eb055637fa50cAlan Cox 132989c78134cc54dff016c83367912eb055637fa50cAlan Cox r_base = psb_intel_crtc->base.gamma_store; 133089c78134cc54dff016c83367912eb055637fa50cAlan Cox g_base = r_base + 256; 133189c78134cc54dff016c83367912eb055637fa50cAlan Cox b_base = g_base + 256; 133289c78134cc54dff016c83367912eb055637fa50cAlan Cox for (i = 0; i < 256; i++) { 133389c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc->lut_r[i] = i; 133489c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc->lut_g[i] = i; 133589c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc->lut_b[i] = i; 133689c78134cc54dff016c83367912eb055637fa50cAlan Cox r_base[i] = i << 8; 133789c78134cc54dff016c83367912eb055637fa50cAlan Cox g_base[i] = i << 8; 133889c78134cc54dff016c83367912eb055637fa50cAlan Cox b_base[i] = i << 8; 133989c78134cc54dff016c83367912eb055637fa50cAlan Cox 134089c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc->lut_adj[i] = 0; 134189c78134cc54dff016c83367912eb055637fa50cAlan Cox } 134289c78134cc54dff016c83367912eb055637fa50cAlan Cox 134389c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc->mode_dev = mode_dev; 134489c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc->cursor_addr = 0; 134589c78134cc54dff016c83367912eb055637fa50cAlan Cox 134689c78134cc54dff016c83367912eb055637fa50cAlan Cox drm_crtc_helper_add(&psb_intel_crtc->base, 134789c78134cc54dff016c83367912eb055637fa50cAlan Cox dev_priv->ops->crtc_helper); 134889c78134cc54dff016c83367912eb055637fa50cAlan Cox 134989c78134cc54dff016c83367912eb055637fa50cAlan Cox /* Setup the array of drm_connector pointer array */ 135089c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc->mode_set.crtc = &psb_intel_crtc->base; 135189c78134cc54dff016c83367912eb055637fa50cAlan Cox BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) || 135289c78134cc54dff016c83367912eb055637fa50cAlan Cox dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] != NULL); 135389c78134cc54dff016c83367912eb055637fa50cAlan Cox dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] = 135489c78134cc54dff016c83367912eb055637fa50cAlan Cox &psb_intel_crtc->base; 135589c78134cc54dff016c83367912eb055637fa50cAlan Cox dev_priv->pipe_to_crtc_mapping[psb_intel_crtc->pipe] = 135689c78134cc54dff016c83367912eb055637fa50cAlan Cox &psb_intel_crtc->base; 135789c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc->mode_set.connectors = 135889c78134cc54dff016c83367912eb055637fa50cAlan Cox (struct drm_connector **) (psb_intel_crtc + 1); 135989c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_crtc->mode_set.num_connectors = 0; 136089c78134cc54dff016c83367912eb055637fa50cAlan Cox psb_intel_cursor_init(dev, pipe); 136189c78134cc54dff016c83367912eb055637fa50cAlan Cox} 136289c78134cc54dff016c83367912eb055637fa50cAlan Cox 136389c78134cc54dff016c83367912eb055637fa50cAlan Coxint psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, 136489c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_file *file_priv) 136589c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 136689c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_psb_private *dev_priv = dev->dev_private; 136789c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_psb_get_pipe_from_crtc_id_arg *pipe_from_crtc_id = data; 136889c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_mode_object *drmmode_obj; 136989c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_crtc *crtc; 137089c78134cc54dff016c83367912eb055637fa50cAlan Cox 137189c78134cc54dff016c83367912eb055637fa50cAlan Cox if (!dev_priv) { 137289c78134cc54dff016c83367912eb055637fa50cAlan Cox dev_err(dev->dev, "called with no initialization\n"); 137389c78134cc54dff016c83367912eb055637fa50cAlan Cox return -EINVAL; 137489c78134cc54dff016c83367912eb055637fa50cAlan Cox } 137589c78134cc54dff016c83367912eb055637fa50cAlan Cox 137689c78134cc54dff016c83367912eb055637fa50cAlan Cox drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id, 137789c78134cc54dff016c83367912eb055637fa50cAlan Cox DRM_MODE_OBJECT_CRTC); 137889c78134cc54dff016c83367912eb055637fa50cAlan Cox 137989c78134cc54dff016c83367912eb055637fa50cAlan Cox if (!drmmode_obj) { 138089c78134cc54dff016c83367912eb055637fa50cAlan Cox dev_err(dev->dev, "no such CRTC id\n"); 138189c78134cc54dff016c83367912eb055637fa50cAlan Cox return -EINVAL; 138289c78134cc54dff016c83367912eb055637fa50cAlan Cox } 138389c78134cc54dff016c83367912eb055637fa50cAlan Cox 138489c78134cc54dff016c83367912eb055637fa50cAlan Cox crtc = to_psb_intel_crtc(obj_to_crtc(drmmode_obj)); 138589c78134cc54dff016c83367912eb055637fa50cAlan Cox pipe_from_crtc_id->pipe = crtc->pipe; 138689c78134cc54dff016c83367912eb055637fa50cAlan Cox 138789c78134cc54dff016c83367912eb055637fa50cAlan Cox return 0; 138889c78134cc54dff016c83367912eb055637fa50cAlan Cox} 138989c78134cc54dff016c83367912eb055637fa50cAlan Cox 139089c78134cc54dff016c83367912eb055637fa50cAlan Coxstruct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, int pipe) 139189c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 139289c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_crtc *crtc = NULL; 139389c78134cc54dff016c83367912eb055637fa50cAlan Cox 139489c78134cc54dff016c83367912eb055637fa50cAlan Cox list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 139589c78134cc54dff016c83367912eb055637fa50cAlan Cox struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 139689c78134cc54dff016c83367912eb055637fa50cAlan Cox if (psb_intel_crtc->pipe == pipe) 139789c78134cc54dff016c83367912eb055637fa50cAlan Cox break; 139889c78134cc54dff016c83367912eb055637fa50cAlan Cox } 139989c78134cc54dff016c83367912eb055637fa50cAlan Cox return crtc; 140089c78134cc54dff016c83367912eb055637fa50cAlan Cox} 140189c78134cc54dff016c83367912eb055637fa50cAlan Cox 140289c78134cc54dff016c83367912eb055637fa50cAlan Coxint psb_intel_connector_clones(struct drm_device *dev, int type_mask) 140389c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 140489c78134cc54dff016c83367912eb055637fa50cAlan Cox int index_mask = 0; 140589c78134cc54dff016c83367912eb055637fa50cAlan Cox struct drm_connector *connector; 140689c78134cc54dff016c83367912eb055637fa50cAlan Cox int entry = 0; 140789c78134cc54dff016c83367912eb055637fa50cAlan Cox 140889c78134cc54dff016c83367912eb055637fa50cAlan Cox list_for_each_entry(connector, &dev->mode_config.connector_list, 140989c78134cc54dff016c83367912eb055637fa50cAlan Cox head) { 14101730f89bfcff353484672cdcefbef13b2f374176Patrik Jakobsson struct psb_intel_encoder *psb_intel_encoder = 14111730f89bfcff353484672cdcefbef13b2f374176Patrik Jakobsson psb_intel_attached_encoder(connector); 14121730f89bfcff353484672cdcefbef13b2f374176Patrik Jakobsson if (type_mask & (1 << psb_intel_encoder->type)) 141389c78134cc54dff016c83367912eb055637fa50cAlan Cox index_mask |= (1 << entry); 141489c78134cc54dff016c83367912eb055637fa50cAlan Cox entry++; 141589c78134cc54dff016c83367912eb055637fa50cAlan Cox } 141689c78134cc54dff016c83367912eb055637fa50cAlan Cox return index_mask; 141789c78134cc54dff016c83367912eb055637fa50cAlan Cox} 141889c78134cc54dff016c83367912eb055637fa50cAlan Cox 141989c78134cc54dff016c83367912eb055637fa50cAlan Cox/* current intel driver doesn't take advantage of encoders 142089c78134cc54dff016c83367912eb055637fa50cAlan Cox always give back the encoder for the connector 142189c78134cc54dff016c83367912eb055637fa50cAlan Cox*/ 142289c78134cc54dff016c83367912eb055637fa50cAlan Coxstruct drm_encoder *psb_intel_best_encoder(struct drm_connector *connector) 142389c78134cc54dff016c83367912eb055637fa50cAlan Cox{ 14241730f89bfcff353484672cdcefbef13b2f374176Patrik Jakobsson struct psb_intel_encoder *psb_intel_encoder = 14251730f89bfcff353484672cdcefbef13b2f374176Patrik Jakobsson psb_intel_attached_encoder(connector); 142689c78134cc54dff016c83367912eb055637fa50cAlan Cox 14271730f89bfcff353484672cdcefbef13b2f374176Patrik Jakobsson return &psb_intel_encoder->base; 142889c78134cc54dff016c83367912eb055637fa50cAlan Cox} 142989c78134cc54dff016c83367912eb055637fa50cAlan Cox 143075e9d019d5625032b708576e02e025c79e04ae44Patrik Jakobssonvoid psb_intel_connector_attach_encoder(struct psb_intel_connector *connector, 143175e9d019d5625032b708576e02e025c79e04ae44Patrik Jakobsson struct psb_intel_encoder *encoder) 143275e9d019d5625032b708576e02e025c79e04ae44Patrik Jakobsson{ 143375e9d019d5625032b708576e02e025c79e04ae44Patrik Jakobsson connector->encoder = encoder; 143475e9d019d5625032b708576e02e025c79e04ae44Patrik Jakobsson drm_mode_connector_attach_encoder(&connector->base, 143575e9d019d5625032b708576e02e025c79e04ae44Patrik Jakobsson &encoder->base); 143675e9d019d5625032b708576e02e025c79e04ae44Patrik Jakobsson} 1437