Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gma500: Add Poulsbo support

This provides the specific code for Poulsbo, some of which is also used for
the later chipsets. We support the GTT, the 2D engine (for console), and
the display setup/management. We do not support 3D or the video overlays.

In theory enough public info is available to do the video overlay work
but that represents a large task.

Framebuffer X will run nicely with this but do *NOT* use the VESA X
server at the same time as KMS. With a Dell mini 10 things like Xfce4 are
nice and usable even when compositing as the CPU has a good path to the
memory.

Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>

authored by

Alan Cox and committed by
Dave Airlie
89c78134 5c49fd3a

+5973
+353
drivers/gpu/drm/gma500/psb_device.c
··· 1 + /************************************************************************** 2 + * Copyright (c) 2011, Intel Corporation. 3 + * All Rights Reserved. 4 + * 5 + * This program is free software; you can redistribute it and/or modify it 6 + * under the terms and conditions of the GNU General Public License, 7 + * version 2, as published by the Free Software Foundation. 8 + * 9 + * This program is distributed in the hope it will be useful, but WITHOUT 10 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 + * more details. 13 + * 14 + * You should have received a copy of the GNU General Public License along with 15 + * this program; if not, write to the Free Software Foundation, Inc., 16 + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 17 + * 18 + **************************************************************************/ 19 + 20 + #include <linux/backlight.h> 21 + #include <drm/drmP.h> 22 + #include <drm/drm.h> 23 + #include "psb_drm.h" 24 + #include "psb_drv.h" 25 + #include "psb_reg.h" 26 + #include "psb_intel_reg.h" 27 + #include "intel_bios.h" 28 + 29 + 30 + static int psb_output_init(struct drm_device *dev) 31 + { 32 + struct drm_psb_private *dev_priv = dev->dev_private; 33 + psb_intel_lvds_init(dev, &dev_priv->mode_dev); 34 + psb_intel_sdvo_init(dev, SDVOB); 35 + return 0; 36 + } 37 + 38 + #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE 39 + 40 + /* 41 + * Poulsbo Backlight Interfaces 42 + */ 43 + 44 + #define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */ 45 + #define BLC_PWM_FREQ_CALC_CONSTANT 32 46 + #define MHz 1000000 47 + 48 + #define PSB_BLC_PWM_PRECISION_FACTOR 10 49 + #define PSB_BLC_MAX_PWM_REG_FREQ 0xFFFE 50 + #define PSB_BLC_MIN_PWM_REG_FREQ 0x2 51 + 52 + #define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) 53 + #define PSB_BACKLIGHT_PWM_CTL_SHIFT (16) 54 + 55 + static int psb_brightness; 56 + static struct backlight_device *psb_backlight_device; 57 + 58 + static int psb_get_brightness(struct backlight_device *bd) 59 + { 60 + /* return locally cached var instead of HW read (due to DPST etc.) */ 61 + /* FIXME: ideally return actual value in case firmware fiddled with 62 + it */ 63 + return psb_brightness; 64 + } 65 + 66 + 67 + static int psb_backlight_setup(struct drm_device *dev) 68 + { 69 + struct drm_psb_private *dev_priv = dev->dev_private; 70 + unsigned long core_clock; 71 + /* u32 bl_max_freq; */ 72 + /* unsigned long value; */ 73 + u16 bl_max_freq; 74 + uint32_t value; 75 + uint32_t blc_pwm_precision_factor; 76 + 77 + /* get bl_max_freq and pol from dev_priv*/ 78 + if (!dev_priv->lvds_bl) { 79 + dev_err(dev->dev, "Has no valid LVDS backlight info\n"); 80 + return -ENOENT; 81 + } 82 + bl_max_freq = dev_priv->lvds_bl->freq; 83 + blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR; 84 + 85 + core_clock = dev_priv->core_freq; 86 + 87 + value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT; 88 + value *= blc_pwm_precision_factor; 89 + value /= bl_max_freq; 90 + value /= blc_pwm_precision_factor; 91 + 92 + if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ || 93 + value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ) 94 + return -ERANGE; 95 + else { 96 + value &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR; 97 + REG_WRITE(BLC_PWM_CTL, 98 + (value << PSB_BACKLIGHT_PWM_CTL_SHIFT) | (value)); 99 + } 100 + return 0; 101 + } 102 + 103 + static int psb_set_brightness(struct backlight_device *bd) 104 + { 105 + struct drm_device *dev = bl_get_data(psb_backlight_device); 106 + int level = bd->props.brightness; 107 + 108 + /* Percentage 1-100% being valid */ 109 + if (level < 1) 110 + level = 1; 111 + 112 + psb_intel_lvds_set_brightness(dev, level); 113 + psb_brightness = level; 114 + return 0; 115 + } 116 + 117 + static const struct backlight_ops psb_ops = { 118 + .get_brightness = psb_get_brightness, 119 + .update_status = psb_set_brightness, 120 + }; 121 + 122 + static int psb_backlight_init(struct drm_device *dev) 123 + { 124 + struct drm_psb_private *dev_priv = dev->dev_private; 125 + int ret; 126 + struct backlight_properties props; 127 + 128 + memset(&props, 0, sizeof(struct backlight_properties)); 129 + props.max_brightness = 100; 130 + props.type = BACKLIGHT_PLATFORM; 131 + 132 + psb_backlight_device = backlight_device_register("psb-bl", 133 + NULL, (void *)dev, &psb_ops, &props); 134 + if (IS_ERR(psb_backlight_device)) 135 + return PTR_ERR(psb_backlight_device); 136 + 137 + ret = psb_backlight_setup(dev); 138 + if (ret < 0) { 139 + backlight_device_unregister(psb_backlight_device); 140 + psb_backlight_device = NULL; 141 + return ret; 142 + } 143 + psb_backlight_device->props.brightness = 100; 144 + psb_backlight_device->props.max_brightness = 100; 145 + backlight_update_status(psb_backlight_device); 146 + dev_priv->backlight_device = psb_backlight_device; 147 + return 0; 148 + } 149 + 150 + #endif 151 + 152 + /* 153 + * Provide the Poulsbo specific chip logic and low level methods 154 + * for power management 155 + */ 156 + 157 + static void psb_init_pm(struct drm_device *dev) 158 + { 159 + struct drm_psb_private *dev_priv = dev->dev_private; 160 + 161 + u32 gating = PSB_RSGX32(PSB_CR_CLKGATECTL); 162 + gating &= ~3; /* Disable 2D clock gating */ 163 + gating |= 1; 164 + PSB_WSGX32(gating, PSB_CR_CLKGATECTL); 165 + PSB_RSGX32(PSB_CR_CLKGATECTL); 166 + } 167 + 168 + /** 169 + * psb_save_display_registers - save registers lost on suspend 170 + * @dev: our DRM device 171 + * 172 + * Save the state we need in order to be able to restore the interface 173 + * upon resume from suspend 174 + */ 175 + static int psb_save_display_registers(struct drm_device *dev) 176 + { 177 + struct drm_psb_private *dev_priv = dev->dev_private; 178 + struct drm_crtc *crtc; 179 + struct drm_connector *connector; 180 + 181 + /* Display arbitration control + watermarks */ 182 + dev_priv->saveDSPARB = PSB_RVDC32(DSPARB); 183 + dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1); 184 + dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2); 185 + dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3); 186 + dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4); 187 + dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5); 188 + dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6); 189 + dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT); 190 + 191 + /* Save crtc and output state */ 192 + mutex_lock(&dev->mode_config.mutex); 193 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 194 + if (drm_helper_crtc_in_use(crtc)) 195 + crtc->funcs->save(crtc); 196 + } 197 + 198 + list_for_each_entry(connector, &dev->mode_config.connector_list, head) 199 + connector->funcs->save(connector); 200 + 201 + mutex_unlock(&dev->mode_config.mutex); 202 + return 0; 203 + } 204 + 205 + /** 206 + * psb_restore_display_registers - restore lost register state 207 + * @dev: our DRM device 208 + * 209 + * Restore register state that was lost during suspend and resume. 210 + */ 211 + static int psb_restore_display_registers(struct drm_device *dev) 212 + { 213 + struct drm_psb_private *dev_priv = dev->dev_private; 214 + struct drm_crtc *crtc; 215 + struct drm_connector *connector; 216 + int pp_stat; 217 + 218 + /* Display arbitration + watermarks */ 219 + PSB_WVDC32(dev_priv->saveDSPARB, DSPARB); 220 + PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1); 221 + PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2); 222 + PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3); 223 + PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4); 224 + PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5); 225 + PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6); 226 + PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT); 227 + 228 + /*make sure VGA plane is off. it initializes to on after reset!*/ 229 + PSB_WVDC32(0x80000000, VGACNTRL); 230 + 231 + mutex_lock(&dev->mode_config.mutex); 232 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) 233 + if (drm_helper_crtc_in_use(crtc)) 234 + crtc->funcs->restore(crtc); 235 + 236 + list_for_each_entry(connector, &dev->mode_config.connector_list, head) 237 + connector->funcs->restore(connector); 238 + 239 + mutex_unlock(&dev->mode_config.mutex); 240 + 241 + if (dev_priv->iLVDS_enable) { 242 + /*shutdown the panel*/ 243 + PSB_WVDC32(0, PP_CONTROL); 244 + do { 245 + pp_stat = PSB_RVDC32(PP_STATUS); 246 + } while (pp_stat & 0x80000000); 247 + 248 + /* Turn off the plane */ 249 + PSB_WVDC32(0x58000000, DSPACNTR); 250 + PSB_WVDC32(0, DSPASURF);/*trigger the plane disable*/ 251 + /* Wait ~4 ticks */ 252 + msleep(4); 253 + /* Turn off pipe */ 254 + PSB_WVDC32(0x0, PIPEACONF); 255 + /* Wait ~8 ticks */ 256 + msleep(8); 257 + 258 + /* Turn off PLLs */ 259 + PSB_WVDC32(0, MRST_DPLL_A); 260 + } else { 261 + PSB_WVDC32(DPI_SHUT_DOWN, DPI_CONTROL_REG); 262 + PSB_WVDC32(0x0, PIPEACONF); 263 + PSB_WVDC32(0x2faf0000, BLC_PWM_CTL); 264 + while (REG_READ(0x70008) & 0x40000000) 265 + cpu_relax(); 266 + while ((PSB_RVDC32(GEN_FIFO_STAT_REG) & DPI_FIFO_EMPTY) 267 + != DPI_FIFO_EMPTY) 268 + cpu_relax(); 269 + PSB_WVDC32(0, DEVICE_READY_REG); 270 + } 271 + return 0; 272 + } 273 + 274 + static int psb_power_down(struct drm_device *dev) 275 + { 276 + return 0; 277 + } 278 + 279 + static int psb_power_up(struct drm_device *dev) 280 + { 281 + return 0; 282 + } 283 + 284 + static void psb_get_core_freq(struct drm_device *dev) 285 + { 286 + uint32_t clock; 287 + struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); 288 + struct drm_psb_private *dev_priv = dev->dev_private; 289 + 290 + /*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/ 291 + /*pci_write_config_dword(pci_root, 0xD0, 0xE0033000);*/ 292 + 293 + pci_write_config_dword(pci_root, 0xD0, 0xD0050300); 294 + pci_read_config_dword(pci_root, 0xD4, &clock); 295 + pci_dev_put(pci_root); 296 + 297 + switch (clock & 0x07) { 298 + case 0: 299 + dev_priv->core_freq = 100; 300 + break; 301 + case 1: 302 + dev_priv->core_freq = 133; 303 + break; 304 + case 2: 305 + dev_priv->core_freq = 150; 306 + break; 307 + case 3: 308 + dev_priv->core_freq = 178; 309 + break; 310 + case 4: 311 + dev_priv->core_freq = 200; 312 + break; 313 + case 5: 314 + case 6: 315 + case 7: 316 + dev_priv->core_freq = 266; 317 + default: 318 + dev_priv->core_freq = 0; 319 + } 320 + } 321 + 322 + static int psb_chip_setup(struct drm_device *dev) 323 + { 324 + psb_get_core_freq(dev); 325 + gma_intel_opregion_init(dev); 326 + psb_intel_init_bios(dev); 327 + return 0; 328 + } 329 + 330 + const struct psb_ops psb_chip_ops = { 331 + .name = "Poulsbo", 332 + .accel_2d = 1, 333 + .pipes = 2, 334 + .crtcs = 2, 335 + .sgx_offset = PSB_SGX_OFFSET, 336 + .chip_setup = psb_chip_setup, 337 + 338 + .crtc_helper = &psb_intel_helper_funcs, 339 + .crtc_funcs = &psb_intel_crtc_funcs, 340 + 341 + .output_init = psb_output_init, 342 + 343 + #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE 344 + .backlight_init = psb_backlight_init, 345 + #endif 346 + 347 + .init_pm = psb_init_pm, 348 + .save_regs = psb_save_display_registers, 349 + .restore_regs = psb_restore_display_registers, 350 + .power_down = psb_power_down, 351 + .power_up = psb_power_up, 352 + }; 353 +
+51
drivers/gpu/drm/gma500/psb_gfx.mod.c
··· 1 + #include <linux/module.h> 2 + #include <linux/vermagic.h> 3 + #include <linux/compiler.h> 4 + 5 + MODULE_INFO(vermagic, VERMAGIC_STRING); 6 + 7 + struct module __this_module 8 + __attribute__((section(".gnu.linkonce.this_module"))) = { 9 + .name = KBUILD_MODNAME, 10 + .init = init_module, 11 + #ifdef CONFIG_MODULE_UNLOAD 12 + .exit = cleanup_module, 13 + #endif 14 + .arch = MODULE_ARCH_INIT, 15 + }; 16 + 17 + MODULE_INFO(staging, "Y"); 18 + 19 + static const char __module_depends[] 20 + __used 21 + __attribute__((section(".modinfo"))) = 22 + "depends=drm,drm_kms_helper,video,i2c-algo-bit"; 23 + 24 + MODULE_ALIAS("pci:v00008086d00008108sv*sd*bc*sc*i*"); 25 + MODULE_ALIAS("pci:v00008086d00008109sv*sd*bc*sc*i*"); 26 + MODULE_ALIAS("pci:v00008086d00004100sv*sd*bc*sc*i*"); 27 + MODULE_ALIAS("pci:v00008086d00004101sv*sd*bc*sc*i*"); 28 + MODULE_ALIAS("pci:v00008086d00004102sv*sd*bc*sc*i*"); 29 + MODULE_ALIAS("pci:v00008086d00004103sv*sd*bc*sc*i*"); 30 + MODULE_ALIAS("pci:v00008086d00004104sv*sd*bc*sc*i*"); 31 + MODULE_ALIAS("pci:v00008086d00004105sv*sd*bc*sc*i*"); 32 + MODULE_ALIAS("pci:v00008086d00004106sv*sd*bc*sc*i*"); 33 + MODULE_ALIAS("pci:v00008086d00004107sv*sd*bc*sc*i*"); 34 + MODULE_ALIAS("pci:v00008086d00000130sv*sd*bc*sc*i*"); 35 + MODULE_ALIAS("pci:v00008086d00000131sv*sd*bc*sc*i*"); 36 + MODULE_ALIAS("pci:v00008086d00000132sv*sd*bc*sc*i*"); 37 + MODULE_ALIAS("pci:v00008086d00000133sv*sd*bc*sc*i*"); 38 + MODULE_ALIAS("pci:v00008086d00000134sv*sd*bc*sc*i*"); 39 + MODULE_ALIAS("pci:v00008086d00000135sv*sd*bc*sc*i*"); 40 + MODULE_ALIAS("pci:v00008086d00000136sv*sd*bc*sc*i*"); 41 + MODULE_ALIAS("pci:v00008086d00000137sv*sd*bc*sc*i*"); 42 + MODULE_ALIAS("pci:v00008086d00000BE0sv*sd*bc*sc*i*"); 43 + MODULE_ALIAS("pci:v00008086d00000BE1sv*sd*bc*sc*i*"); 44 + MODULE_ALIAS("pci:v00008086d00000BE2sv*sd*bc*sc*i*"); 45 + MODULE_ALIAS("pci:v00008086d00000BE3sv*sd*bc*sc*i*"); 46 + MODULE_ALIAS("pci:v00008086d00000BE4sv*sd*bc*sc*i*"); 47 + MODULE_ALIAS("pci:v00008086d00000BE5sv*sd*bc*sc*i*"); 48 + MODULE_ALIAS("pci:v00008086d00000BE6sv*sd*bc*sc*i*"); 49 + MODULE_ALIAS("pci:v00008086d00000BE7sv*sd*bc*sc*i*"); 50 + 51 + MODULE_INFO(srcversion, "51B3334F342F5EEAC93AF22");
+1431
drivers/gpu/drm/gma500/psb_intel_display.c
··· 1 + /* 2 + * Copyright © 2006-2011 Intel Corporation 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms and conditions of the GNU General Public License, 6 + * version 2, as published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope it will be useful, but WITHOUT 9 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 + * more details. 12 + * 13 + * You should have received a copy of the GNU General Public License along with 14 + * this program; if not, write to the Free Software Foundation, Inc., 15 + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 16 + * 17 + * Authors: 18 + * Eric Anholt <eric@anholt.net> 19 + */ 20 + 21 + #include <linux/i2c.h> 22 + #include <linux/pm_runtime.h> 23 + 24 + #include <drm/drmP.h> 25 + #include "framebuffer.h" 26 + #include "psb_drv.h" 27 + #include "psb_intel_drv.h" 28 + #include "psb_intel_reg.h" 29 + #include "psb_intel_display.h" 30 + #include "power.h" 31 + 32 + struct psb_intel_clock_t { 33 + /* given values */ 34 + int n; 35 + int m1, m2; 36 + int p1, p2; 37 + /* derived values */ 38 + int dot; 39 + int vco; 40 + int m; 41 + int p; 42 + }; 43 + 44 + struct psb_intel_range_t { 45 + int min, max; 46 + }; 47 + 48 + struct psb_intel_p2_t { 49 + int dot_limit; 50 + int p2_slow, p2_fast; 51 + }; 52 + 53 + #define INTEL_P2_NUM 2 54 + 55 + struct psb_intel_limit_t { 56 + struct psb_intel_range_t dot, vco, n, m, m1, m2, p, p1; 57 + struct psb_intel_p2_t p2; 58 + }; 59 + 60 + #define I8XX_DOT_MIN 25000 61 + #define I8XX_DOT_MAX 350000 62 + #define I8XX_VCO_MIN 930000 63 + #define I8XX_VCO_MAX 1400000 64 + #define I8XX_N_MIN 3 65 + #define I8XX_N_MAX 16 66 + #define I8XX_M_MIN 96 67 + #define I8XX_M_MAX 140 68 + #define I8XX_M1_MIN 18 69 + #define I8XX_M1_MAX 26 70 + #define I8XX_M2_MIN 6 71 + #define I8XX_M2_MAX 16 72 + #define I8XX_P_MIN 4 73 + #define I8XX_P_MAX 128 74 + #define I8XX_P1_MIN 2 75 + #define I8XX_P1_MAX 33 76 + #define I8XX_P1_LVDS_MIN 1 77 + #define I8XX_P1_LVDS_MAX 6 78 + #define I8XX_P2_SLOW 4 79 + #define I8XX_P2_FAST 2 80 + #define I8XX_P2_LVDS_SLOW 14 81 + #define I8XX_P2_LVDS_FAST 14 /* No fast option */ 82 + #define I8XX_P2_SLOW_LIMIT 165000 83 + 84 + #define I9XX_DOT_MIN 20000 85 + #define I9XX_DOT_MAX 400000 86 + #define I9XX_VCO_MIN 1400000 87 + #define I9XX_VCO_MAX 2800000 88 + #define I9XX_N_MIN 3 89 + #define I9XX_N_MAX 8 90 + #define I9XX_M_MIN 70 91 + #define I9XX_M_MAX 120 92 + #define I9XX_M1_MIN 10 93 + #define I9XX_M1_MAX 20 94 + #define I9XX_M2_MIN 5 95 + #define I9XX_M2_MAX 9 96 + #define I9XX_P_SDVO_DAC_MIN 5 97 + #define I9XX_P_SDVO_DAC_MAX 80 98 + #define I9XX_P_LVDS_MIN 7 99 + #define I9XX_P_LVDS_MAX 98 100 + #define I9XX_P1_MIN 1 101 + #define I9XX_P1_MAX 8 102 + #define I9XX_P2_SDVO_DAC_SLOW 10 103 + #define I9XX_P2_SDVO_DAC_FAST 5 104 + #define I9XX_P2_SDVO_DAC_SLOW_LIMIT 200000 105 + #define I9XX_P2_LVDS_SLOW 14 106 + #define I9XX_P2_LVDS_FAST 7 107 + #define I9XX_P2_LVDS_SLOW_LIMIT 112000 108 + 109 + #define INTEL_LIMIT_I8XX_DVO_DAC 0 110 + #define INTEL_LIMIT_I8XX_LVDS 1 111 + #define INTEL_LIMIT_I9XX_SDVO_DAC 2 112 + #define INTEL_LIMIT_I9XX_LVDS 3 113 + 114 + static const struct psb_intel_limit_t psb_intel_limits[] = { 115 + { /* INTEL_LIMIT_I8XX_DVO_DAC */ 116 + .dot = {.min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX}, 117 + .vco = {.min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX}, 118 + .n = {.min = I8XX_N_MIN, .max = I8XX_N_MAX}, 119 + .m = {.min = I8XX_M_MIN, .max = I8XX_M_MAX}, 120 + .m1 = {.min = I8XX_M1_MIN, .max = I8XX_M1_MAX}, 121 + .m2 = {.min = I8XX_M2_MIN, .max = I8XX_M2_MAX}, 122 + .p = {.min = I8XX_P_MIN, .max = I8XX_P_MAX}, 123 + .p1 = {.min = I8XX_P1_MIN, .max = I8XX_P1_MAX}, 124 + .p2 = {.dot_limit = I8XX_P2_SLOW_LIMIT, 125 + .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST}, 126 + }, 127 + { /* INTEL_LIMIT_I8XX_LVDS */ 128 + .dot = {.min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX}, 129 + .vco = {.min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX}, 130 + .n = {.min = I8XX_N_MIN, .max = I8XX_N_MAX}, 131 + .m = {.min = I8XX_M_MIN, .max = I8XX_M_MAX}, 132 + .m1 = {.min = I8XX_M1_MIN, .max = I8XX_M1_MAX}, 133 + .m2 = {.min = I8XX_M2_MIN, .max = I8XX_M2_MAX}, 134 + .p = {.min = I8XX_P_MIN, .max = I8XX_P_MAX}, 135 + .p1 = {.min = I8XX_P1_LVDS_MIN, .max = I8XX_P1_LVDS_MAX}, 136 + .p2 = {.dot_limit = I8XX_P2_SLOW_LIMIT, 137 + .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST}, 138 + }, 139 + { /* INTEL_LIMIT_I9XX_SDVO_DAC */ 140 + .dot = {.min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, 141 + .vco = {.min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX}, 142 + .n = {.min = I9XX_N_MIN, .max = I9XX_N_MAX}, 143 + .m = {.min = I9XX_M_MIN, .max = I9XX_M_MAX}, 144 + .m1 = {.min = I9XX_M1_MIN, .max = I9XX_M1_MAX}, 145 + .m2 = {.min = I9XX_M2_MIN, .max = I9XX_M2_MAX}, 146 + .p = {.min = I9XX_P_SDVO_DAC_MIN, .max = I9XX_P_SDVO_DAC_MAX}, 147 + .p1 = {.min = I9XX_P1_MIN, .max = I9XX_P1_MAX}, 148 + .p2 = {.dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, 149 + .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = 150 + I9XX_P2_SDVO_DAC_FAST}, 151 + }, 152 + { /* INTEL_LIMIT_I9XX_LVDS */ 153 + .dot = {.min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, 154 + .vco = {.min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX}, 155 + .n = {.min = I9XX_N_MIN, .max = I9XX_N_MAX}, 156 + .m = {.min = I9XX_M_MIN, .max = I9XX_M_MAX}, 157 + .m1 = {.min = I9XX_M1_MIN, .max = I9XX_M1_MAX}, 158 + .m2 = {.min = I9XX_M2_MIN, .max = I9XX_M2_MAX}, 159 + .p = {.min = I9XX_P_LVDS_MIN, .max = I9XX_P_LVDS_MAX}, 160 + .p1 = {.min = I9XX_P1_MIN, .max = I9XX_P1_MAX}, 161 + /* The single-channel range is 25-112Mhz, and dual-channel 162 + * is 80-224Mhz. Prefer single channel as much as possible. 163 + */ 164 + .p2 = {.dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, 165 + .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST}, 166 + }, 167 + }; 168 + 169 + static const struct psb_intel_limit_t *psb_intel_limit(struct drm_crtc *crtc) 170 + { 171 + const struct psb_intel_limit_t *limit; 172 + 173 + if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) 174 + limit = &psb_intel_limits[INTEL_LIMIT_I9XX_LVDS]; 175 + else 176 + limit = &psb_intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; 177 + return limit; 178 + } 179 + 180 + /** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ 181 + 182 + static void i8xx_clock(int refclk, struct psb_intel_clock_t *clock) 183 + { 184 + clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); 185 + clock->p = clock->p1 * clock->p2; 186 + clock->vco = refclk * clock->m / (clock->n + 2); 187 + clock->dot = clock->vco / clock->p; 188 + } 189 + 190 + /** Derive the pixel clock for the given refclk and divisors for 9xx chips. */ 191 + 192 + static void i9xx_clock(int refclk, struct psb_intel_clock_t *clock) 193 + { 194 + clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); 195 + clock->p = clock->p1 * clock->p2; 196 + clock->vco = refclk * clock->m / (clock->n + 2); 197 + clock->dot = clock->vco / clock->p; 198 + } 199 + 200 + static void psb_intel_clock(struct drm_device *dev, int refclk, 201 + struct psb_intel_clock_t *clock) 202 + { 203 + return i9xx_clock(refclk, clock); 204 + } 205 + 206 + /** 207 + * Returns whether any output on the specified pipe is of the specified type 208 + */ 209 + bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type) 210 + { 211 + struct drm_device *dev = crtc->dev; 212 + struct drm_mode_config *mode_config = &dev->mode_config; 213 + struct drm_connector *l_entry; 214 + 215 + list_for_each_entry(l_entry, &mode_config->connector_list, head) { 216 + if (l_entry->encoder && l_entry->encoder->crtc == crtc) { 217 + struct psb_intel_output *psb_intel_output = 218 + to_psb_intel_output(l_entry); 219 + if (psb_intel_output->type == type) 220 + return true; 221 + } 222 + } 223 + return false; 224 + } 225 + 226 + #define INTELPllInvalid(s) { /* ErrorF (s) */; return false; } 227 + /** 228 + * Returns whether the given set of divisors are valid for a given refclk with 229 + * the given connectors. 230 + */ 231 + 232 + static bool psb_intel_PLL_is_valid(struct drm_crtc *crtc, 233 + struct psb_intel_clock_t *clock) 234 + { 235 + const struct psb_intel_limit_t *limit = psb_intel_limit(crtc); 236 + 237 + if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1) 238 + INTELPllInvalid("p1 out of range\n"); 239 + if (clock->p < limit->p.min || limit->p.max < clock->p) 240 + INTELPllInvalid("p out of range\n"); 241 + if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2) 242 + INTELPllInvalid("m2 out of range\n"); 243 + if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1) 244 + INTELPllInvalid("m1 out of range\n"); 245 + if (clock->m1 <= clock->m2) 246 + INTELPllInvalid("m1 <= m2\n"); 247 + if (clock->m < limit->m.min || limit->m.max < clock->m) 248 + INTELPllInvalid("m out of range\n"); 249 + if (clock->n < limit->n.min || limit->n.max < clock->n) 250 + INTELPllInvalid("n out of range\n"); 251 + if (clock->vco < limit->vco.min || limit->vco.max < clock->vco) 252 + INTELPllInvalid("vco out of range\n"); 253 + /* XXX: We may need to be checking "Dot clock" 254 + * depending on the multiplier, connector, etc., 255 + * rather than just a single range. 256 + */ 257 + if (clock->dot < limit->dot.min || limit->dot.max < clock->dot) 258 + INTELPllInvalid("dot out of range\n"); 259 + 260 + return true; 261 + } 262 + 263 + /** 264 + * Returns a set of divisors for the desired target clock with the given 265 + * refclk, or FALSE. The returned values represent the clock equation: 266 + * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. 267 + */ 268 + static bool psb_intel_find_best_PLL(struct drm_crtc *crtc, int target, 269 + int refclk, 270 + struct psb_intel_clock_t *best_clock) 271 + { 272 + struct drm_device *dev = crtc->dev; 273 + struct psb_intel_clock_t clock; 274 + const struct psb_intel_limit_t *limit = psb_intel_limit(crtc); 275 + int err = target; 276 + 277 + if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && 278 + (REG_READ(LVDS) & LVDS_PORT_EN) != 0) { 279 + /* 280 + * For LVDS, if the panel is on, just rely on its current 281 + * settings for dual-channel. We haven't figured out how to 282 + * reliably set up different single/dual channel state, if we 283 + * even can. 284 + */ 285 + if ((REG_READ(LVDS) & LVDS_CLKB_POWER_MASK) == 286 + LVDS_CLKB_POWER_UP) 287 + clock.p2 = limit->p2.p2_fast; 288 + else 289 + clock.p2 = limit->p2.p2_slow; 290 + } else { 291 + if (target < limit->p2.dot_limit) 292 + clock.p2 = limit->p2.p2_slow; 293 + else 294 + clock.p2 = limit->p2.p2_fast; 295 + } 296 + 297 + memset(best_clock, 0, sizeof(*best_clock)); 298 + 299 + for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; 300 + clock.m1++) { 301 + for (clock.m2 = limit->m2.min; 302 + clock.m2 < clock.m1 && clock.m2 <= limit->m2.max; 303 + clock.m2++) { 304 + for (clock.n = limit->n.min; 305 + clock.n <= limit->n.max; clock.n++) { 306 + for (clock.p1 = limit->p1.min; 307 + clock.p1 <= limit->p1.max; 308 + clock.p1++) { 309 + int this_err; 310 + 311 + psb_intel_clock(dev, refclk, &clock); 312 + 313 + if (!psb_intel_PLL_is_valid 314 + (crtc, &clock)) 315 + continue; 316 + 317 + this_err = abs(clock.dot - target); 318 + if (this_err < err) { 319 + *best_clock = clock; 320 + err = this_err; 321 + } 322 + } 323 + } 324 + } 325 + } 326 + 327 + return err != target; 328 + } 329 + 330 + void psb_intel_wait_for_vblank(struct drm_device *dev) 331 + { 332 + /* Wait for 20ms, i.e. one cycle at 50hz. */ 333 + mdelay(20); 334 + } 335 + 336 + int psb_intel_pipe_set_base(struct drm_crtc *crtc, 337 + int x, int y, struct drm_framebuffer *old_fb) 338 + { 339 + struct drm_device *dev = crtc->dev; 340 + /* struct drm_i915_master_private *master_priv; */ 341 + struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 342 + struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); 343 + int pipe = psb_intel_crtc->pipe; 344 + unsigned long start, offset; 345 + int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE); 346 + int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); 347 + int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; 348 + int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; 349 + u32 dspcntr; 350 + int ret = 0; 351 + 352 + if (!gma_power_begin(dev, true)) 353 + return 0; 354 + 355 + /* no fb bound */ 356 + if (!crtc->fb) { 357 + dev_dbg(dev->dev, "No FB bound\n"); 358 + goto psb_intel_pipe_cleaner; 359 + } 360 + 361 + /* We are displaying this buffer, make sure it is actually loaded 362 + into the GTT */ 363 + ret = psb_gtt_pin(psbfb->gtt); 364 + if (ret < 0) 365 + goto psb_intel_pipe_set_base_exit; 366 + start = psbfb->gtt->offset; 367 + 368 + offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); 369 + 370 + REG_WRITE(dspstride, crtc->fb->pitch); 371 + 372 + dspcntr = REG_READ(dspcntr_reg); 373 + dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; 374 + 375 + switch (crtc->fb->bits_per_pixel) { 376 + case 8: 377 + dspcntr |= DISPPLANE_8BPP; 378 + break; 379 + case 16: 380 + if (crtc->fb->depth == 15) 381 + dspcntr |= DISPPLANE_15_16BPP; 382 + else 383 + dspcntr |= DISPPLANE_16BPP; 384 + break; 385 + case 24: 386 + case 32: 387 + dspcntr |= DISPPLANE_32BPP_NO_ALPHA; 388 + break; 389 + default: 390 + dev_err(dev->dev, "Unknown color depth\n"); 391 + ret = -EINVAL; 392 + psb_gtt_unpin(psbfb->gtt); 393 + goto psb_intel_pipe_set_base_exit; 394 + } 395 + REG_WRITE(dspcntr_reg, dspcntr); 396 + 397 + 398 + if (0 /* FIXMEAC - check what PSB needs */) { 399 + REG_WRITE(dspbase, offset); 400 + REG_READ(dspbase); 401 + REG_WRITE(dspsurf, start); 402 + REG_READ(dspsurf); 403 + } else { 404 + REG_WRITE(dspbase, start + offset); 405 + REG_READ(dspbase); 406 + } 407 + 408 + psb_intel_pipe_cleaner: 409 + /* If there was a previous display we can now unpin it */ 410 + if (old_fb) 411 + psb_gtt_unpin(to_psb_fb(old_fb)->gtt); 412 + 413 + psb_intel_pipe_set_base_exit: 414 + gma_power_end(dev); 415 + return ret; 416 + } 417 + 418 + /** 419 + * Sets the power management mode of the pipe and plane. 420 + * 421 + * This code should probably grow support for turning the cursor off and back 422 + * on appropriately at the same time as we're turning the pipe off/on. 423 + */ 424 + static void psb_intel_crtc_dpms(struct drm_crtc *crtc, int mode) 425 + { 426 + struct drm_device *dev = crtc->dev; 427 + /* struct drm_i915_master_private *master_priv; */ 428 + /* struct drm_i915_private *dev_priv = dev->dev_private; */ 429 + struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 430 + int pipe = psb_intel_crtc->pipe; 431 + int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; 432 + int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; 433 + int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE; 434 + int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; 435 + u32 temp; 436 + bool enabled; 437 + 438 + /* XXX: When our outputs are all unaware of DPMS modes other than off 439 + * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. 440 + */ 441 + switch (mode) { 442 + case DRM_MODE_DPMS_ON: 443 + case DRM_MODE_DPMS_STANDBY: 444 + case DRM_MODE_DPMS_SUSPEND: 445 + /* Enable the DPLL */ 446 + temp = REG_READ(dpll_reg); 447 + if ((temp & DPLL_VCO_ENABLE) == 0) { 448 + REG_WRITE(dpll_reg, temp); 449 + REG_READ(dpll_reg); 450 + /* Wait for the clocks to stabilize. */ 451 + udelay(150); 452 + REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); 453 + REG_READ(dpll_reg); 454 + /* Wait for the clocks to stabilize. */ 455 + udelay(150); 456 + REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); 457 + REG_READ(dpll_reg); 458 + /* Wait for the clocks to stabilize. */ 459 + udelay(150); 460 + } 461 + 462 + /* Enable the pipe */ 463 + temp = REG_READ(pipeconf_reg); 464 + if ((temp & PIPEACONF_ENABLE) == 0) 465 + REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); 466 + 467 + /* Enable the plane */ 468 + temp = REG_READ(dspcntr_reg); 469 + if ((temp & DISPLAY_PLANE_ENABLE) == 0) { 470 + REG_WRITE(dspcntr_reg, 471 + temp | DISPLAY_PLANE_ENABLE); 472 + /* Flush the plane changes */ 473 + REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); 474 + } 475 + 476 + psb_intel_crtc_load_lut(crtc); 477 + 478 + /* Give the overlay scaler a chance to enable 479 + * if it's on this pipe */ 480 + /* psb_intel_crtc_dpms_video(crtc, true); TODO */ 481 + break; 482 + case DRM_MODE_DPMS_OFF: 483 + /* Give the overlay scaler a chance to disable 484 + * if it's on this pipe */ 485 + /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */ 486 + 487 + /* Disable the VGA plane that we never use */ 488 + REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); 489 + 490 + /* Disable display plane */ 491 + temp = REG_READ(dspcntr_reg); 492 + if ((temp & DISPLAY_PLANE_ENABLE) != 0) { 493 + REG_WRITE(dspcntr_reg, 494 + temp & ~DISPLAY_PLANE_ENABLE); 495 + /* Flush the plane changes */ 496 + REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); 497 + REG_READ(dspbase_reg); 498 + } 499 + 500 + /* Next, disable display pipes */ 501 + temp = REG_READ(pipeconf_reg); 502 + if ((temp & PIPEACONF_ENABLE) != 0) { 503 + REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); 504 + REG_READ(pipeconf_reg); 505 + } 506 + 507 + /* Wait for vblank for the disable to take effect. */ 508 + psb_intel_wait_for_vblank(dev); 509 + 510 + temp = REG_READ(dpll_reg); 511 + if ((temp & DPLL_VCO_ENABLE) != 0) { 512 + REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); 513 + REG_READ(dpll_reg); 514 + } 515 + 516 + /* Wait for the clocks to turn off. */ 517 + udelay(150); 518 + break; 519 + } 520 + 521 + enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF; 522 + 523 + /*Set FIFO Watermarks*/ 524 + REG_WRITE(DSPARB, 0x3F3E); 525 + } 526 + 527 + static void psb_intel_crtc_prepare(struct drm_crtc *crtc) 528 + { 529 + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 530 + crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); 531 + } 532 + 533 + static void psb_intel_crtc_commit(struct drm_crtc *crtc) 534 + { 535 + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 536 + crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); 537 + } 538 + 539 + void psb_intel_encoder_prepare(struct drm_encoder *encoder) 540 + { 541 + struct drm_encoder_helper_funcs *encoder_funcs = 542 + encoder->helper_private; 543 + /* lvds has its own version of prepare see psb_intel_lvds_prepare */ 544 + encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF); 545 + } 546 + 547 + void psb_intel_encoder_commit(struct drm_encoder *encoder) 548 + { 549 + struct drm_encoder_helper_funcs *encoder_funcs = 550 + encoder->helper_private; 551 + /* lvds has its own version of commit see psb_intel_lvds_commit */ 552 + encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); 553 + } 554 + 555 + static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc, 556 + struct drm_display_mode *mode, 557 + struct drm_display_mode *adjusted_mode) 558 + { 559 + return true; 560 + } 561 + 562 + 563 + /** 564 + * Return the pipe currently connected to the panel fitter, 565 + * or -1 if the panel fitter is not present or not in use 566 + */ 567 + static int psb_intel_panel_fitter_pipe(struct drm_device *dev) 568 + { 569 + u32 pfit_control; 570 + 571 + pfit_control = REG_READ(PFIT_CONTROL); 572 + 573 + /* See if the panel fitter is in use */ 574 + if ((pfit_control & PFIT_ENABLE) == 0) 575 + return -1; 576 + /* Must be on PIPE 1 for PSB */ 577 + return 1; 578 + } 579 + 580 + static int psb_intel_crtc_mode_set(struct drm_crtc *crtc, 581 + struct drm_display_mode *mode, 582 + struct drm_display_mode *adjusted_mode, 583 + int x, int y, 584 + struct drm_framebuffer *old_fb) 585 + { 586 + struct drm_device *dev = crtc->dev; 587 + struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 588 + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 589 + int pipe = psb_intel_crtc->pipe; 590 + int fp_reg = (pipe == 0) ? FPA0 : FPB0; 591 + int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; 592 + int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; 593 + int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; 594 + int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; 595 + int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; 596 + int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; 597 + int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; 598 + int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; 599 + int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; 600 + int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; 601 + int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; 602 + int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; 603 + int refclk; 604 + struct psb_intel_clock_t clock; 605 + u32 dpll = 0, fp = 0, dspcntr, pipeconf; 606 + bool ok, is_sdvo = false, is_dvo = false; 607 + bool is_crt = false, is_lvds = false, is_tv = false; 608 + struct drm_mode_config *mode_config = &dev->mode_config; 609 + struct drm_connector *connector; 610 + 611 + /* No scan out no play */ 612 + if (crtc->fb == NULL) { 613 + crtc_funcs->mode_set_base(crtc, x, y, old_fb); 614 + return 0; 615 + } 616 + 617 + list_for_each_entry(connector, &mode_config->connector_list, head) { 618 + struct psb_intel_output *psb_intel_output = 619 + to_psb_intel_output(connector); 620 + 621 + if (!connector->encoder 622 + || connector->encoder->crtc != crtc) 623 + continue; 624 + 625 + switch (psb_intel_output->type) { 626 + case INTEL_OUTPUT_LVDS: 627 + is_lvds = true; 628 + break; 629 + case INTEL_OUTPUT_SDVO: 630 + is_sdvo = true; 631 + break; 632 + case INTEL_OUTPUT_DVO: 633 + is_dvo = true; 634 + break; 635 + case INTEL_OUTPUT_TVOUT: 636 + is_tv = true; 637 + break; 638 + case INTEL_OUTPUT_ANALOG: 639 + is_crt = true; 640 + break; 641 + } 642 + } 643 + 644 + refclk = 96000; 645 + 646 + ok = psb_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, 647 + &clock); 648 + if (!ok) { 649 + dev_err(dev->dev, "Couldn't find PLL settings for mode!\n"); 650 + return 0; 651 + } 652 + 653 + fp = clock.n << 16 | clock.m1 << 8 | clock.m2; 654 + 655 + dpll = DPLL_VGA_MODE_DIS; 656 + if (is_lvds) { 657 + dpll |= DPLLB_MODE_LVDS; 658 + dpll |= DPLL_DVO_HIGH_SPEED; 659 + } else 660 + dpll |= DPLLB_MODE_DAC_SERIAL; 661 + if (is_sdvo) { 662 + int sdvo_pixel_multiply = 663 + adjusted_mode->clock / mode->clock; 664 + dpll |= DPLL_DVO_HIGH_SPEED; 665 + dpll |= 666 + (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; 667 + } 668 + 669 + /* compute bitmask from p1 value */ 670 + dpll |= (1 << (clock.p1 - 1)) << 16; 671 + switch (clock.p2) { 672 + case 5: 673 + dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; 674 + break; 675 + case 7: 676 + dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7; 677 + break; 678 + case 10: 679 + dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10; 680 + break; 681 + case 14: 682 + dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; 683 + break; 684 + } 685 + 686 + if (is_tv) { 687 + /* XXX: just matching BIOS for now */ 688 + /* dpll |= PLL_REF_INPUT_TVCLKINBC; */ 689 + dpll |= 3; 690 + } 691 + dpll |= PLL_REF_INPUT_DREFCLK; 692 + 693 + /* setup pipeconf */ 694 + pipeconf = REG_READ(pipeconf_reg); 695 + 696 + /* Set up the display plane register */ 697 + dspcntr = DISPPLANE_GAMMA_ENABLE; 698 + 699 + if (pipe == 0) 700 + dspcntr |= DISPPLANE_SEL_PIPE_A; 701 + else 702 + dspcntr |= DISPPLANE_SEL_PIPE_B; 703 + 704 + dspcntr |= DISPLAY_PLANE_ENABLE; 705 + pipeconf |= PIPEACONF_ENABLE; 706 + dpll |= DPLL_VCO_ENABLE; 707 + 708 + 709 + /* Disable the panel fitter if it was on our pipe */ 710 + if (psb_intel_panel_fitter_pipe(dev) == pipe) 711 + REG_WRITE(PFIT_CONTROL, 0); 712 + 713 + drm_mode_debug_printmodeline(mode); 714 + 715 + if (dpll & DPLL_VCO_ENABLE) { 716 + REG_WRITE(fp_reg, fp); 717 + REG_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); 718 + REG_READ(dpll_reg); 719 + udelay(150); 720 + } 721 + 722 + /* The LVDS pin pair needs to be on before the DPLLs are enabled. 723 + * This is an exception to the general rule that mode_set doesn't turn 724 + * things on. 725 + */ 726 + if (is_lvds) { 727 + u32 lvds = REG_READ(LVDS); 728 + 729 + lvds &= ~LVDS_PIPEB_SELECT; 730 + if (pipe == 1) 731 + lvds |= LVDS_PIPEB_SELECT; 732 + 733 + lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; 734 + /* Set the B0-B3 data pairs corresponding to 735 + * whether we're going to 736 + * set the DPLLs for dual-channel mode or not. 737 + */ 738 + lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); 739 + if (clock.p2 == 7) 740 + lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; 741 + 742 + /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP) 743 + * appropriately here, but we need to look more 744 + * thoroughly into how panels behave in the two modes. 745 + */ 746 + 747 + REG_WRITE(LVDS, lvds); 748 + REG_READ(LVDS); 749 + } 750 + 751 + REG_WRITE(fp_reg, fp); 752 + REG_WRITE(dpll_reg, dpll); 753 + REG_READ(dpll_reg); 754 + /* Wait for the clocks to stabilize. */ 755 + udelay(150); 756 + 757 + /* write it again -- the BIOS does, after all */ 758 + REG_WRITE(dpll_reg, dpll); 759 + 760 + REG_READ(dpll_reg); 761 + /* Wait for the clocks to stabilize. */ 762 + udelay(150); 763 + 764 + REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | 765 + ((adjusted_mode->crtc_htotal - 1) << 16)); 766 + REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | 767 + ((adjusted_mode->crtc_hblank_end - 1) << 16)); 768 + REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | 769 + ((adjusted_mode->crtc_hsync_end - 1) << 16)); 770 + REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | 771 + ((adjusted_mode->crtc_vtotal - 1) << 16)); 772 + REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | 773 + ((adjusted_mode->crtc_vblank_end - 1) << 16)); 774 + REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | 775 + ((adjusted_mode->crtc_vsync_end - 1) << 16)); 776 + /* pipesrc and dspsize control the size that is scaled from, 777 + * which should always be the user's requested size. 778 + */ 779 + REG_WRITE(dspsize_reg, 780 + ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); 781 + REG_WRITE(dsppos_reg, 0); 782 + REG_WRITE(pipesrc_reg, 783 + ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); 784 + REG_WRITE(pipeconf_reg, pipeconf); 785 + REG_READ(pipeconf_reg); 786 + 787 + psb_intel_wait_for_vblank(dev); 788 + 789 + REG_WRITE(dspcntr_reg, dspcntr); 790 + 791 + /* Flush the plane changes */ 792 + crtc_funcs->mode_set_base(crtc, x, y, old_fb); 793 + 794 + psb_intel_wait_for_vblank(dev); 795 + 796 + return 0; 797 + } 798 + 799 + /** Loads the palette/gamma unit for the CRTC with the prepared values */ 800 + void psb_intel_crtc_load_lut(struct drm_crtc *crtc) 801 + { 802 + struct drm_device *dev = crtc->dev; 803 + struct drm_psb_private *dev_priv = 804 + (struct drm_psb_private *)dev->dev_private; 805 + struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 806 + int palreg = PALETTE_A; 807 + int i; 808 + 809 + /* The clocks have to be on to load the palette. */ 810 + if (!crtc->enabled) 811 + return; 812 + 813 + switch (psb_intel_crtc->pipe) { 814 + case 0: 815 + break; 816 + case 1: 817 + palreg = PALETTE_B; 818 + break; 819 + case 2: 820 + palreg = PALETTE_C; 821 + break; 822 + default: 823 + dev_err(dev->dev, "Illegal Pipe Number.\n"); 824 + return; 825 + } 826 + 827 + if (gma_power_begin(dev, false)) { 828 + for (i = 0; i < 256; i++) { 829 + REG_WRITE(palreg + 4 * i, 830 + ((psb_intel_crtc->lut_r[i] + 831 + psb_intel_crtc->lut_adj[i]) << 16) | 832 + ((psb_intel_crtc->lut_g[i] + 833 + psb_intel_crtc->lut_adj[i]) << 8) | 834 + (psb_intel_crtc->lut_b[i] + 835 + psb_intel_crtc->lut_adj[i])); 836 + } 837 + gma_power_end(dev); 838 + } else { 839 + for (i = 0; i < 256; i++) { 840 + dev_priv->save_palette_a[i] = 841 + ((psb_intel_crtc->lut_r[i] + 842 + psb_intel_crtc->lut_adj[i]) << 16) | 843 + ((psb_intel_crtc->lut_g[i] + 844 + psb_intel_crtc->lut_adj[i]) << 8) | 845 + (psb_intel_crtc->lut_b[i] + 846 + psb_intel_crtc->lut_adj[i]); 847 + } 848 + 849 + } 850 + } 851 + 852 + /** 853 + * Save HW states of giving crtc 854 + */ 855 + static void psb_intel_crtc_save(struct drm_crtc *crtc) 856 + { 857 + struct drm_device *dev = crtc->dev; 858 + /* struct drm_psb_private *dev_priv = 859 + (struct drm_psb_private *)dev->dev_private; */ 860 + struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 861 + struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state; 862 + int pipeA = (psb_intel_crtc->pipe == 0); 863 + uint32_t paletteReg; 864 + int i; 865 + 866 + if (!crtc_state) { 867 + dev_err(dev->dev, "No CRTC state found\n"); 868 + return; 869 + } 870 + 871 + crtc_state->saveDSPCNTR = REG_READ(pipeA ? DSPACNTR : DSPBCNTR); 872 + crtc_state->savePIPECONF = REG_READ(pipeA ? PIPEACONF : PIPEBCONF); 873 + crtc_state->savePIPESRC = REG_READ(pipeA ? PIPEASRC : PIPEBSRC); 874 + crtc_state->saveFP0 = REG_READ(pipeA ? FPA0 : FPB0); 875 + crtc_state->saveFP1 = REG_READ(pipeA ? FPA1 : FPB1); 876 + crtc_state->saveDPLL = REG_READ(pipeA ? DPLL_A : DPLL_B); 877 + crtc_state->saveHTOTAL = REG_READ(pipeA ? HTOTAL_A : HTOTAL_B); 878 + crtc_state->saveHBLANK = REG_READ(pipeA ? HBLANK_A : HBLANK_B); 879 + crtc_state->saveHSYNC = REG_READ(pipeA ? HSYNC_A : HSYNC_B); 880 + crtc_state->saveVTOTAL = REG_READ(pipeA ? VTOTAL_A : VTOTAL_B); 881 + crtc_state->saveVBLANK = REG_READ(pipeA ? VBLANK_A : VBLANK_B); 882 + crtc_state->saveVSYNC = REG_READ(pipeA ? VSYNC_A : VSYNC_B); 883 + crtc_state->saveDSPSTRIDE = REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE); 884 + 885 + /*NOTE: DSPSIZE DSPPOS only for psb*/ 886 + crtc_state->saveDSPSIZE = REG_READ(pipeA ? DSPASIZE : DSPBSIZE); 887 + crtc_state->saveDSPPOS = REG_READ(pipeA ? DSPAPOS : DSPBPOS); 888 + 889 + crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE); 890 + 891 + paletteReg = pipeA ? PALETTE_A : PALETTE_B; 892 + for (i = 0; i < 256; ++i) 893 + crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2)); 894 + } 895 + 896 + /** 897 + * Restore HW states of giving crtc 898 + */ 899 + static void psb_intel_crtc_restore(struct drm_crtc *crtc) 900 + { 901 + struct drm_device *dev = crtc->dev; 902 + /* struct drm_psb_private * dev_priv = 903 + (struct drm_psb_private *)dev->dev_private; */ 904 + struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 905 + struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state; 906 + /* struct drm_crtc_helper_funcs * crtc_funcs = crtc->helper_private; */ 907 + int pipeA = (psb_intel_crtc->pipe == 0); 908 + uint32_t paletteReg; 909 + int i; 910 + 911 + if (!crtc_state) { 912 + dev_err(dev->dev, "No crtc state\n"); 913 + return; 914 + } 915 + 916 + if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) { 917 + REG_WRITE(pipeA ? DPLL_A : DPLL_B, 918 + crtc_state->saveDPLL & ~DPLL_VCO_ENABLE); 919 + REG_READ(pipeA ? DPLL_A : DPLL_B); 920 + udelay(150); 921 + } 922 + 923 + REG_WRITE(pipeA ? FPA0 : FPB0, crtc_state->saveFP0); 924 + REG_READ(pipeA ? FPA0 : FPB0); 925 + 926 + REG_WRITE(pipeA ? FPA1 : FPB1, crtc_state->saveFP1); 927 + REG_READ(pipeA ? FPA1 : FPB1); 928 + 929 + REG_WRITE(pipeA ? DPLL_A : DPLL_B, crtc_state->saveDPLL); 930 + REG_READ(pipeA ? DPLL_A : DPLL_B); 931 + udelay(150); 932 + 933 + REG_WRITE(pipeA ? HTOTAL_A : HTOTAL_B, crtc_state->saveHTOTAL); 934 + REG_WRITE(pipeA ? HBLANK_A : HBLANK_B, crtc_state->saveHBLANK); 935 + REG_WRITE(pipeA ? HSYNC_A : HSYNC_B, crtc_state->saveHSYNC); 936 + REG_WRITE(pipeA ? VTOTAL_A : VTOTAL_B, crtc_state->saveVTOTAL); 937 + REG_WRITE(pipeA ? VBLANK_A : VBLANK_B, crtc_state->saveVBLANK); 938 + REG_WRITE(pipeA ? VSYNC_A : VSYNC_B, crtc_state->saveVSYNC); 939 + REG_WRITE(pipeA ? DSPASTRIDE : DSPBSTRIDE, crtc_state->saveDSPSTRIDE); 940 + 941 + REG_WRITE(pipeA ? DSPASIZE : DSPBSIZE, crtc_state->saveDSPSIZE); 942 + REG_WRITE(pipeA ? DSPAPOS : DSPBPOS, crtc_state->saveDSPPOS); 943 + 944 + REG_WRITE(pipeA ? PIPEASRC : PIPEBSRC, crtc_state->savePIPESRC); 945 + REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE); 946 + REG_WRITE(pipeA ? PIPEACONF : PIPEBCONF, crtc_state->savePIPECONF); 947 + 948 + psb_intel_wait_for_vblank(dev); 949 + 950 + REG_WRITE(pipeA ? DSPACNTR : DSPBCNTR, crtc_state->saveDSPCNTR); 951 + REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE); 952 + 953 + psb_intel_wait_for_vblank(dev); 954 + 955 + paletteReg = pipeA ? PALETTE_A : PALETTE_B; 956 + for (i = 0; i < 256; ++i) 957 + REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]); 958 + } 959 + 960 + static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc, 961 + struct drm_file *file_priv, 962 + uint32_t handle, 963 + uint32_t width, uint32_t height) 964 + { 965 + struct drm_device *dev = crtc->dev; 966 + struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 967 + int pipe = psb_intel_crtc->pipe; 968 + uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; 969 + uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; 970 + uint32_t temp; 971 + size_t addr = 0; 972 + struct gtt_range *gt; 973 + struct drm_gem_object *obj; 974 + int ret; 975 + 976 + /* if we want to turn of the cursor ignore width and height */ 977 + if (!handle) { 978 + /* turn off the cursor */ 979 + temp = CURSOR_MODE_DISABLE; 980 + 981 + if (gma_power_begin(dev, false)) { 982 + REG_WRITE(control, temp); 983 + REG_WRITE(base, 0); 984 + gma_power_end(dev); 985 + } 986 + 987 + /* Unpin the old GEM object */ 988 + if (psb_intel_crtc->cursor_obj) { 989 + gt = container_of(psb_intel_crtc->cursor_obj, 990 + struct gtt_range, gem); 991 + psb_gtt_unpin(gt); 992 + drm_gem_object_unreference(psb_intel_crtc->cursor_obj); 993 + psb_intel_crtc->cursor_obj = NULL; 994 + } 995 + 996 + return 0; 997 + } 998 + 999 + /* Currently we only support 64x64 cursors */ 1000 + if (width != 64 || height != 64) { 1001 + dev_dbg(dev->dev, "we currently only support 64x64 cursors\n"); 1002 + return -EINVAL; 1003 + } 1004 + 1005 + obj = drm_gem_object_lookup(dev, file_priv, handle); 1006 + if (!obj) 1007 + return -ENOENT; 1008 + 1009 + if (obj->size < width * height * 4) { 1010 + dev_dbg(dev->dev, "buffer is to small\n"); 1011 + return -ENOMEM; 1012 + } 1013 + 1014 + gt = container_of(obj, struct gtt_range, gem); 1015 + 1016 + /* Pin the memory into the GTT */ 1017 + ret = psb_gtt_pin(gt); 1018 + if (ret) { 1019 + dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle); 1020 + return ret; 1021 + } 1022 + 1023 + 1024 + addr = gt->offset; /* Or resource.start ??? */ 1025 + 1026 + psb_intel_crtc->cursor_addr = addr; 1027 + 1028 + temp = 0; 1029 + /* set the pipe for the cursor */ 1030 + temp |= (pipe << 28); 1031 + temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; 1032 + 1033 + if (gma_power_begin(dev, false)) { 1034 + REG_WRITE(control, temp); 1035 + REG_WRITE(base, addr); 1036 + gma_power_end(dev); 1037 + } 1038 + 1039 + /* unpin the old bo */ 1040 + if (psb_intel_crtc->cursor_obj) { 1041 + gt = container_of(psb_intel_crtc->cursor_obj, 1042 + struct gtt_range, gem); 1043 + psb_gtt_unpin(gt); 1044 + drm_gem_object_unreference(psb_intel_crtc->cursor_obj); 1045 + psb_intel_crtc->cursor_obj = obj; 1046 + } 1047 + return 0; 1048 + } 1049 + 1050 + static int psb_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) 1051 + { 1052 + struct drm_device *dev = crtc->dev; 1053 + struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 1054 + int pipe = psb_intel_crtc->pipe; 1055 + uint32_t temp = 0; 1056 + uint32_t addr; 1057 + 1058 + 1059 + if (x < 0) { 1060 + temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT); 1061 + x = -x; 1062 + } 1063 + if (y < 0) { 1064 + temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT); 1065 + y = -y; 1066 + } 1067 + 1068 + temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT); 1069 + temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); 1070 + 1071 + addr = psb_intel_crtc->cursor_addr; 1072 + 1073 + if (gma_power_begin(dev, false)) { 1074 + REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp); 1075 + REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, addr); 1076 + gma_power_end(dev); 1077 + } 1078 + return 0; 1079 + } 1080 + 1081 + void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, 1082 + u16 *green, u16 *blue, uint32_t type, uint32_t size) 1083 + { 1084 + struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 1085 + int i; 1086 + 1087 + if (size != 256) 1088 + return; 1089 + 1090 + for (i = 0; i < 256; i++) { 1091 + psb_intel_crtc->lut_r[i] = red[i] >> 8; 1092 + psb_intel_crtc->lut_g[i] = green[i] >> 8; 1093 + psb_intel_crtc->lut_b[i] = blue[i] >> 8; 1094 + } 1095 + 1096 + psb_intel_crtc_load_lut(crtc); 1097 + } 1098 + 1099 + static int psb_crtc_set_config(struct drm_mode_set *set) 1100 + { 1101 + int ret; 1102 + struct drm_device *dev = set->crtc->dev; 1103 + struct drm_psb_private *dev_priv = dev->dev_private; 1104 + 1105 + if (!dev_priv->rpm_enabled) 1106 + return drm_crtc_helper_set_config(set); 1107 + 1108 + pm_runtime_forbid(&dev->pdev->dev); 1109 + ret = drm_crtc_helper_set_config(set); 1110 + pm_runtime_allow(&dev->pdev->dev); 1111 + return ret; 1112 + } 1113 + 1114 + /* Returns the clock of the currently programmed mode of the given pipe. */ 1115 + static int psb_intel_crtc_clock_get(struct drm_device *dev, 1116 + struct drm_crtc *crtc) 1117 + { 1118 + struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 1119 + int pipe = psb_intel_crtc->pipe; 1120 + u32 dpll; 1121 + u32 fp; 1122 + struct psb_intel_clock_t clock; 1123 + bool is_lvds; 1124 + struct drm_psb_private *dev_priv = dev->dev_private; 1125 + 1126 + if (gma_power_begin(dev, false)) { 1127 + dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B); 1128 + if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) 1129 + fp = REG_READ((pipe == 0) ? FPA0 : FPB0); 1130 + else 1131 + fp = REG_READ((pipe == 0) ? FPA1 : FPB1); 1132 + is_lvds = (pipe == 1) && (REG_READ(LVDS) & LVDS_PORT_EN); 1133 + gma_power_end(dev); 1134 + } else { 1135 + dpll = (pipe == 0) ? 1136 + dev_priv->saveDPLL_A : dev_priv->saveDPLL_B; 1137 + 1138 + if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) 1139 + fp = (pipe == 0) ? 1140 + dev_priv->saveFPA0 : 1141 + dev_priv->saveFPB0; 1142 + else 1143 + fp = (pipe == 0) ? 1144 + dev_priv->saveFPA1 : 1145 + dev_priv->saveFPB1; 1146 + 1147 + is_lvds = (pipe == 1) && (dev_priv->saveLVDS & LVDS_PORT_EN); 1148 + } 1149 + 1150 + clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT; 1151 + clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT; 1152 + clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT; 1153 + 1154 + if (is_lvds) { 1155 + clock.p1 = 1156 + ffs((dpll & 1157 + DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >> 1158 + DPLL_FPA01_P1_POST_DIV_SHIFT); 1159 + clock.p2 = 14; 1160 + 1161 + if ((dpll & PLL_REF_INPUT_MASK) == 1162 + PLLB_REF_INPUT_SPREADSPECTRUMIN) { 1163 + /* XXX: might not be 66MHz */ 1164 + i8xx_clock(66000, &clock); 1165 + } else 1166 + i8xx_clock(48000, &clock); 1167 + } else { 1168 + if (dpll & PLL_P1_DIVIDE_BY_TWO) 1169 + clock.p1 = 2; 1170 + else { 1171 + clock.p1 = 1172 + ((dpll & 1173 + DPLL_FPA01_P1_POST_DIV_MASK_I830) >> 1174 + DPLL_FPA01_P1_POST_DIV_SHIFT) + 2; 1175 + } 1176 + if (dpll & PLL_P2_DIVIDE_BY_4) 1177 + clock.p2 = 4; 1178 + else 1179 + clock.p2 = 2; 1180 + 1181 + i8xx_clock(48000, &clock); 1182 + } 1183 + 1184 + /* XXX: It would be nice to validate the clocks, but we can't reuse 1185 + * i830PllIsValid() because it relies on the xf86_config connector 1186 + * configuration being accurate, which it isn't necessarily. 1187 + */ 1188 + 1189 + return clock.dot; 1190 + } 1191 + 1192 + /** Returns the currently programmed mode of the given pipe. */ 1193 + struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev, 1194 + struct drm_crtc *crtc) 1195 + { 1196 + struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 1197 + int pipe = psb_intel_crtc->pipe; 1198 + struct drm_display_mode *mode; 1199 + int htot; 1200 + int hsync; 1201 + int vtot; 1202 + int vsync; 1203 + struct drm_psb_private *dev_priv = dev->dev_private; 1204 + 1205 + if (gma_power_begin(dev, false)) { 1206 + htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B); 1207 + hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B); 1208 + vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B); 1209 + vsync = REG_READ((pipe == 0) ? VSYNC_A : VSYNC_B); 1210 + gma_power_end(dev); 1211 + } else { 1212 + htot = (pipe == 0) ? 1213 + dev_priv->saveHTOTAL_A : dev_priv->saveHTOTAL_B; 1214 + hsync = (pipe == 0) ? 1215 + dev_priv->saveHSYNC_A : dev_priv->saveHSYNC_B; 1216 + vtot = (pipe == 0) ? 1217 + dev_priv->saveVTOTAL_A : dev_priv->saveVTOTAL_B; 1218 + vsync = (pipe == 0) ? 1219 + dev_priv->saveVSYNC_A : dev_priv->saveVSYNC_B; 1220 + } 1221 + 1222 + mode = kzalloc(sizeof(*mode), GFP_KERNEL); 1223 + if (!mode) 1224 + return NULL; 1225 + 1226 + mode->clock = psb_intel_crtc_clock_get(dev, crtc); 1227 + mode->hdisplay = (htot & 0xffff) + 1; 1228 + mode->htotal = ((htot & 0xffff0000) >> 16) + 1; 1229 + mode->hsync_start = (hsync & 0xffff) + 1; 1230 + mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1; 1231 + mode->vdisplay = (vtot & 0xffff) + 1; 1232 + mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1; 1233 + mode->vsync_start = (vsync & 0xffff) + 1; 1234 + mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1; 1235 + 1236 + drm_mode_set_name(mode); 1237 + drm_mode_set_crtcinfo(mode, 0); 1238 + 1239 + return mode; 1240 + } 1241 + 1242 + void psb_intel_crtc_destroy(struct drm_crtc *crtc) 1243 + { 1244 + struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 1245 + struct gtt_range *gt; 1246 + 1247 + /* Unpin the old GEM object */ 1248 + if (psb_intel_crtc->cursor_obj) { 1249 + gt = container_of(psb_intel_crtc->cursor_obj, 1250 + struct gtt_range, gem); 1251 + psb_gtt_unpin(gt); 1252 + drm_gem_object_unreference(psb_intel_crtc->cursor_obj); 1253 + psb_intel_crtc->cursor_obj = NULL; 1254 + } 1255 + kfree(psb_intel_crtc->crtc_state); 1256 + drm_crtc_cleanup(crtc); 1257 + kfree(psb_intel_crtc); 1258 + } 1259 + 1260 + const struct drm_crtc_helper_funcs psb_intel_helper_funcs = { 1261 + .dpms = psb_intel_crtc_dpms, 1262 + .mode_fixup = psb_intel_crtc_mode_fixup, 1263 + .mode_set = psb_intel_crtc_mode_set, 1264 + .mode_set_base = psb_intel_pipe_set_base, 1265 + .prepare = psb_intel_crtc_prepare, 1266 + .commit = psb_intel_crtc_commit, 1267 + }; 1268 + 1269 + const struct drm_crtc_funcs psb_intel_crtc_funcs = { 1270 + .save = psb_intel_crtc_save, 1271 + .restore = psb_intel_crtc_restore, 1272 + .cursor_set = psb_intel_crtc_cursor_set, 1273 + .cursor_move = psb_intel_crtc_cursor_move, 1274 + .gamma_set = psb_intel_crtc_gamma_set, 1275 + .set_config = psb_crtc_set_config, 1276 + .destroy = psb_intel_crtc_destroy, 1277 + }; 1278 + 1279 + /* 1280 + * Set the default value of cursor control and base register 1281 + * to zero. This is a workaround for h/w defect on Oaktrail 1282 + */ 1283 + static void psb_intel_cursor_init(struct drm_device *dev, int pipe) 1284 + { 1285 + u32 control[3] = { CURACNTR, CURBCNTR, CURCCNTR }; 1286 + u32 base[3] = { CURABASE, CURBBASE, CURCBASE }; 1287 + 1288 + REG_WRITE(control[pipe], 0); 1289 + REG_WRITE(base[pipe], 0); 1290 + } 1291 + 1292 + void psb_intel_crtc_init(struct drm_device *dev, int pipe, 1293 + struct psb_intel_mode_device *mode_dev) 1294 + { 1295 + struct drm_psb_private *dev_priv = dev->dev_private; 1296 + struct psb_intel_crtc *psb_intel_crtc; 1297 + int i; 1298 + uint16_t *r_base, *g_base, *b_base; 1299 + 1300 + /* We allocate a extra array of drm_connector pointers 1301 + * for fbdev after the crtc */ 1302 + psb_intel_crtc = 1303 + kzalloc(sizeof(struct psb_intel_crtc) + 1304 + (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)), 1305 + GFP_KERNEL); 1306 + if (psb_intel_crtc == NULL) 1307 + return; 1308 + 1309 + psb_intel_crtc->crtc_state = 1310 + kzalloc(sizeof(struct psb_intel_crtc_state), GFP_KERNEL); 1311 + if (!psb_intel_crtc->crtc_state) { 1312 + dev_err(dev->dev, "Crtc state error: No memory\n"); 1313 + kfree(psb_intel_crtc); 1314 + return; 1315 + } 1316 + 1317 + /* Set the CRTC operations from the chip specific data */ 1318 + drm_crtc_init(dev, &psb_intel_crtc->base, dev_priv->ops->crtc_funcs); 1319 + 1320 + drm_mode_crtc_set_gamma_size(&psb_intel_crtc->base, 256); 1321 + psb_intel_crtc->pipe = pipe; 1322 + psb_intel_crtc->plane = pipe; 1323 + 1324 + r_base = psb_intel_crtc->base.gamma_store; 1325 + g_base = r_base + 256; 1326 + b_base = g_base + 256; 1327 + for (i = 0; i < 256; i++) { 1328 + psb_intel_crtc->lut_r[i] = i; 1329 + psb_intel_crtc->lut_g[i] = i; 1330 + psb_intel_crtc->lut_b[i] = i; 1331 + r_base[i] = i << 8; 1332 + g_base[i] = i << 8; 1333 + b_base[i] = i << 8; 1334 + 1335 + psb_intel_crtc->lut_adj[i] = 0; 1336 + } 1337 + 1338 + psb_intel_crtc->mode_dev = mode_dev; 1339 + psb_intel_crtc->cursor_addr = 0; 1340 + 1341 + drm_crtc_helper_add(&psb_intel_crtc->base, 1342 + dev_priv->ops->crtc_helper); 1343 + 1344 + /* Setup the array of drm_connector pointer array */ 1345 + psb_intel_crtc->mode_set.crtc = &psb_intel_crtc->base; 1346 + BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) || 1347 + dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] != NULL); 1348 + dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] = 1349 + &psb_intel_crtc->base; 1350 + dev_priv->pipe_to_crtc_mapping[psb_intel_crtc->pipe] = 1351 + &psb_intel_crtc->base; 1352 + psb_intel_crtc->mode_set.connectors = 1353 + (struct drm_connector **) (psb_intel_crtc + 1); 1354 + psb_intel_crtc->mode_set.num_connectors = 0; 1355 + psb_intel_cursor_init(dev, pipe); 1356 + } 1357 + 1358 + int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, 1359 + struct drm_file *file_priv) 1360 + { 1361 + struct drm_psb_private *dev_priv = dev->dev_private; 1362 + struct drm_psb_get_pipe_from_crtc_id_arg *pipe_from_crtc_id = data; 1363 + struct drm_mode_object *drmmode_obj; 1364 + struct psb_intel_crtc *crtc; 1365 + 1366 + if (!dev_priv) { 1367 + dev_err(dev->dev, "called with no initialization\n"); 1368 + return -EINVAL; 1369 + } 1370 + 1371 + drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id, 1372 + DRM_MODE_OBJECT_CRTC); 1373 + 1374 + if (!drmmode_obj) { 1375 + dev_err(dev->dev, "no such CRTC id\n"); 1376 + return -EINVAL; 1377 + } 1378 + 1379 + crtc = to_psb_intel_crtc(obj_to_crtc(drmmode_obj)); 1380 + pipe_from_crtc_id->pipe = crtc->pipe; 1381 + 1382 + return 0; 1383 + } 1384 + 1385 + struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, int pipe) 1386 + { 1387 + struct drm_crtc *crtc = NULL; 1388 + 1389 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 1390 + struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 1391 + if (psb_intel_crtc->pipe == pipe) 1392 + break; 1393 + } 1394 + return crtc; 1395 + } 1396 + 1397 + int psb_intel_connector_clones(struct drm_device *dev, int type_mask) 1398 + { 1399 + int index_mask = 0; 1400 + struct drm_connector *connector; 1401 + int entry = 0; 1402 + 1403 + list_for_each_entry(connector, &dev->mode_config.connector_list, 1404 + head) { 1405 + struct psb_intel_output *psb_intel_output = 1406 + to_psb_intel_output(connector); 1407 + if (type_mask & (1 << psb_intel_output->type)) 1408 + index_mask |= (1 << entry); 1409 + entry++; 1410 + } 1411 + return index_mask; 1412 + } 1413 + 1414 + 1415 + void psb_intel_modeset_cleanup(struct drm_device *dev) 1416 + { 1417 + drm_mode_config_cleanup(dev); 1418 + } 1419 + 1420 + 1421 + /* current intel driver doesn't take advantage of encoders 1422 + always give back the encoder for the connector 1423 + */ 1424 + struct drm_encoder *psb_intel_best_encoder(struct drm_connector *connector) 1425 + { 1426 + struct psb_intel_output *psb_intel_output = 1427 + to_psb_intel_output(connector); 1428 + 1429 + return &psb_intel_output->enc; 1430 + } 1431 +
+28
drivers/gpu/drm/gma500/psb_intel_display.h
··· 1 + /* copyright (c) 2008, Intel Corporation 2 + * 3 + * This program is free software; you can redistribute it and/or modify it 4 + * under the terms and conditions of the GNU General Public License, 5 + * version 2, as published by the Free Software Foundation. 6 + * 7 + * This program is distributed in the hope it will be useful, but WITHOUT 8 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 9 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 10 + * more details. 11 + * 12 + * You should have received a copy of the GNU General Public License along with 13 + * this program; if not, write to the Free Software Foundation, Inc., 14 + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 15 + * 16 + * Authors: 17 + * Eric Anholt <eric@anholt.net> 18 + */ 19 + 20 + #ifndef _INTEL_DISPLAY_H_ 21 + #define _INTEL_DISPLAY_H_ 22 + 23 + bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type); 24 + void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, 25 + u16 *green, u16 *blue, uint32_t type, uint32_t size); 26 + void psb_intel_crtc_destroy(struct drm_crtc *crtc); 27 + 28 + #endif
+228
drivers/gpu/drm/gma500/psb_intel_drv.h
··· 1 + /* 2 + * Copyright (c) 2009-2011, Intel Corporation. 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms and conditions of the GNU General Public License, 6 + * version 2, as published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope it will be useful, but WITHOUT 9 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 + * more details. 12 + * 13 + * You should have received a copy of the GNU General Public License along with 14 + * this program; if not, write to the Free Software Foundation, Inc., 15 + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 16 + * 17 + */ 18 + 19 + #ifndef __INTEL_DRV_H__ 20 + #define __INTEL_DRV_H__ 21 + 22 + #include <linux/i2c.h> 23 + #include <linux/i2c-algo-bit.h> 24 + #include <drm/drm_crtc.h> 25 + #include <drm/drm_crtc_helper.h> 26 + #include <linux/gpio.h> 27 + 28 + /* 29 + * Display related stuff 30 + */ 31 + 32 + /* store information about an Ixxx DVO */ 33 + /* The i830->i865 use multiple DVOs with multiple i2cs */ 34 + /* the i915, i945 have a single sDVO i2c bus - which is different */ 35 + #define MAX_OUTPUTS 6 36 + /* maximum connectors per crtcs in the mode set */ 37 + #define INTELFB_CONN_LIMIT 4 38 + 39 + #define INTEL_I2C_BUS_DVO 1 40 + #define INTEL_I2C_BUS_SDVO 2 41 + 42 + /* these are outputs from the chip - integrated only 43 + * external chips are via DVO or SDVO output */ 44 + #define INTEL_OUTPUT_UNUSED 0 45 + #define INTEL_OUTPUT_ANALOG 1 46 + #define INTEL_OUTPUT_DVO 2 47 + #define INTEL_OUTPUT_SDVO 3 48 + #define INTEL_OUTPUT_LVDS 4 49 + #define INTEL_OUTPUT_TVOUT 5 50 + #define INTEL_OUTPUT_HDMI 6 51 + #define INTEL_OUTPUT_MIPI 7 52 + #define INTEL_OUTPUT_MIPI2 8 53 + 54 + #define INTEL_DVO_CHIP_NONE 0 55 + #define INTEL_DVO_CHIP_LVDS 1 56 + #define INTEL_DVO_CHIP_TMDS 2 57 + #define INTEL_DVO_CHIP_TVOUT 4 58 + 59 + /* 60 + * Hold information useally put on the device driver privates here, 61 + * since it needs to be shared across multiple of devices drivers privates. 62 + */ 63 + struct psb_intel_mode_device { 64 + 65 + /* 66 + * Abstracted memory manager operations 67 + */ 68 + size_t(*bo_offset) (struct drm_device *dev, void *bo); 69 + 70 + /* 71 + * Cursor (Can go ?) 72 + */ 73 + int cursor_needs_physical; 74 + 75 + /* 76 + * LVDS info 77 + */ 78 + int backlight_duty_cycle; /* restore backlight to this value */ 79 + bool panel_wants_dither; 80 + struct drm_display_mode *panel_fixed_mode; 81 + struct drm_display_mode *panel_fixed_mode2; 82 + struct drm_display_mode *vbt_mode; /* if any */ 83 + 84 + uint32_t saveBLC_PWM_CTL; 85 + }; 86 + 87 + struct psb_intel_i2c_chan { 88 + /* for getting at dev. private (mmio etc.) */ 89 + struct drm_device *drm_dev; 90 + u32 reg; /* GPIO reg */ 91 + struct i2c_adapter adapter; 92 + struct i2c_algo_bit_data algo; 93 + u8 slave_addr; 94 + }; 95 + 96 + struct psb_intel_output { 97 + struct drm_connector base; 98 + 99 + struct drm_encoder enc; 100 + int type; 101 + 102 + struct psb_intel_i2c_chan *i2c_bus; /* for control functions */ 103 + struct psb_intel_i2c_chan *ddc_bus; /* for DDC only stuff */ 104 + bool load_detect_temp; 105 + void *dev_priv; 106 + 107 + struct psb_intel_mode_device *mode_dev; 108 + struct i2c_adapter *hdmi_i2c_adapter; /* for control functions */ 109 + }; 110 + 111 + struct psb_intel_crtc_state { 112 + uint32_t saveDSPCNTR; 113 + uint32_t savePIPECONF; 114 + uint32_t savePIPESRC; 115 + uint32_t saveDPLL; 116 + uint32_t saveFP0; 117 + uint32_t saveFP1; 118 + uint32_t saveHTOTAL; 119 + uint32_t saveHBLANK; 120 + uint32_t saveHSYNC; 121 + uint32_t saveVTOTAL; 122 + uint32_t saveVBLANK; 123 + uint32_t saveVSYNC; 124 + uint32_t saveDSPSTRIDE; 125 + uint32_t saveDSPSIZE; 126 + uint32_t saveDSPPOS; 127 + uint32_t saveDSPBASE; 128 + uint32_t savePalette[256]; 129 + }; 130 + 131 + struct psb_intel_crtc { 132 + struct drm_crtc base; 133 + int pipe; 134 + int plane; 135 + uint32_t cursor_addr; 136 + u8 lut_r[256], lut_g[256], lut_b[256]; 137 + u8 lut_adj[256]; 138 + struct psb_intel_framebuffer *fbdev_fb; 139 + /* a mode_set for fbdev users on this crtc */ 140 + struct drm_mode_set mode_set; 141 + 142 + /* GEM object that holds our cursor */ 143 + struct drm_gem_object *cursor_obj; 144 + 145 + struct drm_display_mode saved_mode; 146 + struct drm_display_mode saved_adjusted_mode; 147 + 148 + struct psb_intel_mode_device *mode_dev; 149 + 150 + /*crtc mode setting flags*/ 151 + u32 mode_flags; 152 + 153 + /* Saved Crtc HW states */ 154 + struct psb_intel_crtc_state *crtc_state; 155 + }; 156 + 157 + #define to_psb_intel_crtc(x) \ 158 + container_of(x, struct psb_intel_crtc, base) 159 + #define to_psb_intel_output(x) \ 160 + container_of(x, struct psb_intel_output, base) 161 + #define enc_to_psb_intel_output(x) \ 162 + container_of(x, struct psb_intel_output, enc) 163 + #define to_psb_intel_framebuffer(x) \ 164 + container_of(x, struct psb_intel_framebuffer, base) 165 + 166 + struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev, 167 + const u32 reg, const char *name); 168 + void psb_intel_i2c_destroy(struct psb_intel_i2c_chan *chan); 169 + int psb_intel_ddc_get_modes(struct psb_intel_output *psb_intel_output); 170 + extern bool psb_intel_ddc_probe(struct psb_intel_output *psb_intel_output); 171 + 172 + extern void psb_intel_crtc_init(struct drm_device *dev, int pipe, 173 + struct psb_intel_mode_device *mode_dev); 174 + extern void psb_intel_crt_init(struct drm_device *dev); 175 + extern void psb_intel_sdvo_init(struct drm_device *dev, int output_device); 176 + extern void psb_intel_dvo_init(struct drm_device *dev); 177 + extern void psb_intel_tv_init(struct drm_device *dev); 178 + extern void psb_intel_lvds_init(struct drm_device *dev, 179 + struct psb_intel_mode_device *mode_dev); 180 + extern void psb_intel_lvds_set_brightness(struct drm_device *dev, int level); 181 + extern void oaktrail_lvds_init(struct drm_device *dev, 182 + struct psb_intel_mode_device *mode_dev); 183 + extern void oaktrail_wait_for_INTR_PKT_SENT(struct drm_device *dev); 184 + extern void oaktrail_dsi_init(struct drm_device *dev, 185 + struct psb_intel_mode_device *mode_dev); 186 + extern void mid_dsi_init(struct drm_device *dev, 187 + struct psb_intel_mode_device *mode_dev, int dsi_num); 188 + 189 + extern void psb_intel_crtc_load_lut(struct drm_crtc *crtc); 190 + extern void psb_intel_encoder_prepare(struct drm_encoder *encoder); 191 + extern void psb_intel_encoder_commit(struct drm_encoder *encoder); 192 + 193 + extern struct drm_encoder *psb_intel_best_encoder(struct drm_connector 194 + *connector); 195 + 196 + extern struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev, 197 + struct drm_crtc *crtc); 198 + extern void psb_intel_wait_for_vblank(struct drm_device *dev); 199 + extern int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, 200 + struct drm_file *file_priv); 201 + extern struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, 202 + int pipe); 203 + extern struct drm_connector *psb_intel_sdvo_find(struct drm_device *dev, 204 + int sdvoB); 205 + extern int psb_intel_sdvo_supports_hotplug(struct drm_connector *connector); 206 + extern void psb_intel_sdvo_set_hotplug(struct drm_connector *connector, 207 + int enable); 208 + extern int intelfb_probe(struct drm_device *dev); 209 + extern int intelfb_remove(struct drm_device *dev, 210 + struct drm_framebuffer *fb); 211 + extern struct drm_framebuffer *psb_intel_framebuffer_create(struct drm_device 212 + *dev, struct 213 + drm_mode_fb_cmd 214 + *mode_cmd, 215 + void *mm_private); 216 + extern bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, 217 + struct drm_display_mode *mode, 218 + struct drm_display_mode *adjusted_mode); 219 + extern int psb_intel_lvds_mode_valid(struct drm_connector *connector, 220 + struct drm_display_mode *mode); 221 + extern int psb_intel_lvds_set_property(struct drm_connector *connector, 222 + struct drm_property *property, 223 + uint64_t value); 224 + extern void psb_intel_lvds_destroy(struct drm_connector *connector); 225 + extern const struct drm_encoder_funcs psb_intel_lvds_enc_funcs; 226 + 227 + 228 + #endif /* __INTEL_DRV_H__ */
+849
drivers/gpu/drm/gma500/psb_intel_lvds.c
··· 1 + /* 2 + * Copyright © 2006-2007 Intel Corporation 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms and conditions of the GNU General Public License, 6 + * version 2, as published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope it will be useful, but WITHOUT 9 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 + * more details. 12 + * 13 + * You should have received a copy of the GNU General Public License along with 14 + * this program; if not, write to the Free Software Foundation, Inc., 15 + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 16 + * 17 + * Authors: 18 + * Eric Anholt <eric@anholt.net> 19 + * Dave Airlie <airlied@linux.ie> 20 + * Jesse Barnes <jesse.barnes@intel.com> 21 + */ 22 + 23 + #include <linux/i2c.h> 24 + #include <drm/drmP.h> 25 + 26 + #include "intel_bios.h" 27 + #include "psb_drv.h" 28 + #include "psb_intel_drv.h" 29 + #include "psb_intel_reg.h" 30 + #include "power.h" 31 + #include <linux/pm_runtime.h> 32 + 33 + /* 34 + * LVDS I2C backlight control macros 35 + */ 36 + #define BRIGHTNESS_MAX_LEVEL 100 37 + #define BRIGHTNESS_MASK 0xFF 38 + #define BLC_I2C_TYPE 0x01 39 + #define BLC_PWM_TYPT 0x02 40 + 41 + #define BLC_POLARITY_NORMAL 0 42 + #define BLC_POLARITY_INVERSE 1 43 + 44 + #define PSB_BLC_MAX_PWM_REG_FREQ (0xFFFE) 45 + #define PSB_BLC_MIN_PWM_REG_FREQ (0x2) 46 + #define PSB_BLC_PWM_PRECISION_FACTOR (10) 47 + #define PSB_BACKLIGHT_PWM_CTL_SHIFT (16) 48 + #define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) 49 + 50 + struct psb_intel_lvds_priv { 51 + /* 52 + * Saved LVDO output states 53 + */ 54 + uint32_t savePP_ON; 55 + uint32_t savePP_OFF; 56 + uint32_t saveLVDS; 57 + uint32_t savePP_CONTROL; 58 + uint32_t savePP_CYCLE; 59 + uint32_t savePFIT_CONTROL; 60 + uint32_t savePFIT_PGM_RATIOS; 61 + uint32_t saveBLC_PWM_CTL; 62 + }; 63 + 64 + 65 + /* 66 + * Returns the maximum level of the backlight duty cycle field. 67 + */ 68 + static u32 psb_intel_lvds_get_max_backlight(struct drm_device *dev) 69 + { 70 + struct drm_psb_private *dev_priv = dev->dev_private; 71 + u32 retVal; 72 + 73 + if (gma_power_begin(dev, false)) { 74 + retVal = ((REG_READ(BLC_PWM_CTL) & 75 + BACKLIGHT_MODULATION_FREQ_MASK) >> 76 + BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; 77 + 78 + gma_power_end(dev); 79 + } else 80 + retVal = ((dev_priv->saveBLC_PWM_CTL & 81 + BACKLIGHT_MODULATION_FREQ_MASK) >> 82 + BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; 83 + 84 + return retVal; 85 + } 86 + 87 + /* 88 + * Set LVDS backlight level by I2C command 89 + * 90 + * FIXME: at some point we need to both track this for PM and also 91 + * disable runtime pm on MRST if the brightness is nil (ie blanked) 92 + */ 93 + static int psb_lvds_i2c_set_brightness(struct drm_device *dev, 94 + unsigned int level) 95 + { 96 + struct drm_psb_private *dev_priv = 97 + (struct drm_psb_private *)dev->dev_private; 98 + 99 + struct psb_intel_i2c_chan *lvds_i2c_bus = dev_priv->lvds_i2c_bus; 100 + u8 out_buf[2]; 101 + unsigned int blc_i2c_brightness; 102 + 103 + struct i2c_msg msgs[] = { 104 + { 105 + .addr = lvds_i2c_bus->slave_addr, 106 + .flags = 0, 107 + .len = 2, 108 + .buf = out_buf, 109 + } 110 + }; 111 + 112 + blc_i2c_brightness = BRIGHTNESS_MASK & ((unsigned int)level * 113 + BRIGHTNESS_MASK / 114 + BRIGHTNESS_MAX_LEVEL); 115 + 116 + if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE) 117 + blc_i2c_brightness = BRIGHTNESS_MASK - blc_i2c_brightness; 118 + 119 + out_buf[0] = dev_priv->lvds_bl->brightnesscmd; 120 + out_buf[1] = (u8)blc_i2c_brightness; 121 + 122 + if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1) { 123 + dev_dbg(dev->dev, "I2C set brightness.(command, value) (%d, %d)\n", 124 + dev_priv->lvds_bl->brightnesscmd, 125 + blc_i2c_brightness); 126 + return 0; 127 + } 128 + 129 + dev_err(dev->dev, "I2C transfer error\n"); 130 + return -1; 131 + } 132 + 133 + 134 + static int psb_lvds_pwm_set_brightness(struct drm_device *dev, int level) 135 + { 136 + struct drm_psb_private *dev_priv = 137 + (struct drm_psb_private *)dev->dev_private; 138 + 139 + u32 max_pwm_blc; 140 + u32 blc_pwm_duty_cycle; 141 + 142 + max_pwm_blc = psb_intel_lvds_get_max_backlight(dev); 143 + 144 + /*BLC_PWM_CTL Should be initiated while backlight device init*/ 145 + BUG_ON((max_pwm_blc & PSB_BLC_MAX_PWM_REG_FREQ) == 0); 146 + 147 + blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL; 148 + 149 + if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE) 150 + blc_pwm_duty_cycle = max_pwm_blc - blc_pwm_duty_cycle; 151 + 152 + blc_pwm_duty_cycle &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR; 153 + REG_WRITE(BLC_PWM_CTL, 154 + (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) | 155 + (blc_pwm_duty_cycle)); 156 + 157 + return 0; 158 + } 159 + 160 + /* 161 + * Set LVDS backlight level either by I2C or PWM 162 + */ 163 + void psb_intel_lvds_set_brightness(struct drm_device *dev, int level) 164 + { 165 + /*u32 blc_pwm_ctl;*/ 166 + struct drm_psb_private *dev_priv = 167 + (struct drm_psb_private *)dev->dev_private; 168 + 169 + dev_dbg(dev->dev, "backlight level is %d\n", level); 170 + 171 + if (!dev_priv->lvds_bl) { 172 + dev_err(dev->dev, "NO LVDS Backlight Info\n"); 173 + return; 174 + } 175 + 176 + if (dev_priv->lvds_bl->type == BLC_I2C_TYPE) 177 + psb_lvds_i2c_set_brightness(dev, level); 178 + else 179 + psb_lvds_pwm_set_brightness(dev, level); 180 + } 181 + 182 + /* 183 + * Sets the backlight level. 184 + * 185 + * level: backlight level, from 0 to psb_intel_lvds_get_max_backlight(). 186 + */ 187 + static void psb_intel_lvds_set_backlight(struct drm_device *dev, int level) 188 + { 189 + struct drm_psb_private *dev_priv = dev->dev_private; 190 + u32 blc_pwm_ctl; 191 + 192 + if (gma_power_begin(dev, false)) { 193 + blc_pwm_ctl = 194 + REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; 195 + REG_WRITE(BLC_PWM_CTL, 196 + (blc_pwm_ctl | 197 + (level << BACKLIGHT_DUTY_CYCLE_SHIFT))); 198 + gma_power_end(dev); 199 + } else { 200 + blc_pwm_ctl = dev_priv->saveBLC_PWM_CTL & 201 + ~BACKLIGHT_DUTY_CYCLE_MASK; 202 + dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl | 203 + (level << BACKLIGHT_DUTY_CYCLE_SHIFT)); 204 + } 205 + } 206 + 207 + /* 208 + * Sets the power state for the panel. 209 + */ 210 + static void psb_intel_lvds_set_power(struct drm_device *dev, 211 + struct psb_intel_output *output, bool on) 212 + { 213 + u32 pp_status; 214 + 215 + if (!gma_power_begin(dev, true)) 216 + return; 217 + 218 + if (on) { 219 + REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | 220 + POWER_TARGET_ON); 221 + do { 222 + pp_status = REG_READ(PP_STATUS); 223 + } while ((pp_status & PP_ON) == 0); 224 + 225 + psb_intel_lvds_set_backlight(dev, 226 + output-> 227 + mode_dev->backlight_duty_cycle); 228 + } else { 229 + psb_intel_lvds_set_backlight(dev, 0); 230 + 231 + REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & 232 + ~POWER_TARGET_ON); 233 + do { 234 + pp_status = REG_READ(PP_STATUS); 235 + } while (pp_status & PP_ON); 236 + } 237 + 238 + gma_power_end(dev); 239 + } 240 + 241 + static void psb_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode) 242 + { 243 + struct drm_device *dev = encoder->dev; 244 + struct psb_intel_output *output = enc_to_psb_intel_output(encoder); 245 + 246 + if (mode == DRM_MODE_DPMS_ON) 247 + psb_intel_lvds_set_power(dev, output, true); 248 + else 249 + psb_intel_lvds_set_power(dev, output, false); 250 + 251 + /* XXX: We never power down the LVDS pairs. */ 252 + } 253 + 254 + static void psb_intel_lvds_save(struct drm_connector *connector) 255 + { 256 + struct drm_device *dev = connector->dev; 257 + struct drm_psb_private *dev_priv = 258 + (struct drm_psb_private *)dev->dev_private; 259 + struct psb_intel_output *psb_intel_output = 260 + to_psb_intel_output(connector); 261 + struct psb_intel_lvds_priv *lvds_priv = 262 + (struct psb_intel_lvds_priv *)psb_intel_output->dev_priv; 263 + 264 + lvds_priv->savePP_ON = REG_READ(LVDSPP_ON); 265 + lvds_priv->savePP_OFF = REG_READ(LVDSPP_OFF); 266 + lvds_priv->saveLVDS = REG_READ(LVDS); 267 + lvds_priv->savePP_CONTROL = REG_READ(PP_CONTROL); 268 + lvds_priv->savePP_CYCLE = REG_READ(PP_CYCLE); 269 + /*lvds_priv->savePP_DIVISOR = REG_READ(PP_DIVISOR);*/ 270 + lvds_priv->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL); 271 + lvds_priv->savePFIT_CONTROL = REG_READ(PFIT_CONTROL); 272 + lvds_priv->savePFIT_PGM_RATIOS = REG_READ(PFIT_PGM_RATIOS); 273 + 274 + /*TODO: move backlight_duty_cycle to psb_intel_lvds_priv*/ 275 + dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL & 276 + BACKLIGHT_DUTY_CYCLE_MASK); 277 + 278 + /* 279 + * If the light is off at server startup, 280 + * just make it full brightness 281 + */ 282 + if (dev_priv->backlight_duty_cycle == 0) 283 + dev_priv->backlight_duty_cycle = 284 + psb_intel_lvds_get_max_backlight(dev); 285 + 286 + dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", 287 + lvds_priv->savePP_ON, 288 + lvds_priv->savePP_OFF, 289 + lvds_priv->saveLVDS, 290 + lvds_priv->savePP_CONTROL, 291 + lvds_priv->savePP_CYCLE, 292 + lvds_priv->saveBLC_PWM_CTL); 293 + } 294 + 295 + static void psb_intel_lvds_restore(struct drm_connector *connector) 296 + { 297 + struct drm_device *dev = connector->dev; 298 + u32 pp_status; 299 + 300 + /*struct drm_psb_private *dev_priv = 301 + (struct drm_psb_private *)dev->dev_private;*/ 302 + struct psb_intel_output *psb_intel_output = 303 + to_psb_intel_output(connector); 304 + struct psb_intel_lvds_priv *lvds_priv = 305 + (struct psb_intel_lvds_priv *)psb_intel_output->dev_priv; 306 + 307 + dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", 308 + lvds_priv->savePP_ON, 309 + lvds_priv->savePP_OFF, 310 + lvds_priv->saveLVDS, 311 + lvds_priv->savePP_CONTROL, 312 + lvds_priv->savePP_CYCLE, 313 + lvds_priv->saveBLC_PWM_CTL); 314 + 315 + REG_WRITE(BLC_PWM_CTL, lvds_priv->saveBLC_PWM_CTL); 316 + REG_WRITE(PFIT_CONTROL, lvds_priv->savePFIT_CONTROL); 317 + REG_WRITE(PFIT_PGM_RATIOS, lvds_priv->savePFIT_PGM_RATIOS); 318 + REG_WRITE(LVDSPP_ON, lvds_priv->savePP_ON); 319 + REG_WRITE(LVDSPP_OFF, lvds_priv->savePP_OFF); 320 + /*REG_WRITE(PP_DIVISOR, lvds_priv->savePP_DIVISOR);*/ 321 + REG_WRITE(PP_CYCLE, lvds_priv->savePP_CYCLE); 322 + REG_WRITE(PP_CONTROL, lvds_priv->savePP_CONTROL); 323 + REG_WRITE(LVDS, lvds_priv->saveLVDS); 324 + 325 + if (lvds_priv->savePP_CONTROL & POWER_TARGET_ON) { 326 + REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | 327 + POWER_TARGET_ON); 328 + do { 329 + pp_status = REG_READ(PP_STATUS); 330 + } while ((pp_status & PP_ON) == 0); 331 + } else { 332 + REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & 333 + ~POWER_TARGET_ON); 334 + do { 335 + pp_status = REG_READ(PP_STATUS); 336 + } while (pp_status & PP_ON); 337 + } 338 + } 339 + 340 + int psb_intel_lvds_mode_valid(struct drm_connector *connector, 341 + struct drm_display_mode *mode) 342 + { 343 + struct psb_intel_output *psb_intel_output = 344 + to_psb_intel_output(connector); 345 + struct drm_display_mode *fixed_mode = 346 + psb_intel_output->mode_dev->panel_fixed_mode; 347 + 348 + if (psb_intel_output->type == INTEL_OUTPUT_MIPI2) 349 + fixed_mode = psb_intel_output->mode_dev->panel_fixed_mode2; 350 + 351 + /* just in case */ 352 + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) 353 + return MODE_NO_DBLESCAN; 354 + 355 + /* just in case */ 356 + if (mode->flags & DRM_MODE_FLAG_INTERLACE) 357 + return MODE_NO_INTERLACE; 358 + 359 + if (fixed_mode) { 360 + if (mode->hdisplay > fixed_mode->hdisplay) 361 + return MODE_PANEL; 362 + if (mode->vdisplay > fixed_mode->vdisplay) 363 + return MODE_PANEL; 364 + } 365 + return MODE_OK; 366 + } 367 + 368 + bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, 369 + struct drm_display_mode *mode, 370 + struct drm_display_mode *adjusted_mode) 371 + { 372 + struct psb_intel_mode_device *mode_dev = 373 + enc_to_psb_intel_output(encoder)->mode_dev; 374 + struct drm_device *dev = encoder->dev; 375 + struct psb_intel_crtc *psb_intel_crtc = 376 + to_psb_intel_crtc(encoder->crtc); 377 + struct drm_encoder *tmp_encoder; 378 + struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode; 379 + struct psb_intel_output *psb_intel_output = 380 + enc_to_psb_intel_output(encoder); 381 + 382 + if (psb_intel_output->type == INTEL_OUTPUT_MIPI2) 383 + panel_fixed_mode = mode_dev->panel_fixed_mode2; 384 + 385 + /* FIXME: review for Medfield */ 386 + /* PSB requires the LVDS is on pipe B, MRST has only one pipe anyway */ 387 + if (!IS_MRST(dev) && psb_intel_crtc->pipe == 0) { 388 + printk(KERN_ERR "Can't support LVDS on pipe A\n"); 389 + return false; 390 + } 391 + if (IS_MRST(dev) && psb_intel_crtc->pipe != 0) { 392 + printk(KERN_ERR "Must use PIPE A\n"); 393 + return false; 394 + } 395 + /* Should never happen!! */ 396 + list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list, 397 + head) { 398 + if (tmp_encoder != encoder 399 + && tmp_encoder->crtc == encoder->crtc) { 400 + printk(KERN_ERR "Can't enable LVDS and another " 401 + "encoder on the same pipe\n"); 402 + return false; 403 + } 404 + } 405 + 406 + /* 407 + * If we have timings from the BIOS for the panel, put them in 408 + * to the adjusted mode. The CRTC will be set up for this mode, 409 + * with the panel scaling set up to source from the H/VDisplay 410 + * of the original mode. 411 + */ 412 + if (panel_fixed_mode != NULL) { 413 + adjusted_mode->hdisplay = panel_fixed_mode->hdisplay; 414 + adjusted_mode->hsync_start = panel_fixed_mode->hsync_start; 415 + adjusted_mode->hsync_end = panel_fixed_mode->hsync_end; 416 + adjusted_mode->htotal = panel_fixed_mode->htotal; 417 + adjusted_mode->vdisplay = panel_fixed_mode->vdisplay; 418 + adjusted_mode->vsync_start = panel_fixed_mode->vsync_start; 419 + adjusted_mode->vsync_end = panel_fixed_mode->vsync_end; 420 + adjusted_mode->vtotal = panel_fixed_mode->vtotal; 421 + adjusted_mode->clock = panel_fixed_mode->clock; 422 + drm_mode_set_crtcinfo(adjusted_mode, 423 + CRTC_INTERLACE_HALVE_V); 424 + } 425 + 426 + /* 427 + * XXX: It would be nice to support lower refresh rates on the 428 + * panels to reduce power consumption, and perhaps match the 429 + * user's requested refresh rate. 430 + */ 431 + 432 + return true; 433 + } 434 + 435 + static void psb_intel_lvds_prepare(struct drm_encoder *encoder) 436 + { 437 + struct drm_device *dev = encoder->dev; 438 + struct psb_intel_output *output = enc_to_psb_intel_output(encoder); 439 + struct psb_intel_mode_device *mode_dev = output->mode_dev; 440 + 441 + if (!gma_power_begin(dev, true)) 442 + return; 443 + 444 + mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL); 445 + mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL & 446 + BACKLIGHT_DUTY_CYCLE_MASK); 447 + 448 + psb_intel_lvds_set_power(dev, output, false); 449 + 450 + gma_power_end(dev); 451 + } 452 + 453 + static void psb_intel_lvds_commit(struct drm_encoder *encoder) 454 + { 455 + struct drm_device *dev = encoder->dev; 456 + struct psb_intel_output *output = enc_to_psb_intel_output(encoder); 457 + struct psb_intel_mode_device *mode_dev = output->mode_dev; 458 + 459 + if (mode_dev->backlight_duty_cycle == 0) 460 + mode_dev->backlight_duty_cycle = 461 + psb_intel_lvds_get_max_backlight(dev); 462 + 463 + psb_intel_lvds_set_power(dev, output, true); 464 + } 465 + 466 + static void psb_intel_lvds_mode_set(struct drm_encoder *encoder, 467 + struct drm_display_mode *mode, 468 + struct drm_display_mode *adjusted_mode) 469 + { 470 + struct drm_device *dev = encoder->dev; 471 + struct drm_psb_private *dev_priv = dev->dev_private; 472 + u32 pfit_control; 473 + 474 + /* 475 + * The LVDS pin pair will already have been turned on in the 476 + * psb_intel_crtc_mode_set since it has a large impact on the DPLL 477 + * settings. 478 + */ 479 + 480 + /* 481 + * Enable automatic panel scaling so that non-native modes fill the 482 + * screen. Should be enabled before the pipe is enabled, according to 483 + * register description and PRM. 484 + */ 485 + if (mode->hdisplay != adjusted_mode->hdisplay || 486 + mode->vdisplay != adjusted_mode->vdisplay) 487 + pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE | 488 + HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR | 489 + HORIZ_INTERP_BILINEAR); 490 + else 491 + pfit_control = 0; 492 + 493 + if (dev_priv->lvds_dither) 494 + pfit_control |= PANEL_8TO6_DITHER_ENABLE; 495 + 496 + REG_WRITE(PFIT_CONTROL, pfit_control); 497 + } 498 + 499 + /* 500 + * Detect the LVDS connection. 501 + * 502 + * This always returns CONNECTOR_STATUS_CONNECTED. 503 + * This connector should only have 504 + * been set up if the LVDS was actually connected anyway. 505 + */ 506 + static enum drm_connector_status psb_intel_lvds_detect(struct drm_connector 507 + *connector, bool force) 508 + { 509 + return connector_status_connected; 510 + } 511 + 512 + /* 513 + * Return the list of DDC modes if available, or the BIOS fixed mode otherwise. 514 + */ 515 + static int psb_intel_lvds_get_modes(struct drm_connector *connector) 516 + { 517 + struct drm_device *dev = connector->dev; 518 + struct psb_intel_output *psb_intel_output = 519 + to_psb_intel_output(connector); 520 + struct psb_intel_mode_device *mode_dev = 521 + psb_intel_output->mode_dev; 522 + int ret = 0; 523 + 524 + if (!IS_MRST(dev)) 525 + ret = psb_intel_ddc_get_modes(psb_intel_output); 526 + 527 + if (ret) 528 + return ret; 529 + 530 + /* Didn't get an EDID, so 531 + * Set wide sync ranges so we get all modes 532 + * handed to valid_mode for checking 533 + */ 534 + connector->display_info.min_vfreq = 0; 535 + connector->display_info.max_vfreq = 200; 536 + connector->display_info.min_hfreq = 0; 537 + connector->display_info.max_hfreq = 200; 538 + 539 + if (mode_dev->panel_fixed_mode != NULL) { 540 + struct drm_display_mode *mode = 541 + drm_mode_duplicate(dev, mode_dev->panel_fixed_mode); 542 + drm_mode_probed_add(connector, mode); 543 + return 1; 544 + } 545 + 546 + return 0; 547 + } 548 + 549 + /** 550 + * psb_intel_lvds_destroy - unregister and free LVDS structures 551 + * @connector: connector to free 552 + * 553 + * Unregister the DDC bus for this connector then free the driver private 554 + * structure. 555 + */ 556 + void psb_intel_lvds_destroy(struct drm_connector *connector) 557 + { 558 + struct psb_intel_output *psb_intel_output = 559 + to_psb_intel_output(connector); 560 + 561 + if (psb_intel_output->ddc_bus) 562 + psb_intel_i2c_destroy(psb_intel_output->ddc_bus); 563 + drm_sysfs_connector_remove(connector); 564 + drm_connector_cleanup(connector); 565 + kfree(connector); 566 + } 567 + 568 + int psb_intel_lvds_set_property(struct drm_connector *connector, 569 + struct drm_property *property, 570 + uint64_t value) 571 + { 572 + struct drm_encoder *encoder = connector->encoder; 573 + 574 + if (!encoder) 575 + return -1; 576 + 577 + if (!strcmp(property->name, "scaling mode")) { 578 + struct psb_intel_crtc *crtc = 579 + to_psb_intel_crtc(encoder->crtc); 580 + uint64_t curval; 581 + 582 + if (!crtc) 583 + goto set_prop_error; 584 + 585 + switch (value) { 586 + case DRM_MODE_SCALE_FULLSCREEN: 587 + break; 588 + case DRM_MODE_SCALE_NO_SCALE: 589 + break; 590 + case DRM_MODE_SCALE_ASPECT: 591 + break; 592 + default: 593 + goto set_prop_error; 594 + } 595 + 596 + if (drm_connector_property_get_value(connector, 597 + property, 598 + &curval)) 599 + goto set_prop_error; 600 + 601 + if (curval == value) 602 + goto set_prop_done; 603 + 604 + if (drm_connector_property_set_value(connector, 605 + property, 606 + value)) 607 + goto set_prop_error; 608 + 609 + if (crtc->saved_mode.hdisplay != 0 && 610 + crtc->saved_mode.vdisplay != 0) { 611 + if (!drm_crtc_helper_set_mode(encoder->crtc, 612 + &crtc->saved_mode, 613 + encoder->crtc->x, 614 + encoder->crtc->y, 615 + encoder->crtc->fb)) 616 + goto set_prop_error; 617 + } 618 + } else if (!strcmp(property->name, "backlight")) { 619 + if (drm_connector_property_set_value(connector, 620 + property, 621 + value)) 622 + goto set_prop_error; 623 + else { 624 + #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE 625 + struct drm_psb_private *devp = encoder->dev->dev_private; 626 + struct backlight_device *bd = devp->backlight_device; 627 + if (bd) { 628 + bd->props.brightness = value; 629 + backlight_update_status(bd); 630 + } 631 + #endif 632 + } 633 + } else if (!strcmp(property->name, "DPMS")) { 634 + struct drm_encoder_helper_funcs *hfuncs 635 + = encoder->helper_private; 636 + hfuncs->dpms(encoder, value); 637 + } 638 + 639 + set_prop_done: 640 + return 0; 641 + set_prop_error: 642 + return -1; 643 + } 644 + 645 + static const struct drm_encoder_helper_funcs psb_intel_lvds_helper_funcs = { 646 + .dpms = psb_intel_lvds_encoder_dpms, 647 + .mode_fixup = psb_intel_lvds_mode_fixup, 648 + .prepare = psb_intel_lvds_prepare, 649 + .mode_set = psb_intel_lvds_mode_set, 650 + .commit = psb_intel_lvds_commit, 651 + }; 652 + 653 + const struct drm_connector_helper_funcs 654 + psb_intel_lvds_connector_helper_funcs = { 655 + .get_modes = psb_intel_lvds_get_modes, 656 + .mode_valid = psb_intel_lvds_mode_valid, 657 + .best_encoder = psb_intel_best_encoder, 658 + }; 659 + 660 + const struct drm_connector_funcs psb_intel_lvds_connector_funcs = { 661 + .dpms = drm_helper_connector_dpms, 662 + .save = psb_intel_lvds_save, 663 + .restore = psb_intel_lvds_restore, 664 + .detect = psb_intel_lvds_detect, 665 + .fill_modes = drm_helper_probe_single_connector_modes, 666 + .set_property = psb_intel_lvds_set_property, 667 + .destroy = psb_intel_lvds_destroy, 668 + }; 669 + 670 + 671 + static void psb_intel_lvds_enc_destroy(struct drm_encoder *encoder) 672 + { 673 + drm_encoder_cleanup(encoder); 674 + } 675 + 676 + const struct drm_encoder_funcs psb_intel_lvds_enc_funcs = { 677 + .destroy = psb_intel_lvds_enc_destroy, 678 + }; 679 + 680 + 681 + 682 + /** 683 + * psb_intel_lvds_init - setup LVDS connectors on this device 684 + * @dev: drm device 685 + * 686 + * Create the connector, register the LVDS DDC bus, and try to figure out what 687 + * modes we can display on the LVDS panel (if present). 688 + */ 689 + void psb_intel_lvds_init(struct drm_device *dev, 690 + struct psb_intel_mode_device *mode_dev) 691 + { 692 + struct psb_intel_output *psb_intel_output; 693 + struct psb_intel_lvds_priv *lvds_priv; 694 + struct drm_connector *connector; 695 + struct drm_encoder *encoder; 696 + struct drm_display_mode *scan; /* *modes, *bios_mode; */ 697 + struct drm_crtc *crtc; 698 + struct drm_psb_private *dev_priv = 699 + (struct drm_psb_private *)dev->dev_private; 700 + u32 lvds; 701 + int pipe; 702 + 703 + psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL); 704 + if (!psb_intel_output) 705 + return; 706 + 707 + lvds_priv = kzalloc(sizeof(struct psb_intel_lvds_priv), GFP_KERNEL); 708 + if (!lvds_priv) { 709 + kfree(psb_intel_output); 710 + dev_err(dev->dev, "LVDS private allocation error\n"); 711 + return; 712 + } 713 + 714 + psb_intel_output->dev_priv = lvds_priv; 715 + 716 + psb_intel_output->mode_dev = mode_dev; 717 + connector = &psb_intel_output->base; 718 + encoder = &psb_intel_output->enc; 719 + drm_connector_init(dev, &psb_intel_output->base, 720 + &psb_intel_lvds_connector_funcs, 721 + DRM_MODE_CONNECTOR_LVDS); 722 + 723 + drm_encoder_init(dev, &psb_intel_output->enc, 724 + &psb_intel_lvds_enc_funcs, 725 + DRM_MODE_ENCODER_LVDS); 726 + 727 + drm_mode_connector_attach_encoder(&psb_intel_output->base, 728 + &psb_intel_output->enc); 729 + psb_intel_output->type = INTEL_OUTPUT_LVDS; 730 + 731 + drm_encoder_helper_add(encoder, &psb_intel_lvds_helper_funcs); 732 + drm_connector_helper_add(connector, 733 + &psb_intel_lvds_connector_helper_funcs); 734 + connector->display_info.subpixel_order = SubPixelHorizontalRGB; 735 + connector->interlace_allowed = false; 736 + connector->doublescan_allowed = false; 737 + 738 + /*Attach connector properties*/ 739 + drm_connector_attach_property(connector, 740 + dev->mode_config.scaling_mode_property, 741 + DRM_MODE_SCALE_FULLSCREEN); 742 + drm_connector_attach_property(connector, 743 + dev_priv->backlight_property, 744 + BRIGHTNESS_MAX_LEVEL); 745 + 746 + /* 747 + * Set up I2C bus 748 + * FIXME: distroy i2c_bus when exit 749 + */ 750 + psb_intel_output->i2c_bus = psb_intel_i2c_create(dev, 751 + GPIOB, 752 + "LVDSBLC_B"); 753 + if (!psb_intel_output->i2c_bus) { 754 + dev_printk(KERN_ERR, 755 + &dev->pdev->dev, "I2C bus registration failed.\n"); 756 + goto failed_blc_i2c; 757 + } 758 + psb_intel_output->i2c_bus->slave_addr = 0x2C; 759 + dev_priv->lvds_i2c_bus = psb_intel_output->i2c_bus; 760 + 761 + /* 762 + * LVDS discovery: 763 + * 1) check for EDID on DDC 764 + * 2) check for VBT data 765 + * 3) check to see if LVDS is already on 766 + * if none of the above, no panel 767 + * 4) make sure lid is open 768 + * if closed, act like it's not there for now 769 + */ 770 + 771 + /* Set up the DDC bus. */ 772 + psb_intel_output->ddc_bus = psb_intel_i2c_create(dev, 773 + GPIOC, 774 + "LVDSDDC_C"); 775 + if (!psb_intel_output->ddc_bus) { 776 + dev_printk(KERN_ERR, &dev->pdev->dev, 777 + "DDC bus registration " "failed.\n"); 778 + goto failed_ddc; 779 + } 780 + 781 + /* 782 + * Attempt to get the fixed panel mode from DDC. Assume that the 783 + * preferred mode is the right one. 784 + */ 785 + psb_intel_ddc_get_modes(psb_intel_output); 786 + list_for_each_entry(scan, &connector->probed_modes, head) { 787 + if (scan->type & DRM_MODE_TYPE_PREFERRED) { 788 + mode_dev->panel_fixed_mode = 789 + drm_mode_duplicate(dev, scan); 790 + goto out; /* FIXME: check for quirks */ 791 + } 792 + } 793 + 794 + /* Failed to get EDID, what about VBT? do we need this? */ 795 + if (mode_dev->vbt_mode) 796 + mode_dev->panel_fixed_mode = 797 + drm_mode_duplicate(dev, mode_dev->vbt_mode); 798 + 799 + if (!mode_dev->panel_fixed_mode) 800 + if (dev_priv->lfp_lvds_vbt_mode) 801 + mode_dev->panel_fixed_mode = 802 + drm_mode_duplicate(dev, 803 + dev_priv->lfp_lvds_vbt_mode); 804 + 805 + /* 806 + * If we didn't get EDID, try checking if the panel is already turned 807 + * on. If so, assume that whatever is currently programmed is the 808 + * correct mode. 809 + */ 810 + lvds = REG_READ(LVDS); 811 + pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; 812 + crtc = psb_intel_get_crtc_from_pipe(dev, pipe); 813 + 814 + if (crtc && (lvds & LVDS_PORT_EN)) { 815 + mode_dev->panel_fixed_mode = 816 + psb_intel_crtc_mode_get(dev, crtc); 817 + if (mode_dev->panel_fixed_mode) { 818 + mode_dev->panel_fixed_mode->type |= 819 + DRM_MODE_TYPE_PREFERRED; 820 + goto out; /* FIXME: check for quirks */ 821 + } 822 + } 823 + 824 + /* If we still don't have a mode after all that, give up. */ 825 + if (!mode_dev->panel_fixed_mode) { 826 + dev_err(dev->dev, "Found no modes on the lvds, ignoring the LVDS\n"); 827 + goto failed_find; 828 + } 829 + 830 + /* 831 + * Blacklist machines with BIOSes that list an LVDS panel without 832 + * actually having one. 833 + */ 834 + out: 835 + drm_sysfs_connector_add(connector); 836 + return; 837 + 838 + failed_find: 839 + if (psb_intel_output->ddc_bus) 840 + psb_intel_i2c_destroy(psb_intel_output->ddc_bus); 841 + failed_ddc: 842 + if (psb_intel_output->i2c_bus) 843 + psb_intel_i2c_destroy(psb_intel_output->i2c_bus); 844 + failed_blc_i2c: 845 + drm_encoder_cleanup(encoder); 846 + drm_connector_cleanup(connector); 847 + kfree(connector); 848 + } 849 +
+77
drivers/gpu/drm/gma500/psb_intel_modes.c
··· 1 + /* 2 + * Copyright (c) 2007 Intel Corporation 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms and conditions of the GNU General Public License, 6 + * version 2, as published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope it will be useful, but WITHOUT 9 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 + * more details. 12 + * 13 + * You should have received a copy of the GNU General Public License along with 14 + * this program; if not, write to the Free Software Foundation, Inc., 15 + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 16 + * 17 + * Authers: Jesse Barnes <jesse.barnes@intel.com> 18 + */ 19 + 20 + #include <linux/i2c.h> 21 + #include <linux/fb.h> 22 + #include <drm/drmP.h> 23 + #include "psb_intel_drv.h" 24 + 25 + /** 26 + * psb_intel_ddc_probe 27 + * 28 + */ 29 + bool psb_intel_ddc_probe(struct psb_intel_output *psb_intel_output) 30 + { 31 + u8 out_buf[] = { 0x0, 0x0 }; 32 + u8 buf[2]; 33 + int ret; 34 + struct i2c_msg msgs[] = { 35 + { 36 + .addr = 0x50, 37 + .flags = 0, 38 + .len = 1, 39 + .buf = out_buf, 40 + }, 41 + { 42 + .addr = 0x50, 43 + .flags = I2C_M_RD, 44 + .len = 1, 45 + .buf = buf, 46 + } 47 + }; 48 + 49 + ret = i2c_transfer(&psb_intel_output->ddc_bus->adapter, msgs, 2); 50 + if (ret == 2) 51 + return true; 52 + 53 + return false; 54 + } 55 + 56 + /** 57 + * psb_intel_ddc_get_modes - get modelist from monitor 58 + * @connector: DRM connector device to use 59 + * 60 + * Fetch the EDID information from @connector using the DDC bus. 61 + */ 62 + int psb_intel_ddc_get_modes(struct psb_intel_output *psb_intel_output) 63 + { 64 + struct edid *edid; 65 + int ret = 0; 66 + 67 + edid = 68 + drm_get_edid(&psb_intel_output->base, 69 + &psb_intel_output->ddc_bus->adapter); 70 + if (edid) { 71 + drm_mode_connector_update_edid_property(&psb_intel_output-> 72 + base, edid); 73 + ret = drm_add_edid_modes(&psb_intel_output->base, edid); 74 + kfree(edid); 75 + } 76 + return ret; 77 + }
+1235
drivers/gpu/drm/gma500/psb_intel_reg.h
··· 1 + /* 2 + * Copyright (c) 2009, Intel Corporation. 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms and conditions of the GNU General Public License, 6 + * version 2, as published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope it will be useful, but WITHOUT 9 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 + * more details. 12 + * 13 + * You should have received a copy of the GNU General Public License along with 14 + * this program; if not, write to the Free Software Foundation, Inc., 15 + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 16 + */ 17 + #ifndef __PSB_INTEL_REG_H__ 18 + #define __PSB_INTEL_REG_H__ 19 + 20 + #define BLC_PWM_CTL 0x61254 21 + #define BLC_PWM_CTL2 0x61250 22 + #define BLC_PWM_CTL_C 0x62254 23 + #define BLC_PWM_CTL2_C 0x62250 24 + #define BACKLIGHT_MODULATION_FREQ_SHIFT (17) 25 + /* 26 + * This is the most significant 15 bits of the number of backlight cycles in a 27 + * complete cycle of the modulated backlight control. 28 + * 29 + * The actual value is this field multiplied by two. 30 + */ 31 + #define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17) 32 + #define BLM_LEGACY_MODE (1 << 16) 33 + /* 34 + * This is the number of cycles out of the backlight modulation cycle for which 35 + * the backlight is on. 36 + * 37 + * This field must be no greater than the number of cycles in the complete 38 + * backlight modulation cycle. 39 + */ 40 + #define BACKLIGHT_DUTY_CYCLE_SHIFT (0) 41 + #define BACKLIGHT_DUTY_CYCLE_MASK (0xffff) 42 + 43 + #define I915_GCFGC 0xf0 44 + #define I915_LOW_FREQUENCY_ENABLE (1 << 7) 45 + #define I915_DISPLAY_CLOCK_190_200_MHZ (0 << 4) 46 + #define I915_DISPLAY_CLOCK_333_MHZ (4 << 4) 47 + #define I915_DISPLAY_CLOCK_MASK (7 << 4) 48 + 49 + #define I855_HPLLCC 0xc0 50 + #define I855_CLOCK_CONTROL_MASK (3 << 0) 51 + #define I855_CLOCK_133_200 (0 << 0) 52 + #define I855_CLOCK_100_200 (1 << 0) 53 + #define I855_CLOCK_100_133 (2 << 0) 54 + #define I855_CLOCK_166_250 (3 << 0) 55 + 56 + /* I830 CRTC registers */ 57 + #define HTOTAL_A 0x60000 58 + #define HBLANK_A 0x60004 59 + #define HSYNC_A 0x60008 60 + #define VTOTAL_A 0x6000c 61 + #define VBLANK_A 0x60010 62 + #define VSYNC_A 0x60014 63 + #define PIPEASRC 0x6001c 64 + #define BCLRPAT_A 0x60020 65 + #define VSYNCSHIFT_A 0x60028 66 + 67 + #define HTOTAL_B 0x61000 68 + #define HBLANK_B 0x61004 69 + #define HSYNC_B 0x61008 70 + #define VTOTAL_B 0x6100c 71 + #define VBLANK_B 0x61010 72 + #define VSYNC_B 0x61014 73 + #define PIPEBSRC 0x6101c 74 + #define BCLRPAT_B 0x61020 75 + #define VSYNCSHIFT_B 0x61028 76 + 77 + #define HTOTAL_C 0x62000 78 + #define HBLANK_C 0x62004 79 + #define HSYNC_C 0x62008 80 + #define VTOTAL_C 0x6200c 81 + #define VBLANK_C 0x62010 82 + #define VSYNC_C 0x62014 83 + #define PIPECSRC 0x6201c 84 + #define BCLRPAT_C 0x62020 85 + #define VSYNCSHIFT_C 0x62028 86 + 87 + #define PP_STATUS 0x61200 88 + # define PP_ON (1 << 31) 89 + /* 90 + * Indicates that all dependencies of the panel are on: 91 + * 92 + * - PLL enabled 93 + * - pipe enabled 94 + * - LVDS/DVOB/DVOC on 95 + */ 96 + #define PP_READY (1 << 30) 97 + #define PP_SEQUENCE_NONE (0 << 28) 98 + #define PP_SEQUENCE_ON (1 << 28) 99 + #define PP_SEQUENCE_OFF (2 << 28) 100 + #define PP_SEQUENCE_MASK 0x30000000 101 + #define PP_CONTROL 0x61204 102 + #define POWER_TARGET_ON (1 << 0) 103 + 104 + #define LVDSPP_ON 0x61208 105 + #define LVDSPP_OFF 0x6120c 106 + #define PP_CYCLE 0x61210 107 + 108 + #define PFIT_CONTROL 0x61230 109 + #define PFIT_ENABLE (1 << 31) 110 + #define PFIT_PIPE_MASK (3 << 29) 111 + #define PFIT_PIPE_SHIFT 29 112 + #define PFIT_SCALING_MODE_PILLARBOX (1 << 27) 113 + #define PFIT_SCALING_MODE_LETTERBOX (3 << 26) 114 + #define VERT_INTERP_DISABLE (0 << 10) 115 + #define VERT_INTERP_BILINEAR (1 << 10) 116 + #define VERT_INTERP_MASK (3 << 10) 117 + #define VERT_AUTO_SCALE (1 << 9) 118 + #define HORIZ_INTERP_DISABLE (0 << 6) 119 + #define HORIZ_INTERP_BILINEAR (1 << 6) 120 + #define HORIZ_INTERP_MASK (3 << 6) 121 + #define HORIZ_AUTO_SCALE (1 << 5) 122 + #define PANEL_8TO6_DITHER_ENABLE (1 << 3) 123 + 124 + #define PFIT_PGM_RATIOS 0x61234 125 + #define PFIT_VERT_SCALE_MASK 0xfff00000 126 + #define PFIT_HORIZ_SCALE_MASK 0x0000fff0 127 + 128 + #define PFIT_AUTO_RATIOS 0x61238 129 + 130 + #define DPLL_A 0x06014 131 + #define DPLL_B 0x06018 132 + #define DPLL_VCO_ENABLE (1 << 31) 133 + #define DPLL_DVO_HIGH_SPEED (1 << 30) 134 + #define DPLL_SYNCLOCK_ENABLE (1 << 29) 135 + #define DPLL_VGA_MODE_DIS (1 << 28) 136 + #define DPLLB_MODE_DAC_SERIAL (1 << 26) /* i915 */ 137 + #define DPLLB_MODE_LVDS (2 << 26) /* i915 */ 138 + #define DPLL_MODE_MASK (3 << 26) 139 + #define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */ 140 + #define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */ 141 + #define DPLLB_LVDS_P2_CLOCK_DIV_14 (0 << 24) /* i915 */ 142 + #define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */ 143 + #define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */ 144 + #define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ 145 + #define DPLL_LOCK (1 << 15) /* CDV */ 146 + 147 + /* 148 + * The i830 generation, in DAC/serial mode, defines p1 as two plus this 149 + * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set. 150 + */ 151 + # define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000 152 + /* 153 + * The i830 generation, in LVDS mode, defines P1 as the bit number set within 154 + * this field (only one bit may be set). 155 + */ 156 + #define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000 157 + #define DPLL_FPA01_P1_POST_DIV_SHIFT 16 158 + #define PLL_P2_DIVIDE_BY_4 (1 << 23) /* i830, required 159 + * in DVO non-gang */ 160 + # define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */ 161 + #define PLL_REF_INPUT_DREFCLK (0 << 13) 162 + #define PLL_REF_INPUT_TVCLKINA (1 << 13) /* i830 */ 163 + #define PLL_REF_INPUT_TVCLKINBC (2 << 13) /* SDVO 164 + * TVCLKIN */ 165 + #define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13) 166 + #define PLL_REF_INPUT_MASK (3 << 13) 167 + #define PLL_LOAD_PULSE_PHASE_SHIFT 9 168 + /* 169 + * Parallel to Serial Load Pulse phase selection. 170 + * Selects the phase for the 10X DPLL clock for the PCIe 171 + * digital display port. The range is 4 to 13; 10 or more 172 + * is just a flip delay. The default is 6 173 + */ 174 + #define PLL_LOAD_PULSE_PHASE_MASK (0xf << PLL_LOAD_PULSE_PHASE_SHIFT) 175 + #define DISPLAY_RATE_SELECT_FPA1 (1 << 8) 176 + 177 + /* 178 + * SDVO multiplier for 945G/GM. Not used on 965. 179 + * 180 + * DPLL_MD_UDI_MULTIPLIER_MASK 181 + */ 182 + #define SDVO_MULTIPLIER_MASK 0x000000ff 183 + #define SDVO_MULTIPLIER_SHIFT_HIRES 4 184 + #define SDVO_MULTIPLIER_SHIFT_VGA 0 185 + 186 + /* 187 + * PLL_MD 188 + */ 189 + /* Pipe A SDVO/UDI clock multiplier/divider register for G965. */ 190 + #define DPLL_A_MD 0x0601c 191 + /* Pipe B SDVO/UDI clock multiplier/divider register for G965. */ 192 + #define DPLL_B_MD 0x06020 193 + /* 194 + * UDI pixel divider, controlling how many pixels are stuffed into a packet. 195 + * 196 + * Value is pixels minus 1. Must be set to 1 pixel for SDVO. 197 + */ 198 + #define DPLL_MD_UDI_DIVIDER_MASK 0x3f000000 199 + #define DPLL_MD_UDI_DIVIDER_SHIFT 24 200 + /* UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */ 201 + #define DPLL_MD_VGA_UDI_DIVIDER_MASK 0x003f0000 202 + #define DPLL_MD_VGA_UDI_DIVIDER_SHIFT 16 203 + /* 204 + * SDVO/UDI pixel multiplier. 205 + * 206 + * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus 207 + * clock rate is 10 times the DPLL clock. At low resolution/refresh rate 208 + * modes, the bus rate would be below the limits, so SDVO allows for stuffing 209 + * dummy bytes in the datastream at an increased clock rate, with both sides of 210 + * the link knowing how many bytes are fill. 211 + * 212 + * So, for a mode with a dotclock of 65Mhz, we would want to double the clock 213 + * rate to 130Mhz to get a bus rate of 1.30Ghz. The DPLL clock rate would be 214 + * set to 130Mhz, and the SDVO multiplier set to 2x in this register and 215 + * through an SDVO command. 216 + * 217 + * This register field has values of multiplication factor minus 1, with 218 + * a maximum multiplier of 5 for SDVO. 219 + */ 220 + #define DPLL_MD_UDI_MULTIPLIER_MASK 0x00003f00 221 + #define DPLL_MD_UDI_MULTIPLIER_SHIFT 8 222 + /* 223 + * SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK. 224 + * This best be set to the default value (3) or the CRT won't work. No, 225 + * I don't entirely understand what this does... 226 + */ 227 + #define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f 228 + #define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0 229 + 230 + #define DPLL_TEST 0x606c 231 + #define DPLLB_TEST_SDVO_DIV_1 (0 << 22) 232 + #define DPLLB_TEST_SDVO_DIV_2 (1 << 22) 233 + #define DPLLB_TEST_SDVO_DIV_4 (2 << 22) 234 + #define DPLLB_TEST_SDVO_DIV_MASK (3 << 22) 235 + #define DPLLB_TEST_N_BYPASS (1 << 19) 236 + #define DPLLB_TEST_M_BYPASS (1 << 18) 237 + #define DPLLB_INPUT_BUFFER_ENABLE (1 << 16) 238 + #define DPLLA_TEST_N_BYPASS (1 << 3) 239 + #define DPLLA_TEST_M_BYPASS (1 << 2) 240 + #define DPLLA_INPUT_BUFFER_ENABLE (1 << 0) 241 + 242 + #define ADPA 0x61100 243 + #define ADPA_DAC_ENABLE (1 << 31) 244 + #define ADPA_DAC_DISABLE 0 245 + #define ADPA_PIPE_SELECT_MASK (1 << 30) 246 + #define ADPA_PIPE_A_SELECT 0 247 + #define ADPA_PIPE_B_SELECT (1 << 30) 248 + #define ADPA_USE_VGA_HVPOLARITY (1 << 15) 249 + #define ADPA_SETS_HVPOLARITY 0 250 + #define ADPA_VSYNC_CNTL_DISABLE (1 << 11) 251 + #define ADPA_VSYNC_CNTL_ENABLE 0 252 + #define ADPA_HSYNC_CNTL_DISABLE (1 << 10) 253 + #define ADPA_HSYNC_CNTL_ENABLE 0 254 + #define ADPA_VSYNC_ACTIVE_HIGH (1 << 4) 255 + #define ADPA_VSYNC_ACTIVE_LOW 0 256 + #define ADPA_HSYNC_ACTIVE_HIGH (1 << 3) 257 + #define ADPA_HSYNC_ACTIVE_LOW 0 258 + 259 + #define FPA0 0x06040 260 + #define FPA1 0x06044 261 + #define FPB0 0x06048 262 + #define FPB1 0x0604c 263 + #define FP_N_DIV_MASK 0x003f0000 264 + #define FP_N_DIV_SHIFT 16 265 + #define FP_M1_DIV_MASK 0x00003f00 266 + #define FP_M1_DIV_SHIFT 8 267 + #define FP_M2_DIV_MASK 0x0000003f 268 + #define FP_M2_DIV_SHIFT 0 269 + 270 + #define PORT_HOTPLUG_EN 0x61110 271 + #define SDVOB_HOTPLUG_INT_EN (1 << 26) 272 + #define SDVOC_HOTPLUG_INT_EN (1 << 25) 273 + #define TV_HOTPLUG_INT_EN (1 << 18) 274 + #define CRT_HOTPLUG_INT_EN (1 << 9) 275 + #define CRT_HOTPLUG_FORCE_DETECT (1 << 3) 276 + /* CDV.. */ 277 + #define CRT_HOTPLUG_ACTIVATION_PERIOD_64 (1 << 8) 278 + #define CRT_HOTPLUG_DAC_ON_TIME_2M (0 << 7) 279 + #define CRT_HOTPLUG_DAC_ON_TIME_4M (1 << 7) 280 + #define CRT_HOTPLUG_VOLTAGE_COMPARE_40 (0 << 5) 281 + #define CRT_HOTPLUG_VOLTAGE_COMPARE_50 (1 << 5) 282 + #define CRT_HOTPLUG_VOLTAGE_COMPARE_60 (2 << 5) 283 + #define CRT_HOTPLUG_VOLTAGE_COMPARE_70 (3 << 5) 284 + #define CRT_HOTPLUG_VOLTAGE_COMPARE_MASK (3 << 5) 285 + #define CRT_HOTPLUG_DETECT_DELAY_1G (0 << 4) 286 + #define CRT_HOTPLUG_DETECT_DELAY_2G (1 << 4) 287 + #define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2) 288 + #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) 289 + #define CRT_HOTPLUG_DETECT_MASK 0x000000F8 290 + 291 + #define PORT_HOTPLUG_STAT 0x61114 292 + #define CRT_HOTPLUG_INT_STATUS (1 << 11) 293 + #define TV_HOTPLUG_INT_STATUS (1 << 10) 294 + #define CRT_HOTPLUG_MONITOR_MASK (3 << 8) 295 + #define CRT_HOTPLUG_MONITOR_COLOR (3 << 8) 296 + #define CRT_HOTPLUG_MONITOR_MONO (2 << 8) 297 + #define CRT_HOTPLUG_MONITOR_NONE (0 << 8) 298 + #define SDVOC_HOTPLUG_INT_STATUS (1 << 7) 299 + #define SDVOB_HOTPLUG_INT_STATUS (1 << 6) 300 + 301 + #define SDVOB 0x61140 302 + #define SDVOC 0x61160 303 + #define SDVO_ENABLE (1 << 31) 304 + #define SDVO_PIPE_B_SELECT (1 << 30) 305 + #define SDVO_STALL_SELECT (1 << 29) 306 + #define SDVO_INTERRUPT_ENABLE (1 << 26) 307 + 308 + /** 309 + * 915G/GM SDVO pixel multiplier. 310 + * 311 + * Programmed value is multiplier - 1, up to 5x. 312 + * 313 + * DPLL_MD_UDI_MULTIPLIER_MASK 314 + */ 315 + #define SDVO_PORT_MULTIPLY_MASK (7 << 23) 316 + #define SDVO_PORT_MULTIPLY_SHIFT 23 317 + #define SDVO_PHASE_SELECT_MASK (15 << 19) 318 + #define SDVO_PHASE_SELECT_DEFAULT (6 << 19) 319 + #define SDVO_CLOCK_OUTPUT_INVERT (1 << 18) 320 + #define SDVOC_GANG_MODE (1 << 16) 321 + #define SDVO_BORDER_ENABLE (1 << 7) 322 + #define SDVOB_PCIE_CONCURRENCY (1 << 3) 323 + #define SDVO_DETECTED (1 << 2) 324 + /* Bits to be preserved when writing */ 325 + #define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14)) 326 + #define SDVOC_PRESERVE_MASK (1 << 17) 327 + 328 + /* 329 + * This register controls the LVDS output enable, pipe selection, and data 330 + * format selection. 331 + * 332 + * All of the clock/data pairs are force powered down by power sequencing. 333 + */ 334 + #define LVDS 0x61180 335 + /* 336 + * Enables the LVDS port. This bit must be set before DPLLs are enabled, as 337 + * the DPLL semantics change when the LVDS is assigned to that pipe. 338 + */ 339 + #define LVDS_PORT_EN (1 << 31) 340 + /* Selects pipe B for LVDS data. Must be set on pre-965. */ 341 + #define LVDS_PIPEB_SELECT (1 << 30) 342 + 343 + /* Turns on border drawing to allow centered display. */ 344 + #define LVDS_BORDER_EN (1 << 15) 345 + 346 + /* 347 + * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per 348 + * pixel. 349 + */ 350 + #define LVDS_A0A2_CLKA_POWER_MASK (3 << 8) 351 + #define LVDS_A0A2_CLKA_POWER_DOWN (0 << 8) 352 + #define LVDS_A0A2_CLKA_POWER_UP (3 << 8) 353 + /* 354 + * Controls the A3 data pair, which contains the additional LSBs for 24 bit 355 + * mode. Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be 356 + * on. 357 + */ 358 + #define LVDS_A3_POWER_MASK (3 << 6) 359 + #define LVDS_A3_POWER_DOWN (0 << 6) 360 + #define LVDS_A3_POWER_UP (3 << 6) 361 + /* 362 + * Controls the CLKB pair. This should only be set when LVDS_B0B3_POWER_UP 363 + * is set. 364 + */ 365 + #define LVDS_CLKB_POWER_MASK (3 << 4) 366 + #define LVDS_CLKB_POWER_DOWN (0 << 4) 367 + #define LVDS_CLKB_POWER_UP (3 << 4) 368 + /* 369 + * Controls the B0-B3 data pairs. This must be set to match the DPLL p2 370 + * setting for whether we are in dual-channel mode. The B3 pair will 371 + * additionally only be powered up when LVDS_A3_POWER_UP is set. 372 + */ 373 + #define LVDS_B0B3_POWER_MASK (3 << 2) 374 + #define LVDS_B0B3_POWER_DOWN (0 << 2) 375 + #define LVDS_B0B3_POWER_UP (3 << 2) 376 + 377 + #define PIPEACONF 0x70008 378 + #define PIPEACONF_ENABLE (1 << 31) 379 + #define PIPEACONF_DISABLE 0 380 + #define PIPEACONF_DOUBLE_WIDE (1 << 30) 381 + #define PIPECONF_ACTIVE (1 << 30) 382 + #define I965_PIPECONF_ACTIVE (1 << 30) 383 + #define PIPECONF_DSIPLL_LOCK (1 << 29) 384 + #define PIPEACONF_SINGLE_WIDE 0 385 + #define PIPEACONF_PIPE_UNLOCKED 0 386 + #define PIPEACONF_DSR (1 << 26) 387 + #define PIPEACONF_PIPE_LOCKED (1 << 25) 388 + #define PIPEACONF_PALETTE 0 389 + #define PIPECONF_FORCE_BORDER (1 << 25) 390 + #define PIPEACONF_GAMMA (1 << 24) 391 + #define PIPECONF_PROGRESSIVE (0 << 21) 392 + #define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21) 393 + #define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21) 394 + #define PIPECONF_PLANE_OFF (1 << 19) 395 + #define PIPECONF_CURSOR_OFF (1 << 18) 396 + 397 + #define PIPEBCONF 0x71008 398 + #define PIPEBCONF_ENABLE (1 << 31) 399 + #define PIPEBCONF_DISABLE 0 400 + #define PIPEBCONF_DOUBLE_WIDE (1 << 30) 401 + #define PIPEBCONF_DISABLE 0 402 + #define PIPEBCONF_GAMMA (1 << 24) 403 + #define PIPEBCONF_PALETTE 0 404 + 405 + #define PIPECCONF 0x72008 406 + 407 + #define PIPEBGCMAXRED 0x71010 408 + #define PIPEBGCMAXGREEN 0x71014 409 + #define PIPEBGCMAXBLUE 0x71018 410 + 411 + #define PIPEASTAT 0x70024 412 + #define PIPEBSTAT 0x71024 413 + #define PIPECSTAT 0x72024 414 + #define PIPE_VBLANK_INTERRUPT_STATUS (1UL << 1) 415 + #define PIPE_START_VBLANK_INTERRUPT_STATUS (1UL << 2) 416 + #define PIPE_VBLANK_CLEAR (1 << 1) 417 + #define PIPE_VBLANK_STATUS (1 << 1) 418 + #define PIPE_TE_STATUS (1UL << 6) 419 + #define PIPE_DPST_EVENT_STATUS (1UL << 7) 420 + #define PIPE_VSYNC_CLEAR (1UL << 9) 421 + #define PIPE_VSYNC_STATUS (1UL << 9) 422 + #define PIPE_HDMI_AUDIO_UNDERRUN_STATUS (1UL << 10) 423 + #define PIPE_HDMI_AUDIO_BUFFER_DONE_STATUS (1UL << 11) 424 + #define PIPE_VBLANK_INTERRUPT_ENABLE (1UL << 17) 425 + #define PIPE_START_VBLANK_INTERRUPT_ENABLE (1UL << 18) 426 + #define PIPE_TE_ENABLE (1UL << 22) 427 + #define PIPE_DPST_EVENT_ENABLE (1UL << 23) 428 + #define PIPE_VSYNC_ENABL (1UL << 25) 429 + #define PIPE_HDMI_AUDIO_UNDERRUN (1UL << 26) 430 + #define PIPE_HDMI_AUDIO_BUFFER_DONE (1UL << 27) 431 + #define PIPE_HDMI_AUDIO_INT_MASK (PIPE_HDMI_AUDIO_UNDERRUN | \ 432 + PIPE_HDMI_AUDIO_BUFFER_DONE) 433 + #define PIPE_EVENT_MASK ((1 << 29)|(1 << 28)|(1 << 27)|(1 << 26)|(1 << 24)|(1 << 23)|(1 << 22)|(1 << 21)|(1 << 20)|(1 << 16)) 434 + #define PIPE_VBLANK_MASK ((1 << 25)|(1 << 24)|(1 << 18)|(1 << 17)) 435 + #define HISTOGRAM_INT_CONTROL 0x61268 436 + #define HISTOGRAM_BIN_DATA 0X61264 437 + #define HISTOGRAM_LOGIC_CONTROL 0x61260 438 + #define PWM_CONTROL_LOGIC 0x61250 439 + #define PIPE_HOTPLUG_INTERRUPT_STATUS (1UL << 10) 440 + #define HISTOGRAM_INTERRUPT_ENABLE (1UL << 31) 441 + #define HISTOGRAM_LOGIC_ENABLE (1UL << 31) 442 + #define PWM_LOGIC_ENABLE (1UL << 31) 443 + #define PWM_PHASEIN_ENABLE (1UL << 25) 444 + #define PWM_PHASEIN_INT_ENABLE (1UL << 24) 445 + #define PWM_PHASEIN_VB_COUNT 0x00001f00 446 + #define PWM_PHASEIN_INC 0x0000001f 447 + #define HISTOGRAM_INT_CTRL_CLEAR (1UL << 30) 448 + #define DPST_YUV_LUMA_MODE 0 449 + 450 + struct dpst_ie_histogram_control { 451 + union { 452 + uint32_t data; 453 + struct { 454 + uint32_t bin_reg_index:7; 455 + uint32_t reserved:4; 456 + uint32_t bin_reg_func_select:1; 457 + uint32_t sync_to_phase_in:1; 458 + uint32_t alt_enhancement_mode:2; 459 + uint32_t reserved1:1; 460 + uint32_t sync_to_phase_in_count:8; 461 + uint32_t histogram_mode_select:1; 462 + uint32_t reserved2:4; 463 + uint32_t ie_pipe_assignment:1; 464 + uint32_t ie_mode_table_enabled:1; 465 + uint32_t ie_histogram_enable:1; 466 + }; 467 + }; 468 + }; 469 + 470 + struct dpst_guardband { 471 + union { 472 + uint32_t data; 473 + struct { 474 + uint32_t guardband:22; 475 + uint32_t guardband_interrupt_delay:8; 476 + uint32_t interrupt_status:1; 477 + uint32_t interrupt_enable:1; 478 + }; 479 + }; 480 + }; 481 + 482 + #define PIPEAFRAMEHIGH 0x70040 483 + #define PIPEAFRAMEPIXEL 0x70044 484 + #define PIPEBFRAMEHIGH 0x71040 485 + #define PIPEBFRAMEPIXEL 0x71044 486 + #define PIPECFRAMEHIGH 0x72040 487 + #define PIPECFRAMEPIXEL 0x72044 488 + #define PIPE_FRAME_HIGH_MASK 0x0000ffff 489 + #define PIPE_FRAME_HIGH_SHIFT 0 490 + #define PIPE_FRAME_LOW_MASK 0xff000000 491 + #define PIPE_FRAME_LOW_SHIFT 24 492 + #define PIPE_PIXEL_MASK 0x00ffffff 493 + #define PIPE_PIXEL_SHIFT 0 494 + 495 + #define DSPARB 0x70030 496 + #define DSPFW1 0x70034 497 + #define DSPFW2 0x70038 498 + #define DSPFW3 0x7003c 499 + #define DSPFW4 0x70050 500 + #define DSPFW5 0x70054 501 + #define DSPFW6 0x70058 502 + #define DSPCHICKENBIT 0x70400 503 + #define DSPACNTR 0x70180 504 + #define DSPBCNTR 0x71180 505 + #define DSPCCNTR 0x72180 506 + #define DISPLAY_PLANE_ENABLE (1 << 31) 507 + #define DISPLAY_PLANE_DISABLE 0 508 + #define DISPPLANE_GAMMA_ENABLE (1 << 30) 509 + #define DISPPLANE_GAMMA_DISABLE 0 510 + #define DISPPLANE_PIXFORMAT_MASK (0xf << 26) 511 + #define DISPPLANE_8BPP (0x2 << 26) 512 + #define DISPPLANE_15_16BPP (0x4 << 26) 513 + #define DISPPLANE_16BPP (0x5 << 26) 514 + #define DISPPLANE_32BPP_NO_ALPHA (0x6 << 26) 515 + #define DISPPLANE_32BPP (0x7 << 26) 516 + #define DISPPLANE_STEREO_ENABLE (1 << 25) 517 + #define DISPPLANE_STEREO_DISABLE 0 518 + #define DISPPLANE_SEL_PIPE_MASK (1 << 24) 519 + #define DISPPLANE_SEL_PIPE_POS 24 520 + #define DISPPLANE_SEL_PIPE_A 0 521 + #define DISPPLANE_SEL_PIPE_B (1 << 24) 522 + #define DISPPLANE_SRC_KEY_ENABLE (1 << 22) 523 + #define DISPPLANE_SRC_KEY_DISABLE 0 524 + #define DISPPLANE_LINE_DOUBLE (1 << 20) 525 + #define DISPPLANE_NO_LINE_DOUBLE 0 526 + #define DISPPLANE_STEREO_POLARITY_FIRST 0 527 + #define DISPPLANE_STEREO_POLARITY_SECOND (1 << 18) 528 + /* plane B only */ 529 + #define DISPPLANE_ALPHA_TRANS_ENABLE (1 << 15) 530 + #define DISPPLANE_ALPHA_TRANS_DISABLE 0 531 + #define DISPPLANE_SPRITE_ABOVE_DISPLAYA 0 532 + #define DISPPLANE_SPRITE_ABOVE_OVERLAY (1) 533 + #define DISPPLANE_BOTTOM (4) 534 + 535 + #define DSPABASE 0x70184 536 + #define DSPALINOFF 0x70184 537 + #define DSPASTRIDE 0x70188 538 + 539 + #define DSPBBASE 0x71184 540 + #define DSPBLINOFF 0X71184 541 + #define DSPBADDR DSPBBASE 542 + #define DSPBSTRIDE 0x71188 543 + 544 + #define DSPCBASE 0x72184 545 + #define DSPCLINOFF 0x72184 546 + #define DSPCSTRIDE 0x72188 547 + 548 + #define DSPAKEYVAL 0x70194 549 + #define DSPAKEYMASK 0x70198 550 + 551 + #define DSPAPOS 0x7018C /* reserved */ 552 + #define DSPASIZE 0x70190 553 + #define DSPBPOS 0x7118C 554 + #define DSPBSIZE 0x71190 555 + #define DSPCPOS 0x7218C 556 + #define DSPCSIZE 0x72190 557 + 558 + #define DSPASURF 0x7019C 559 + #define DSPATILEOFF 0x701A4 560 + 561 + #define DSPBSURF 0x7119C 562 + #define DSPBTILEOFF 0x711A4 563 + 564 + #define DSPCSURF 0x7219C 565 + #define DSPCTILEOFF 0x721A4 566 + #define DSPCKEYMAXVAL 0x721A0 567 + #define DSPCKEYMINVAL 0x72194 568 + #define DSPCKEYMSK 0x72198 569 + 570 + #define VGACNTRL 0x71400 571 + #define VGA_DISP_DISABLE (1 << 31) 572 + #define VGA_2X_MODE (1 << 30) 573 + #define VGA_PIPE_B_SELECT (1 << 29) 574 + 575 + /* 576 + * Overlay registers 577 + */ 578 + #define OV_C_OFFSET 0x08000 579 + #define OV_OVADD 0x30000 580 + #define OV_DOVASTA 0x30008 581 + # define OV_PIPE_SELECT ((1 << 6)|(1 << 7)) 582 + # define OV_PIPE_SELECT_POS 6 583 + # define OV_PIPE_A 0 584 + # define OV_PIPE_C 1 585 + #define OV_OGAMC5 0x30010 586 + #define OV_OGAMC4 0x30014 587 + #define OV_OGAMC3 0x30018 588 + #define OV_OGAMC2 0x3001C 589 + #define OV_OGAMC1 0x30020 590 + #define OV_OGAMC0 0x30024 591 + #define OVC_OVADD 0x38000 592 + #define OVC_DOVCSTA 0x38008 593 + #define OVC_OGAMC5 0x38010 594 + #define OVC_OGAMC4 0x38014 595 + #define OVC_OGAMC3 0x38018 596 + #define OVC_OGAMC2 0x3801C 597 + #define OVC_OGAMC1 0x38020 598 + #define OVC_OGAMC0 0x38024 599 + 600 + /* 601 + * Some BIOS scratch area registers. The 845 (and 830?) store the amount 602 + * of video memory available to the BIOS in SWF1. 603 + */ 604 + #define SWF0 0x71410 605 + #define SWF1 0x71414 606 + #define SWF2 0x71418 607 + #define SWF3 0x7141c 608 + #define SWF4 0x71420 609 + #define SWF5 0x71424 610 + #define SWF6 0x71428 611 + 612 + /* 613 + * 855 scratch registers. 614 + */ 615 + #define SWF00 0x70410 616 + #define SWF01 0x70414 617 + #define SWF02 0x70418 618 + #define SWF03 0x7041c 619 + #define SWF04 0x70420 620 + #define SWF05 0x70424 621 + #define SWF06 0x70428 622 + 623 + #define SWF10 SWF0 624 + #define SWF11 SWF1 625 + #define SWF12 SWF2 626 + #define SWF13 SWF3 627 + #define SWF14 SWF4 628 + #define SWF15 SWF5 629 + #define SWF16 SWF6 630 + 631 + #define SWF30 0x72414 632 + #define SWF31 0x72418 633 + #define SWF32 0x7241c 634 + 635 + 636 + /* 637 + * Palette registers 638 + */ 639 + #define PALETTE_A 0x0a000 640 + #define PALETTE_B 0x0a800 641 + #define PALETTE_C 0x0ac00 642 + 643 + /* Cursor A & B regs */ 644 + #define CURACNTR 0x70080 645 + #define CURSOR_MODE_DISABLE 0x00 646 + #define CURSOR_MODE_64_32B_AX 0x07 647 + #define CURSOR_MODE_64_ARGB_AX ((1 << 5) | CURSOR_MODE_64_32B_AX) 648 + #define MCURSOR_GAMMA_ENABLE (1 << 26) 649 + #define CURABASE 0x70084 650 + #define CURAPOS 0x70088 651 + #define CURSOR_POS_MASK 0x007FF 652 + #define CURSOR_POS_SIGN 0x8000 653 + #define CURSOR_X_SHIFT 0 654 + #define CURSOR_Y_SHIFT 16 655 + #define CURBCNTR 0x700c0 656 + #define CURBBASE 0x700c4 657 + #define CURBPOS 0x700c8 658 + #define CURCCNTR 0x700e0 659 + #define CURCBASE 0x700e4 660 + #define CURCPOS 0x700e8 661 + 662 + /* 663 + * Interrupt Registers 664 + */ 665 + #define IER 0x020a0 666 + #define IIR 0x020a4 667 + #define IMR 0x020a8 668 + #define ISR 0x020ac 669 + 670 + /* 671 + * MOORESTOWN delta registers 672 + */ 673 + #define MRST_DPLL_A 0x0f014 674 + #define MDFLD_DPLL_B 0x0f018 675 + #define MDFLD_INPUT_REF_SEL (1 << 14) 676 + #define MDFLD_VCO_SEL (1 << 16) 677 + #define DPLLA_MODE_LVDS (2 << 26) /* mrst */ 678 + #define MDFLD_PLL_LATCHEN (1 << 28) 679 + #define MDFLD_PWR_GATE_EN (1 << 30) 680 + #define MDFLD_P1_MASK (0x1FF << 17) 681 + #define MRST_FPA0 0x0f040 682 + #define MRST_FPA1 0x0f044 683 + #define MDFLD_DPLL_DIV0 0x0f048 684 + #define MDFLD_DPLL_DIV1 0x0f04c 685 + #define MRST_PERF_MODE 0x020f4 686 + 687 + /* 688 + * MEDFIELD HDMI registers 689 + */ 690 + #define HDMIPHYMISCCTL 0x61134 691 + #define HDMI_PHY_POWER_DOWN 0x7f 692 + #define HDMIB_CONTROL 0x61140 693 + #define HDMIB_PORT_EN (1 << 31) 694 + #define HDMIB_PIPE_B_SELECT (1 << 30) 695 + #define HDMIB_NULL_PACKET (1 << 9) 696 + #define HDMIB_HDCP_PORT (1 << 5) 697 + 698 + /* #define LVDS 0x61180 */ 699 + #define MRST_PANEL_8TO6_DITHER_ENABLE (1 << 25) 700 + #define MRST_PANEL_24_DOT_1_FORMAT (1 << 24) 701 + #define LVDS_A3_POWER_UP_0_OUTPUT (1 << 6) 702 + 703 + #define MIPI 0x61190 704 + #define MIPI_C 0x62190 705 + #define MIPI_PORT_EN (1 << 31) 706 + /* Turns on border drawing to allow centered display. */ 707 + #define SEL_FLOPPED_HSTX (1 << 23) 708 + #define PASS_FROM_SPHY_TO_AFE (1 << 16) 709 + #define MIPI_BORDER_EN (1 << 15) 710 + #define MIPIA_3LANE_MIPIC_1LANE 0x1 711 + #define MIPIA_2LANE_MIPIC_2LANE 0x2 712 + #define TE_TRIGGER_DSI_PROTOCOL (1 << 2) 713 + #define TE_TRIGGER_GPIO_PIN (1 << 3) 714 + #define MIPI_TE_COUNT 0x61194 715 + 716 + /* #define PP_CONTROL 0x61204 */ 717 + #define POWER_DOWN_ON_RESET (1 << 1) 718 + 719 + /* #define PFIT_CONTROL 0x61230 */ 720 + #define PFIT_PIPE_SELECT (3 << 29) 721 + #define PFIT_PIPE_SELECT_SHIFT (29) 722 + 723 + /* #define BLC_PWM_CTL 0x61254 */ 724 + #define MRST_BACKLIGHT_MODULATION_FREQ_SHIFT (16) 725 + #define MRST_BACKLIGHT_MODULATION_FREQ_MASK (0xffff << 16) 726 + 727 + /* #define PIPEACONF 0x70008 */ 728 + #define PIPEACONF_PIPE_STATE (1 << 30) 729 + /* #define DSPACNTR 0x70180 */ 730 + 731 + #define MRST_DSPABASE 0x7019c 732 + #define MRST_DSPBBASE 0x7119c 733 + #define MDFLD_DSPCBASE 0x7219c 734 + 735 + /* 736 + * Moorestown registers. 737 + */ 738 + 739 + /* 740 + * MIPI IP registers 741 + */ 742 + #define MIPIC_REG_OFFSET 0x800 743 + 744 + #define DEVICE_READY_REG 0xb000 745 + #define LP_OUTPUT_HOLD (1 << 16) 746 + #define EXIT_ULPS_DEV_READY 0x3 747 + #define LP_OUTPUT_HOLD_RELEASE 0x810000 748 + # define ENTERING_ULPS (2 << 1) 749 + # define EXITING_ULPS (1 << 1) 750 + # define ULPS_MASK (3 << 1) 751 + # define BUS_POSSESSION (1 << 3) 752 + #define INTR_STAT_REG 0xb004 753 + #define RX_SOT_ERROR (1 << 0) 754 + #define RX_SOT_SYNC_ERROR (1 << 1) 755 + #define RX_ESCAPE_MODE_ENTRY_ERROR (1 << 3) 756 + #define RX_LP_TX_SYNC_ERROR (1 << 4) 757 + #define RX_HS_RECEIVE_TIMEOUT_ERROR (1 << 5) 758 + #define RX_FALSE_CONTROL_ERROR (1 << 6) 759 + #define RX_ECC_SINGLE_BIT_ERROR (1 << 7) 760 + #define RX_ECC_MULTI_BIT_ERROR (1 << 8) 761 + #define RX_CHECKSUM_ERROR (1 << 9) 762 + #define RX_DSI_DATA_TYPE_NOT_RECOGNIZED (1 << 10) 763 + #define RX_DSI_VC_ID_INVALID (1 << 11) 764 + #define TX_FALSE_CONTROL_ERROR (1 << 12) 765 + #define TX_ECC_SINGLE_BIT_ERROR (1 << 13) 766 + #define TX_ECC_MULTI_BIT_ERROR (1 << 14) 767 + #define TX_CHECKSUM_ERROR (1 << 15) 768 + #define TX_DSI_DATA_TYPE_NOT_RECOGNIZED (1 << 16) 769 + #define TX_DSI_VC_ID_INVALID (1 << 17) 770 + #define HIGH_CONTENTION (1 << 18) 771 + #define LOW_CONTENTION (1 << 19) 772 + #define DPI_FIFO_UNDER_RUN (1 << 20) 773 + #define HS_TX_TIMEOUT (1 << 21) 774 + #define LP_RX_TIMEOUT (1 << 22) 775 + #define TURN_AROUND_ACK_TIMEOUT (1 << 23) 776 + #define ACK_WITH_NO_ERROR (1 << 24) 777 + #define HS_GENERIC_WR_FIFO_FULL (1 << 27) 778 + #define LP_GENERIC_WR_FIFO_FULL (1 << 28) 779 + #define SPL_PKT_SENT (1 << 30) 780 + #define INTR_EN_REG 0xb008 781 + #define DSI_FUNC_PRG_REG 0xb00c 782 + #define DPI_CHANNEL_NUMBER_POS 0x03 783 + #define DBI_CHANNEL_NUMBER_POS 0x05 784 + #define FMT_DPI_POS 0x07 785 + #define FMT_DBI_POS 0x0A 786 + #define DBI_DATA_WIDTH_POS 0x0D 787 + 788 + /* DPI PIXEL FORMATS */ 789 + #define RGB_565_FMT 0x01 /* RGB 565 FORMAT */ 790 + #define RGB_666_FMT 0x02 /* RGB 666 FORMAT */ 791 + #define LRGB_666_FMT 0x03 /* RGB LOOSELY PACKED 792 + * 666 FORMAT 793 + */ 794 + #define RGB_888_FMT 0x04 /* RGB 888 FORMAT */ 795 + #define VIRTUAL_CHANNEL_NUMBER_0 0x00 /* Virtual channel 0 */ 796 + #define VIRTUAL_CHANNEL_NUMBER_1 0x01 /* Virtual channel 1 */ 797 + #define VIRTUAL_CHANNEL_NUMBER_2 0x02 /* Virtual channel 2 */ 798 + #define VIRTUAL_CHANNEL_NUMBER_3 0x03 /* Virtual channel 3 */ 799 + 800 + #define DBI_NOT_SUPPORTED 0x00 /* command mode 801 + * is not supported 802 + */ 803 + #define DBI_DATA_WIDTH_16BIT 0x01 /* 16 bit data */ 804 + #define DBI_DATA_WIDTH_9BIT 0x02 /* 9 bit data */ 805 + #define DBI_DATA_WIDTH_8BIT 0x03 /* 8 bit data */ 806 + #define DBI_DATA_WIDTH_OPT1 0x04 /* option 1 */ 807 + #define DBI_DATA_WIDTH_OPT2 0x05 /* option 2 */ 808 + 809 + #define HS_TX_TIMEOUT_REG 0xb010 810 + #define LP_RX_TIMEOUT_REG 0xb014 811 + #define TURN_AROUND_TIMEOUT_REG 0xb018 812 + #define DEVICE_RESET_REG 0xb01C 813 + #define DPI_RESOLUTION_REG 0xb020 814 + #define RES_V_POS 0x10 815 + #define DBI_RESOLUTION_REG 0xb024 /* Reserved for MDFLD */ 816 + #define HORIZ_SYNC_PAD_COUNT_REG 0xb028 817 + #define HORIZ_BACK_PORCH_COUNT_REG 0xb02C 818 + #define HORIZ_FRONT_PORCH_COUNT_REG 0xb030 819 + #define HORIZ_ACTIVE_AREA_COUNT_REG 0xb034 820 + #define VERT_SYNC_PAD_COUNT_REG 0xb038 821 + #define VERT_BACK_PORCH_COUNT_REG 0xb03c 822 + #define VERT_FRONT_PORCH_COUNT_REG 0xb040 823 + #define HIGH_LOW_SWITCH_COUNT_REG 0xb044 824 + #define DPI_CONTROL_REG 0xb048 825 + #define DPI_SHUT_DOWN (1 << 0) 826 + #define DPI_TURN_ON (1 << 1) 827 + #define DPI_COLOR_MODE_ON (1 << 2) 828 + #define DPI_COLOR_MODE_OFF (1 << 3) 829 + #define DPI_BACK_LIGHT_ON (1 << 4) 830 + #define DPI_BACK_LIGHT_OFF (1 << 5) 831 + #define DPI_LP (1 << 6) 832 + #define DPI_DATA_REG 0xb04c 833 + #define DPI_BACK_LIGHT_ON_DATA 0x07 834 + #define DPI_BACK_LIGHT_OFF_DATA 0x17 835 + #define INIT_COUNT_REG 0xb050 836 + #define MAX_RET_PAK_REG 0xb054 837 + #define VIDEO_FMT_REG 0xb058 838 + #define COMPLETE_LAST_PCKT (1 << 2) 839 + #define EOT_DISABLE_REG 0xb05c 840 + #define ENABLE_CLOCK_STOPPING (1 << 1) 841 + #define LP_BYTECLK_REG 0xb060 842 + #define LP_GEN_DATA_REG 0xb064 843 + #define HS_GEN_DATA_REG 0xb068 844 + #define LP_GEN_CTRL_REG 0xb06C 845 + #define HS_GEN_CTRL_REG 0xb070 846 + #define DCS_CHANNEL_NUMBER_POS 0x6 847 + #define MCS_COMMANDS_POS 0x8 848 + #define WORD_COUNTS_POS 0x8 849 + #define MCS_PARAMETER_POS 0x10 850 + #define GEN_FIFO_STAT_REG 0xb074 851 + #define HS_DATA_FIFO_FULL (1 << 0) 852 + #define HS_DATA_FIFO_HALF_EMPTY (1 << 1) 853 + #define HS_DATA_FIFO_EMPTY (1 << 2) 854 + #define LP_DATA_FIFO_FULL (1 << 8) 855 + #define LP_DATA_FIFO_HALF_EMPTY (1 << 9) 856 + #define LP_DATA_FIFO_EMPTY (1 << 10) 857 + #define HS_CTRL_FIFO_FULL (1 << 16) 858 + #define HS_CTRL_FIFO_HALF_EMPTY (1 << 17) 859 + #define HS_CTRL_FIFO_EMPTY (1 << 18) 860 + #define LP_CTRL_FIFO_FULL (1 << 24) 861 + #define LP_CTRL_FIFO_HALF_EMPTY (1 << 25) 862 + #define LP_CTRL_FIFO_EMPTY (1 << 26) 863 + #define DBI_FIFO_EMPTY (1 << 27) 864 + #define DPI_FIFO_EMPTY (1 << 28) 865 + #define HS_LS_DBI_ENABLE_REG 0xb078 866 + #define TXCLKESC_REG 0xb07c 867 + #define DPHY_PARAM_REG 0xb080 868 + #define DBI_BW_CTRL_REG 0xb084 869 + #define CLK_LANE_SWT_REG 0xb088 870 + 871 + /* 872 + * MIPI Adapter registers 873 + */ 874 + #define MIPI_CONTROL_REG 0xb104 875 + #define MIPI_2X_CLOCK_BITS ((1 << 0) | (1 << 1)) 876 + #define MIPI_DATA_ADDRESS_REG 0xb108 877 + #define MIPI_DATA_LENGTH_REG 0xb10C 878 + #define MIPI_COMMAND_ADDRESS_REG 0xb110 879 + #define MIPI_COMMAND_LENGTH_REG 0xb114 880 + #define MIPI_READ_DATA_RETURN_REG0 0xb118 881 + #define MIPI_READ_DATA_RETURN_REG1 0xb11C 882 + #define MIPI_READ_DATA_RETURN_REG2 0xb120 883 + #define MIPI_READ_DATA_RETURN_REG3 0xb124 884 + #define MIPI_READ_DATA_RETURN_REG4 0xb128 885 + #define MIPI_READ_DATA_RETURN_REG5 0xb12C 886 + #define MIPI_READ_DATA_RETURN_REG6 0xb130 887 + #define MIPI_READ_DATA_RETURN_REG7 0xb134 888 + #define MIPI_READ_DATA_VALID_REG 0xb138 889 + 890 + /* DBI COMMANDS */ 891 + #define soft_reset 0x01 892 + /* 893 + * The display module performs a software reset. 894 + * Registers are written with their SW Reset default values. 895 + */ 896 + #define get_power_mode 0x0a 897 + /* 898 + * The display module returns the current power mode 899 + */ 900 + #define get_address_mode 0x0b 901 + /* 902 + * The display module returns the current status. 903 + */ 904 + #define get_pixel_format 0x0c 905 + /* 906 + * This command gets the pixel format for the RGB image data 907 + * used by the interface. 908 + */ 909 + #define get_display_mode 0x0d 910 + /* 911 + * The display module returns the Display Image Mode status. 912 + */ 913 + #define get_signal_mode 0x0e 914 + /* 915 + * The display module returns the Display Signal Mode. 916 + */ 917 + #define get_diagnostic_result 0x0f 918 + /* 919 + * The display module returns the self-diagnostic results following 920 + * a Sleep Out command. 921 + */ 922 + #define enter_sleep_mode 0x10 923 + /* 924 + * This command causes the display module to enter the Sleep mode. 925 + * In this mode, all unnecessary blocks inside the display module are 926 + * disabled except interface communication. This is the lowest power 927 + * mode the display module supports. 928 + */ 929 + #define exit_sleep_mode 0x11 930 + /* 931 + * This command causes the display module to exit Sleep mode. 932 + * All blocks inside the display module are enabled. 933 + */ 934 + #define enter_partial_mode 0x12 935 + /* 936 + * This command causes the display module to enter the Partial Display 937 + * Mode. The Partial Display Mode window is described by the 938 + * set_partial_area command. 939 + */ 940 + #define enter_normal_mode 0x13 941 + /* 942 + * This command causes the display module to enter the Normal mode. 943 + * Normal Mode is defined as Partial Display mode and Scroll mode are off 944 + */ 945 + #define exit_invert_mode 0x20 946 + /* 947 + * This command causes the display module to stop inverting the image 948 + * data on the display device. The frame memory contents remain unchanged. 949 + * No status bits are changed. 950 + */ 951 + #define enter_invert_mode 0x21 952 + /* 953 + * This command causes the display module to invert the image data only on 954 + * the display device. The frame memory contents remain unchanged. 955 + * No status bits are changed. 956 + */ 957 + #define set_gamma_curve 0x26 958 + /* 959 + * This command selects the desired gamma curve for the display device. 960 + * Four fixed gamma curves are defined in section DCS spec. 961 + */ 962 + #define set_display_off 0x28 963 + /* ************************************************************************* *\ 964 + This command causes the display module to stop displaying the image data 965 + on the display device. The frame memory contents remain unchanged. 966 + No status bits are changed. 967 + \* ************************************************************************* */ 968 + #define set_display_on 0x29 969 + /* ************************************************************************* *\ 970 + This command causes the display module to start displaying the image data 971 + on the display device. The frame memory contents remain unchanged. 972 + No status bits are changed. 973 + \* ************************************************************************* */ 974 + #define set_column_address 0x2a 975 + /* 976 + * This command defines the column extent of the frame memory accessed by 977 + * the hostprocessor with the read_memory_continue and 978 + * write_memory_continue commands. 979 + * No status bits are changed. 980 + */ 981 + #define set_page_addr 0x2b 982 + /* 983 + * This command defines the page extent of the frame memory accessed by 984 + * the host processor with the write_memory_continue and 985 + * read_memory_continue command. 986 + * No status bits are changed. 987 + */ 988 + #define write_mem_start 0x2c 989 + /* 990 + * This command transfers image data from the host processor to the 991 + * display modules frame memory starting at the pixel location specified 992 + * by preceding set_column_address and set_page_address commands. 993 + */ 994 + #define set_partial_area 0x30 995 + /* 996 + * This command defines the Partial Display mode s display area. 997 + * There are two parameters associated with this command, the first 998 + * defines the Start Row (SR) and the second the End Row (ER). SR and ER 999 + * refer to the Frame Memory Line Pointer. 1000 + */ 1001 + #define set_scroll_area 0x33 1002 + /* 1003 + * This command defines the display modules Vertical Scrolling Area. 1004 + */ 1005 + #define set_tear_off 0x34 1006 + /* 1007 + * This command turns off the display modules Tearing Effect output 1008 + * signal on the TE signal line. 1009 + */ 1010 + #define set_tear_on 0x35 1011 + /* 1012 + * This command turns on the display modules Tearing Effect output signal 1013 + * on the TE signal line. 1014 + */ 1015 + #define set_address_mode 0x36 1016 + /* 1017 + * This command sets the data order for transfers from the host processor 1018 + * to display modules frame memory,bits B[7:5] and B3, and from the 1019 + * display modules frame memory to the display device, bits B[2:0] and B4. 1020 + */ 1021 + #define set_scroll_start 0x37 1022 + /* 1023 + * This command sets the start of the vertical scrolling area in the frame 1024 + * memory. The vertical scrolling area is fully defined when this command 1025 + * is used with the set_scroll_area command The set_scroll_start command 1026 + * has one parameter, the Vertical Scroll Pointer. The VSP defines the 1027 + * line in the frame memory that is written to the display device as the 1028 + * first line of the vertical scroll area. 1029 + */ 1030 + #define exit_idle_mode 0x38 1031 + /* 1032 + * This command causes the display module to exit Idle mode. 1033 + */ 1034 + #define enter_idle_mode 0x39 1035 + /* 1036 + * This command causes the display module to enter Idle Mode. 1037 + * In Idle Mode, color expression is reduced. Colors are shown on the 1038 + * display device using the MSB of each of the R, G and B color 1039 + * components in the frame memory 1040 + */ 1041 + #define set_pixel_format 0x3a 1042 + /* 1043 + * This command sets the pixel format for the RGB image data used by the 1044 + * interface. 1045 + * Bits D[6:4] DPI Pixel Format Definition 1046 + * Bits D[2:0] DBI Pixel Format Definition 1047 + * Bits D7 and D3 are not used. 1048 + */ 1049 + #define DCS_PIXEL_FORMAT_3bpp 0x1 1050 + #define DCS_PIXEL_FORMAT_8bpp 0x2 1051 + #define DCS_PIXEL_FORMAT_12bpp 0x3 1052 + #define DCS_PIXEL_FORMAT_16bpp 0x5 1053 + #define DCS_PIXEL_FORMAT_18bpp 0x6 1054 + #define DCS_PIXEL_FORMAT_24bpp 0x7 1055 + 1056 + #define write_mem_cont 0x3c 1057 + 1058 + /* 1059 + * This command transfers image data from the host processor to the 1060 + * display module's frame memory continuing from the pixel location 1061 + * following the previous write_memory_continue or write_memory_start 1062 + * command. 1063 + */ 1064 + #define set_tear_scanline 0x44 1065 + /* 1066 + * This command turns on the display modules Tearing Effect output signal 1067 + * on the TE signal line when the display module reaches line N. 1068 + */ 1069 + #define get_scanline 0x45 1070 + /* 1071 + * The display module returns the current scanline, N, used to update the 1072 + * display device. The total number of scanlines on a display device is 1073 + * defined as VSYNC + VBP + VACT + VFP.The first scanline is defined as 1074 + * the first line of V Sync and is denoted as Line 0. 1075 + * When in Sleep Mode, the value returned by get_scanline is undefined. 1076 + */ 1077 + 1078 + /* MCS or Generic COMMANDS */ 1079 + /* MCS/generic data type */ 1080 + #define GEN_SHORT_WRITE_0 0x03 /* generic short write, no parameters */ 1081 + #define GEN_SHORT_WRITE_1 0x13 /* generic short write, 1 parameters */ 1082 + #define GEN_SHORT_WRITE_2 0x23 /* generic short write, 2 parameters */ 1083 + #define GEN_READ_0 0x04 /* generic read, no parameters */ 1084 + #define GEN_READ_1 0x14 /* generic read, 1 parameters */ 1085 + #define GEN_READ_2 0x24 /* generic read, 2 parameters */ 1086 + #define GEN_LONG_WRITE 0x29 /* generic long write */ 1087 + #define MCS_SHORT_WRITE_0 0x05 /* MCS short write, no parameters */ 1088 + #define MCS_SHORT_WRITE_1 0x15 /* MCS short write, 1 parameters */ 1089 + #define MCS_READ 0x06 /* MCS read, no parameters */ 1090 + #define MCS_LONG_WRITE 0x39 /* MCS long write */ 1091 + /* MCS/generic commands */ 1092 + /* TPO MCS */ 1093 + #define write_display_profile 0x50 1094 + #define write_display_brightness 0x51 1095 + #define write_ctrl_display 0x53 1096 + #define write_ctrl_cabc 0x55 1097 + #define UI_IMAGE 0x01 1098 + #define STILL_IMAGE 0x02 1099 + #define MOVING_IMAGE 0x03 1100 + #define write_hysteresis 0x57 1101 + #define write_gamma_setting 0x58 1102 + #define write_cabc_min_bright 0x5e 1103 + #define write_kbbc_profile 0x60 1104 + /* TMD MCS */ 1105 + #define tmd_write_display_brightness 0x8c 1106 + 1107 + /* 1108 + * This command is used to control ambient light, panel backlight 1109 + * brightness and gamma settings. 1110 + */ 1111 + #define BRIGHT_CNTL_BLOCK_ON (1 << 5) 1112 + #define AMBIENT_LIGHT_SENSE_ON (1 << 4) 1113 + #define DISPLAY_DIMMING_ON (1 << 3) 1114 + #define BACKLIGHT_ON (1 << 2) 1115 + #define DISPLAY_BRIGHTNESS_AUTO (1 << 1) 1116 + #define GAMMA_AUTO (1 << 0) 1117 + 1118 + /* DCS Interface Pixel Formats */ 1119 + #define DCS_PIXEL_FORMAT_3BPP 0x1 1120 + #define DCS_PIXEL_FORMAT_8BPP 0x2 1121 + #define DCS_PIXEL_FORMAT_12BPP 0x3 1122 + #define DCS_PIXEL_FORMAT_16BPP 0x5 1123 + #define DCS_PIXEL_FORMAT_18BPP 0x6 1124 + #define DCS_PIXEL_FORMAT_24BPP 0x7 1125 + /* ONE PARAMETER READ DATA */ 1126 + #define addr_mode_data 0xfc 1127 + #define diag_res_data 0x00 1128 + #define disp_mode_data 0x23 1129 + #define pxl_fmt_data 0x77 1130 + #define pwr_mode_data 0x74 1131 + #define sig_mode_data 0x00 1132 + /* TWO PARAMETERS READ DATA */ 1133 + #define scanline_data1 0xff 1134 + #define scanline_data2 0xff 1135 + #define NON_BURST_MODE_SYNC_PULSE 0x01 /* Non Burst Mode 1136 + * with Sync Pulse 1137 + */ 1138 + #define NON_BURST_MODE_SYNC_EVENTS 0x02 /* Non Burst Mode 1139 + * with Sync events 1140 + */ 1141 + #define BURST_MODE 0x03 /* Burst Mode */ 1142 + #define DBI_COMMAND_BUFFER_SIZE 0x240 /* 0x32 */ /* 0x120 */ 1143 + /* Allocate at least 1144 + * 0x100 Byte with 32 1145 + * byte alignment 1146 + */ 1147 + #define DBI_DATA_BUFFER_SIZE 0x120 /* Allocate at least 1148 + * 0x100 Byte with 32 1149 + * byte alignment 1150 + */ 1151 + #define DBI_CB_TIME_OUT 0xFFFF 1152 + 1153 + #define GEN_FB_TIME_OUT 2000 1154 + 1155 + #define SKU_83 0x01 1156 + #define SKU_100 0x02 1157 + #define SKU_100L 0x04 1158 + #define SKU_BYPASS 0x08 1159 + 1160 + /* Some handy macros for playing with bitfields. */ 1161 + #define PSB_MASK(high, low) (((1<<((high)-(low)+1))-1)<<(low)) 1162 + #define SET_FIELD(value, field) (((value) << field ## _SHIFT) & field ## _MASK) 1163 + #define GET_FIELD(word, field) (((word) & field ## _MASK) >> field ## _SHIFT) 1164 + 1165 + #define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a))) 1166 + 1167 + /* PCI config space */ 1168 + 1169 + #define SB_PCKT 0x02100 /* cedarview */ 1170 + # define SB_OPCODE_MASK PSB_MASK(31, 16) 1171 + # define SB_OPCODE_SHIFT 16 1172 + # define SB_OPCODE_READ 0 1173 + # define SB_OPCODE_WRITE 1 1174 + # define SB_DEST_MASK PSB_MASK(15, 8) 1175 + # define SB_DEST_SHIFT 8 1176 + # define SB_DEST_DPLL 0x88 1177 + # define SB_BYTE_ENABLE_MASK PSB_MASK(7, 4) 1178 + # define SB_BYTE_ENABLE_SHIFT 4 1179 + # define SB_BUSY (1 << 0) 1180 + 1181 + 1182 + /* 32-bit value read/written from the DPIO reg. */ 1183 + #define SB_DATA 0x02104 /* cedarview */ 1184 + /* 32-bit address of the DPIO reg to be read/written. */ 1185 + #define SB_ADDR 0x02108 /* cedarview */ 1186 + #define DPIO_CFG 0x02110 /* cedarview */ 1187 + # define DPIO_MODE_SELECT_1 (1 << 3) 1188 + # define DPIO_MODE_SELECT_0 (1 << 2) 1189 + # define DPIO_SFR_BYPASS (1 << 1) 1190 + /* reset is active low */ 1191 + # define DPIO_CMN_RESET_N (1 << 0) 1192 + 1193 + /* Cedarview sideband registers */ 1194 + #define _SB_M_A 0x8008 1195 + #define _SB_M_B 0x8028 1196 + #define SB_M(pipe) _PIPE(pipe, _SB_M_A, _SB_M_B) 1197 + # define SB_M_DIVIDER_MASK (0xFF << 24) 1198 + # define SB_M_DIVIDER_SHIFT 24 1199 + 1200 + #define _SB_N_VCO_A 0x8014 1201 + #define _SB_N_VCO_B 0x8034 1202 + #define SB_N_VCO(pipe) _PIPE(pipe, _SB_N_VCO_A, _SB_N_VCO_B) 1203 + #define SB_N_VCO_SEL_MASK PSB_MASK(31, 30) 1204 + #define SB_N_VCO_SEL_SHIFT 30 1205 + #define SB_N_DIVIDER_MASK PSB_MASK(29, 26) 1206 + #define SB_N_DIVIDER_SHIFT 26 1207 + #define SB_N_CB_TUNE_MASK PSB_MASK(25, 24) 1208 + #define SB_N_CB_TUNE_SHIFT 24 1209 + 1210 + #define _SB_REF_A 0x8018 1211 + #define _SB_REF_B 0x8038 1212 + #define SB_REF_SFR(pipe) _PIPE(pipe, _SB_REF_A, _SB_REF_B) 1213 + 1214 + #define _SB_P_A 0x801c 1215 + #define _SB_P_B 0x803c 1216 + #define SB_P(pipe) _PIPE(pipe, _SB_P_A, _SB_P_B) 1217 + #define SB_P2_DIVIDER_MASK PSB_MASK(31, 30) 1218 + #define SB_P2_DIVIDER_SHIFT 30 1219 + #define SB_P2_10 0 /* HDMI, DP, DAC */ 1220 + #define SB_P2_5 1 /* DAC */ 1221 + #define SB_P2_14 2 /* LVDS single */ 1222 + #define SB_P2_7 3 /* LVDS double */ 1223 + #define SB_P1_DIVIDER_MASK PSB_MASK(15, 12) 1224 + #define SB_P1_DIVIDER_SHIFT 12 1225 + 1226 + #define PSB_LANE0 0x120 1227 + #define PSB_LANE1 0x220 1228 + #define PSB_LANE2 0x2320 1229 + #define PSB_LANE3 0x2420 1230 + 1231 + #define LANE_PLL_MASK (0x7 << 20) 1232 + #define LANE_PLL_ENABLE (0x3 << 20) 1233 + 1234 + 1235 + #endif
+1293
drivers/gpu/drm/gma500/psb_intel_sdvo.c
··· 1 + /* 2 + * Copyright (c) 2006-2007 Intel Corporation 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms and conditions of the GNU General Public License, 6 + * version 2, as published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope it will be useful, but WITHOUT 9 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 + * more details. 12 + * 13 + * You should have received a copy of the GNU General Public License along with 14 + * this program; if not, write to the Free Software Foundation, Inc., 15 + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 16 + * 17 + * Authors: 18 + * Eric Anholt <eric@anholt.net> 19 + */ 20 + 21 + #include <linux/i2c.h> 22 + #include <linux/delay.h> 23 + /* #include <drm/drm_crtc.h> */ 24 + #include <drm/drmP.h> 25 + #include "psb_drv.h" 26 + #include "psb_intel_drv.h" 27 + #include "psb_intel_reg.h" 28 + #include "psb_intel_sdvo_regs.h" 29 + 30 + struct psb_intel_sdvo_priv { 31 + struct psb_intel_i2c_chan *i2c_bus; 32 + int slaveaddr; 33 + int output_device; 34 + 35 + u16 active_outputs; 36 + 37 + struct psb_intel_sdvo_caps caps; 38 + int pixel_clock_min, pixel_clock_max; 39 + 40 + int save_sdvo_mult; 41 + u16 save_active_outputs; 42 + struct psb_intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2; 43 + struct psb_intel_sdvo_dtd save_output_dtd[16]; 44 + u32 save_SDVOX; 45 + u8 in_out_map[4]; 46 + 47 + u8 by_input_wiring; 48 + u32 active_device; 49 + }; 50 + 51 + /** 52 + * Writes the SDVOB or SDVOC with the given value, but always writes both 53 + * SDVOB and SDVOC to work around apparent hardware issues (according to 54 + * comments in the BIOS). 55 + */ 56 + void psb_intel_sdvo_write_sdvox(struct psb_intel_output *psb_intel_output, 57 + u32 val) 58 + { 59 + struct drm_device *dev = psb_intel_output->base.dev; 60 + struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; 61 + u32 bval = val, cval = val; 62 + int i; 63 + 64 + if (sdvo_priv->output_device == SDVOB) 65 + cval = REG_READ(SDVOC); 66 + else 67 + bval = REG_READ(SDVOB); 68 + /* 69 + * Write the registers twice for luck. Sometimes, 70 + * writing them only once doesn't appear to 'stick'. 71 + * The BIOS does this too. Yay, magic 72 + */ 73 + for (i = 0; i < 2; i++) { 74 + REG_WRITE(SDVOB, bval); 75 + REG_READ(SDVOB); 76 + REG_WRITE(SDVOC, cval); 77 + REG_READ(SDVOC); 78 + } 79 + } 80 + 81 + static bool psb_intel_sdvo_read_byte( 82 + struct psb_intel_output *psb_intel_output, 83 + u8 addr, u8 *ch) 84 + { 85 + struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; 86 + u8 out_buf[2]; 87 + u8 buf[2]; 88 + int ret; 89 + 90 + struct i2c_msg msgs[] = { 91 + { 92 + .addr = sdvo_priv->i2c_bus->slave_addr, 93 + .flags = 0, 94 + .len = 1, 95 + .buf = out_buf, 96 + }, 97 + { 98 + .addr = sdvo_priv->i2c_bus->slave_addr, 99 + .flags = I2C_M_RD, 100 + .len = 1, 101 + .buf = buf, 102 + } 103 + }; 104 + 105 + out_buf[0] = addr; 106 + out_buf[1] = 0; 107 + 108 + ret = i2c_transfer(&sdvo_priv->i2c_bus->adapter, msgs, 2); 109 + if (ret == 2) { 110 + *ch = buf[0]; 111 + return true; 112 + } 113 + 114 + return false; 115 + } 116 + 117 + static bool psb_intel_sdvo_write_byte( 118 + struct psb_intel_output *psb_intel_output, 119 + int addr, u8 ch) 120 + { 121 + u8 out_buf[2]; 122 + struct i2c_msg msgs[] = { 123 + { 124 + .addr = psb_intel_output->i2c_bus->slave_addr, 125 + .flags = 0, 126 + .len = 2, 127 + .buf = out_buf, 128 + } 129 + }; 130 + 131 + out_buf[0] = addr; 132 + out_buf[1] = ch; 133 + 134 + if (i2c_transfer(&psb_intel_output->i2c_bus->adapter, msgs, 1) == 1) 135 + return true; 136 + return false; 137 + } 138 + 139 + #define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd} 140 + /** Mapping of command numbers to names, for debug output */ 141 + static const struct _sdvo_cmd_name { 142 + u8 cmd; 143 + char *name; 144 + } sdvo_cmd_names[] = { 145 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET), 146 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS), 147 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV), 148 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TRAINED_INPUTS), 149 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_OUTPUTS), 150 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_OUTPUTS), 151 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_IN_OUT_MAP), 152 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_IN_OUT_MAP), 153 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ATTACHED_DISPLAYS), 154 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HOT_PLUG_SUPPORT), 155 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_HOT_PLUG), 156 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_HOT_PLUG), 157 + SDVO_CMD_NAME_ENTRY 158 + (SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE), 159 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_INPUT), 160 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_OUTPUT), 161 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART1), 162 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART2), 163 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1), 164 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART2), 165 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1), 166 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART1), 167 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART2), 168 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART1), 169 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART2), 170 + SDVO_CMD_NAME_ENTRY 171 + (SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING), 172 + SDVO_CMD_NAME_ENTRY 173 + (SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1), 174 + SDVO_CMD_NAME_ENTRY 175 + (SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2), 176 + SDVO_CMD_NAME_ENTRY 177 + (SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE), 178 + SDVO_CMD_NAME_ENTRY 179 + (SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE), 180 + SDVO_CMD_NAME_ENTRY 181 + (SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS), 182 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CLOCK_RATE_MULT), 183 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CLOCK_RATE_MULT), 184 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS), 185 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT), 186 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT), 187 + SDVO_CMD_NAME_ENTRY 188 + (SDVO_CMD_SET_TV_RESOLUTION_SUPPORT), 189 + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH),}; 190 + 191 + #define SDVO_NAME(dev_priv) \ 192 + ((dev_priv)->output_device == SDVOB ? "SDVOB" : "SDVOC") 193 + #define SDVO_PRIV(output) ((struct psb_intel_sdvo_priv *) (output)->dev_priv) 194 + 195 + static void psb_intel_sdvo_write_cmd(struct psb_intel_output *psb_intel_output, 196 + u8 cmd, 197 + void *args, 198 + int args_len) 199 + { 200 + struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; 201 + int i; 202 + 203 + if (0) { 204 + printk(KERN_DEBUG "%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd); 205 + for (i = 0; i < args_len; i++) 206 + printk(KERN_CONT "%02X ", ((u8 *) args)[i]); 207 + for (; i < 8; i++) 208 + printk(KERN_CONT " "); 209 + for (i = 0; 210 + i < 211 + sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]); 212 + i++) { 213 + if (cmd == sdvo_cmd_names[i].cmd) { 214 + printk(KERN_CONT 215 + "(%s)", sdvo_cmd_names[i].name); 216 + break; 217 + } 218 + } 219 + if (i == 220 + sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0])) 221 + printk(KERN_CONT "(%02X)", cmd); 222 + printk(KERN_CONT "\n"); 223 + } 224 + 225 + for (i = 0; i < args_len; i++) { 226 + psb_intel_sdvo_write_byte(psb_intel_output, 227 + SDVO_I2C_ARG_0 - i, 228 + ((u8 *) args)[i]); 229 + } 230 + 231 + psb_intel_sdvo_write_byte(psb_intel_output, SDVO_I2C_OPCODE, cmd); 232 + } 233 + 234 + static const char *const cmd_status_names[] = { 235 + "Power on", 236 + "Success", 237 + "Not supported", 238 + "Invalid arg", 239 + "Pending", 240 + "Target not specified", 241 + "Scaling not supported" 242 + }; 243 + 244 + static u8 psb_intel_sdvo_read_response( 245 + struct psb_intel_output *psb_intel_output, 246 + void *response, int response_len) 247 + { 248 + struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; 249 + int i; 250 + u8 status; 251 + u8 retry = 50; 252 + 253 + while (retry--) { 254 + /* Read the command response */ 255 + for (i = 0; i < response_len; i++) { 256 + psb_intel_sdvo_read_byte(psb_intel_output, 257 + SDVO_I2C_RETURN_0 + i, 258 + &((u8 *) response)[i]); 259 + } 260 + 261 + /* read the return status */ 262 + psb_intel_sdvo_read_byte(psb_intel_output, 263 + SDVO_I2C_CMD_STATUS, 264 + &status); 265 + 266 + if (0) { 267 + pr_debug("%s: R: ", SDVO_NAME(sdvo_priv)); 268 + for (i = 0; i < response_len; i++) 269 + printk(KERN_CONT "%02X ", ((u8 *) response)[i]); 270 + for (; i < 8; i++) 271 + printk(" "); 272 + if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) 273 + printk(KERN_CONT "(%s)", 274 + cmd_status_names[status]); 275 + else 276 + printk(KERN_CONT "(??? %d)", status); 277 + printk(KERN_CONT "\n"); 278 + } 279 + 280 + if (status != SDVO_CMD_STATUS_PENDING) 281 + return status; 282 + 283 + mdelay(50); 284 + } 285 + 286 + return status; 287 + } 288 + 289 + int psb_intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode) 290 + { 291 + if (mode->clock >= 100000) 292 + return 1; 293 + else if (mode->clock >= 50000) 294 + return 2; 295 + else 296 + return 4; 297 + } 298 + 299 + /** 300 + * Don't check status code from this as it switches the bus back to the 301 + * SDVO chips which defeats the purpose of doing a bus switch in the first 302 + * place. 303 + */ 304 + void psb_intel_sdvo_set_control_bus_switch( 305 + struct psb_intel_output *psb_intel_output, 306 + u8 target) 307 + { 308 + psb_intel_sdvo_write_cmd(psb_intel_output, 309 + SDVO_CMD_SET_CONTROL_BUS_SWITCH, 310 + &target, 311 + 1); 312 + } 313 + 314 + static bool psb_intel_sdvo_set_target_input( 315 + struct psb_intel_output *psb_intel_output, 316 + bool target_0, bool target_1) 317 + { 318 + struct psb_intel_sdvo_set_target_input_args targets = { 0 }; 319 + u8 status; 320 + 321 + if (target_0 && target_1) 322 + return SDVO_CMD_STATUS_NOTSUPP; 323 + 324 + if (target_1) 325 + targets.target_1 = 1; 326 + 327 + psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_SET_TARGET_INPUT, 328 + &targets, sizeof(targets)); 329 + 330 + status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); 331 + 332 + return status == SDVO_CMD_STATUS_SUCCESS; 333 + } 334 + 335 + /** 336 + * Return whether each input is trained. 337 + * 338 + * This function is making an assumption about the layout of the response, 339 + * which should be checked against the docs. 340 + */ 341 + static bool psb_intel_sdvo_get_trained_inputs(struct psb_intel_output 342 + *psb_intel_output, bool *input_1, 343 + bool *input_2) 344 + { 345 + struct psb_intel_sdvo_get_trained_inputs_response response; 346 + u8 status; 347 + 348 + psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_GET_TRAINED_INPUTS, 349 + NULL, 0); 350 + status = 351 + psb_intel_sdvo_read_response(psb_intel_output, &response, 352 + sizeof(response)); 353 + if (status != SDVO_CMD_STATUS_SUCCESS) 354 + return false; 355 + 356 + *input_1 = response.input0_trained; 357 + *input_2 = response.input1_trained; 358 + return true; 359 + } 360 + 361 + static bool psb_intel_sdvo_get_active_outputs(struct psb_intel_output 362 + *psb_intel_output, u16 *outputs) 363 + { 364 + u8 status; 365 + 366 + psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_GET_ACTIVE_OUTPUTS, 367 + NULL, 0); 368 + status = 369 + psb_intel_sdvo_read_response(psb_intel_output, outputs, 370 + sizeof(*outputs)); 371 + 372 + return status == SDVO_CMD_STATUS_SUCCESS; 373 + } 374 + 375 + static bool psb_intel_sdvo_set_active_outputs(struct psb_intel_output 376 + *psb_intel_output, u16 outputs) 377 + { 378 + u8 status; 379 + 380 + psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_SET_ACTIVE_OUTPUTS, 381 + &outputs, sizeof(outputs)); 382 + status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); 383 + return status == SDVO_CMD_STATUS_SUCCESS; 384 + } 385 + 386 + static bool psb_intel_sdvo_set_encoder_power_state(struct psb_intel_output 387 + *psb_intel_output, int mode) 388 + { 389 + u8 status, state = SDVO_ENCODER_STATE_ON; 390 + 391 + switch (mode) { 392 + case DRM_MODE_DPMS_ON: 393 + state = SDVO_ENCODER_STATE_ON; 394 + break; 395 + case DRM_MODE_DPMS_STANDBY: 396 + state = SDVO_ENCODER_STATE_STANDBY; 397 + break; 398 + case DRM_MODE_DPMS_SUSPEND: 399 + state = SDVO_ENCODER_STATE_SUSPEND; 400 + break; 401 + case DRM_MODE_DPMS_OFF: 402 + state = SDVO_ENCODER_STATE_OFF; 403 + break; 404 + } 405 + 406 + psb_intel_sdvo_write_cmd(psb_intel_output, 407 + SDVO_CMD_SET_ENCODER_POWER_STATE, &state, 408 + sizeof(state)); 409 + status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); 410 + 411 + return status == SDVO_CMD_STATUS_SUCCESS; 412 + } 413 + 414 + static bool psb_intel_sdvo_get_input_pixel_clock_range(struct psb_intel_output 415 + *psb_intel_output, 416 + int *clock_min, 417 + int *clock_max) 418 + { 419 + struct psb_intel_sdvo_pixel_clock_range clocks; 420 + u8 status; 421 + 422 + psb_intel_sdvo_write_cmd(psb_intel_output, 423 + SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE, NULL, 424 + 0); 425 + 426 + status = 427 + psb_intel_sdvo_read_response(psb_intel_output, &clocks, 428 + sizeof(clocks)); 429 + 430 + if (status != SDVO_CMD_STATUS_SUCCESS) 431 + return false; 432 + 433 + /* Convert the values from units of 10 kHz to kHz. */ 434 + *clock_min = clocks.min * 10; 435 + *clock_max = clocks.max * 10; 436 + 437 + return true; 438 + } 439 + 440 + static bool psb_intel_sdvo_set_target_output( 441 + struct psb_intel_output *psb_intel_output, 442 + u16 outputs) 443 + { 444 + u8 status; 445 + 446 + psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_SET_TARGET_OUTPUT, 447 + &outputs, sizeof(outputs)); 448 + 449 + status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); 450 + return status == SDVO_CMD_STATUS_SUCCESS; 451 + } 452 + 453 + static bool psb_intel_sdvo_get_timing(struct psb_intel_output *psb_intel_output, 454 + u8 cmd, struct psb_intel_sdvo_dtd *dtd) 455 + { 456 + u8 status; 457 + 458 + psb_intel_sdvo_write_cmd(psb_intel_output, cmd, NULL, 0); 459 + status = psb_intel_sdvo_read_response(psb_intel_output, &dtd->part1, 460 + sizeof(dtd->part1)); 461 + if (status != SDVO_CMD_STATUS_SUCCESS) 462 + return false; 463 + 464 + psb_intel_sdvo_write_cmd(psb_intel_output, cmd + 1, NULL, 0); 465 + status = psb_intel_sdvo_read_response(psb_intel_output, &dtd->part2, 466 + sizeof(dtd->part2)); 467 + if (status != SDVO_CMD_STATUS_SUCCESS) 468 + return false; 469 + 470 + return true; 471 + } 472 + 473 + static bool psb_intel_sdvo_get_input_timing( 474 + struct psb_intel_output *psb_intel_output, 475 + struct psb_intel_sdvo_dtd *dtd) 476 + { 477 + return psb_intel_sdvo_get_timing(psb_intel_output, 478 + SDVO_CMD_GET_INPUT_TIMINGS_PART1, 479 + dtd); 480 + } 481 + 482 + static bool psb_intel_sdvo_set_timing( 483 + struct psb_intel_output *psb_intel_output, 484 + u8 cmd, 485 + struct psb_intel_sdvo_dtd *dtd) 486 + { 487 + u8 status; 488 + 489 + psb_intel_sdvo_write_cmd(psb_intel_output, cmd, &dtd->part1, 490 + sizeof(dtd->part1)); 491 + status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); 492 + if (status != SDVO_CMD_STATUS_SUCCESS) 493 + return false; 494 + 495 + psb_intel_sdvo_write_cmd(psb_intel_output, cmd + 1, &dtd->part2, 496 + sizeof(dtd->part2)); 497 + status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); 498 + if (status != SDVO_CMD_STATUS_SUCCESS) 499 + return false; 500 + 501 + return true; 502 + } 503 + 504 + static bool psb_intel_sdvo_set_input_timing( 505 + struct psb_intel_output *psb_intel_output, 506 + struct psb_intel_sdvo_dtd *dtd) 507 + { 508 + return psb_intel_sdvo_set_timing(psb_intel_output, 509 + SDVO_CMD_SET_INPUT_TIMINGS_PART1, 510 + dtd); 511 + } 512 + 513 + static bool psb_intel_sdvo_set_output_timing( 514 + struct psb_intel_output *psb_intel_output, 515 + struct psb_intel_sdvo_dtd *dtd) 516 + { 517 + return psb_intel_sdvo_set_timing(psb_intel_output, 518 + SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, 519 + dtd); 520 + } 521 + 522 + static int psb_intel_sdvo_get_clock_rate_mult(struct psb_intel_output 523 + *psb_intel_output) 524 + { 525 + u8 response, status; 526 + 527 + psb_intel_sdvo_write_cmd(psb_intel_output, 528 + SDVO_CMD_GET_CLOCK_RATE_MULT, 529 + NULL, 530 + 0); 531 + 532 + status = psb_intel_sdvo_read_response(psb_intel_output, &response, 1); 533 + 534 + if (status != SDVO_CMD_STATUS_SUCCESS) { 535 + DRM_DEBUG("Couldn't get SDVO clock rate multiplier\n"); 536 + return SDVO_CLOCK_RATE_MULT_1X; 537 + } else { 538 + DRM_DEBUG("Current clock rate multiplier: %d\n", response); 539 + } 540 + 541 + return response; 542 + } 543 + 544 + static bool psb_intel_sdvo_set_clock_rate_mult(struct psb_intel_output 545 + *psb_intel_output, u8 val) 546 + { 547 + u8 status; 548 + 549 + psb_intel_sdvo_write_cmd(psb_intel_output, 550 + SDVO_CMD_SET_CLOCK_RATE_MULT, 551 + &val, 552 + 1); 553 + 554 + status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); 555 + if (status != SDVO_CMD_STATUS_SUCCESS) 556 + return false; 557 + 558 + return true; 559 + } 560 + 561 + static bool psb_sdvo_set_current_inoutmap(struct psb_intel_output *output, 562 + u32 in0outputmask, 563 + u32 in1outputmask) 564 + { 565 + u8 byArgs[4]; 566 + u8 status; 567 + int i; 568 + struct psb_intel_sdvo_priv *sdvo_priv = output->dev_priv; 569 + 570 + /* Make all fields of the args/ret to zero */ 571 + memset(byArgs, 0, sizeof(byArgs)); 572 + 573 + /* Fill up the argument values; */ 574 + byArgs[0] = (u8) (in0outputmask & 0xFF); 575 + byArgs[1] = (u8) ((in0outputmask >> 8) & 0xFF); 576 + byArgs[2] = (u8) (in1outputmask & 0xFF); 577 + byArgs[3] = (u8) ((in1outputmask >> 8) & 0xFF); 578 + 579 + 580 + /*save inoutmap arg here*/ 581 + for (i = 0; i < 4; i++) 582 + sdvo_priv->in_out_map[i] = byArgs[0]; 583 + 584 + psb_intel_sdvo_write_cmd(output, SDVO_CMD_SET_IN_OUT_MAP, byArgs, 4); 585 + status = psb_intel_sdvo_read_response(output, NULL, 0); 586 + 587 + if (status != SDVO_CMD_STATUS_SUCCESS) 588 + return false; 589 + return true; 590 + } 591 + 592 + 593 + static void psb_intel_sdvo_set_iomap(struct psb_intel_output *output) 594 + { 595 + u32 dwCurrentSDVOIn0 = 0; 596 + u32 dwCurrentSDVOIn1 = 0; 597 + u32 dwDevMask = 0; 598 + 599 + 600 + struct psb_intel_sdvo_priv *sdvo_priv = output->dev_priv; 601 + 602 + /* Please DO NOT change the following code. */ 603 + /* SDVOB_IN0 or SDVOB_IN1 ==> sdvo_in0 */ 604 + /* SDVOC_IN0 or SDVOC_IN1 ==> sdvo_in1 */ 605 + if (sdvo_priv->by_input_wiring & (SDVOB_IN0 | SDVOC_IN0)) { 606 + switch (sdvo_priv->active_device) { 607 + case SDVO_DEVICE_LVDS: 608 + dwDevMask = SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1; 609 + break; 610 + case SDVO_DEVICE_TMDS: 611 + dwDevMask = SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1; 612 + break; 613 + case SDVO_DEVICE_TV: 614 + dwDevMask = 615 + SDVO_OUTPUT_YPRPB0 | SDVO_OUTPUT_SVID0 | 616 + SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_YPRPB1 | 617 + SDVO_OUTPUT_SVID1 | SDVO_OUTPUT_CVBS1 | 618 + SDVO_OUTPUT_SCART0 | SDVO_OUTPUT_SCART1; 619 + break; 620 + case SDVO_DEVICE_CRT: 621 + dwDevMask = SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1; 622 + break; 623 + } 624 + dwCurrentSDVOIn0 = (sdvo_priv->active_outputs & dwDevMask); 625 + } else if (sdvo_priv->by_input_wiring & (SDVOB_IN1 | SDVOC_IN1)) { 626 + switch (sdvo_priv->active_device) { 627 + case SDVO_DEVICE_LVDS: 628 + dwDevMask = SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1; 629 + break; 630 + case SDVO_DEVICE_TMDS: 631 + dwDevMask = SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1; 632 + break; 633 + case SDVO_DEVICE_TV: 634 + dwDevMask = 635 + SDVO_OUTPUT_YPRPB0 | SDVO_OUTPUT_SVID0 | 636 + SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_YPRPB1 | 637 + SDVO_OUTPUT_SVID1 | SDVO_OUTPUT_CVBS1 | 638 + SDVO_OUTPUT_SCART0 | SDVO_OUTPUT_SCART1; 639 + break; 640 + case SDVO_DEVICE_CRT: 641 + dwDevMask = SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1; 642 + break; 643 + } 644 + dwCurrentSDVOIn1 = (sdvo_priv->active_outputs & dwDevMask); 645 + } 646 + 647 + psb_sdvo_set_current_inoutmap(output, dwCurrentSDVOIn0, 648 + dwCurrentSDVOIn1); 649 + } 650 + 651 + 652 + static bool psb_intel_sdvo_mode_fixup(struct drm_encoder *encoder, 653 + struct drm_display_mode *mode, 654 + struct drm_display_mode *adjusted_mode) 655 + { 656 + /* Make the CRTC code factor in the SDVO pixel multiplier. The SDVO 657 + * device will be told of the multiplier during mode_set. 658 + */ 659 + adjusted_mode->clock *= psb_intel_sdvo_get_pixel_multiplier(mode); 660 + return true; 661 + } 662 + 663 + static void psb_intel_sdvo_mode_set(struct drm_encoder *encoder, 664 + struct drm_display_mode *mode, 665 + struct drm_display_mode *adjusted_mode) 666 + { 667 + struct drm_device *dev = encoder->dev; 668 + struct drm_crtc *crtc = encoder->crtc; 669 + struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 670 + struct psb_intel_output *psb_intel_output = 671 + enc_to_psb_intel_output(encoder); 672 + struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; 673 + u16 width, height; 674 + u16 h_blank_len, h_sync_len, v_blank_len, v_sync_len; 675 + u16 h_sync_offset, v_sync_offset; 676 + u32 sdvox; 677 + struct psb_intel_sdvo_dtd output_dtd; 678 + int sdvo_pixel_multiply; 679 + 680 + if (!mode) 681 + return; 682 + 683 + psb_intel_sdvo_set_target_output(psb_intel_output, 0); 684 + 685 + width = mode->crtc_hdisplay; 686 + height = mode->crtc_vdisplay; 687 + 688 + /* do some mode translations */ 689 + h_blank_len = mode->crtc_hblank_end - mode->crtc_hblank_start; 690 + h_sync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 691 + 692 + v_blank_len = mode->crtc_vblank_end - mode->crtc_vblank_start; 693 + v_sync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; 694 + 695 + h_sync_offset = mode->crtc_hsync_start - mode->crtc_hblank_start; 696 + v_sync_offset = mode->crtc_vsync_start - mode->crtc_vblank_start; 697 + 698 + output_dtd.part1.clock = mode->clock / 10; 699 + output_dtd.part1.h_active = width & 0xff; 700 + output_dtd.part1.h_blank = h_blank_len & 0xff; 701 + output_dtd.part1.h_high = (((width >> 8) & 0xf) << 4) | 702 + ((h_blank_len >> 8) & 0xf); 703 + output_dtd.part1.v_active = height & 0xff; 704 + output_dtd.part1.v_blank = v_blank_len & 0xff; 705 + output_dtd.part1.v_high = (((height >> 8) & 0xf) << 4) | 706 + ((v_blank_len >> 8) & 0xf); 707 + 708 + output_dtd.part2.h_sync_off = h_sync_offset; 709 + output_dtd.part2.h_sync_width = h_sync_len & 0xff; 710 + output_dtd.part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 | 711 + (v_sync_len & 0xf); 712 + output_dtd.part2.sync_off_width_high = 713 + ((h_sync_offset & 0x300) >> 2) | ((h_sync_len & 0x300) >> 4) | 714 + ((v_sync_offset & 0x30) >> 2) | ((v_sync_len & 0x30) >> 4); 715 + 716 + output_dtd.part2.dtd_flags = 0x18; 717 + if (mode->flags & DRM_MODE_FLAG_PHSYNC) 718 + output_dtd.part2.dtd_flags |= 0x2; 719 + if (mode->flags & DRM_MODE_FLAG_PVSYNC) 720 + output_dtd.part2.dtd_flags |= 0x4; 721 + 722 + output_dtd.part2.sdvo_flags = 0; 723 + output_dtd.part2.v_sync_off_high = v_sync_offset & 0xc0; 724 + output_dtd.part2.reserved = 0; 725 + 726 + /* Set the output timing to the screen */ 727 + psb_intel_sdvo_set_target_output(psb_intel_output, 728 + sdvo_priv->active_outputs); 729 + 730 + /* Set the input timing to the screen. Assume always input 0. */ 731 + psb_intel_sdvo_set_target_input(psb_intel_output, true, false); 732 + 733 + psb_intel_sdvo_set_output_timing(psb_intel_output, &output_dtd); 734 + 735 + /* We would like to use i830_sdvo_create_preferred_input_timing() to 736 + * provide the device with a timing it can support, if it supports that 737 + * feature. However, presumably we would need to adjust the CRTC to 738 + * output the preferred timing, and we don't support that currently. 739 + */ 740 + psb_intel_sdvo_set_input_timing(psb_intel_output, &output_dtd); 741 + 742 + switch (psb_intel_sdvo_get_pixel_multiplier(mode)) { 743 + case 1: 744 + psb_intel_sdvo_set_clock_rate_mult(psb_intel_output, 745 + SDVO_CLOCK_RATE_MULT_1X); 746 + break; 747 + case 2: 748 + psb_intel_sdvo_set_clock_rate_mult(psb_intel_output, 749 + SDVO_CLOCK_RATE_MULT_2X); 750 + break; 751 + case 4: 752 + psb_intel_sdvo_set_clock_rate_mult(psb_intel_output, 753 + SDVO_CLOCK_RATE_MULT_4X); 754 + break; 755 + } 756 + 757 + /* Set the SDVO control regs. */ 758 + sdvox = REG_READ(sdvo_priv->output_device); 759 + switch (sdvo_priv->output_device) { 760 + case SDVOB: 761 + sdvox &= SDVOB_PRESERVE_MASK; 762 + break; 763 + case SDVOC: 764 + sdvox &= SDVOC_PRESERVE_MASK; 765 + break; 766 + } 767 + sdvox |= (9 << 19) | SDVO_BORDER_ENABLE; 768 + if (psb_intel_crtc->pipe == 1) 769 + sdvox |= SDVO_PIPE_B_SELECT; 770 + 771 + sdvo_pixel_multiply = psb_intel_sdvo_get_pixel_multiplier(mode); 772 + 773 + psb_intel_sdvo_write_sdvox(psb_intel_output, sdvox); 774 + 775 + psb_intel_sdvo_set_iomap(psb_intel_output); 776 + } 777 + 778 + static void psb_intel_sdvo_dpms(struct drm_encoder *encoder, int mode) 779 + { 780 + struct drm_device *dev = encoder->dev; 781 + struct psb_intel_output *psb_intel_output = 782 + enc_to_psb_intel_output(encoder); 783 + struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; 784 + u32 temp; 785 + 786 + if (mode != DRM_MODE_DPMS_ON) { 787 + psb_intel_sdvo_set_active_outputs(psb_intel_output, 0); 788 + if (0) 789 + psb_intel_sdvo_set_encoder_power_state( 790 + psb_intel_output, 791 + mode); 792 + 793 + if (mode == DRM_MODE_DPMS_OFF) { 794 + temp = REG_READ(sdvo_priv->output_device); 795 + if ((temp & SDVO_ENABLE) != 0) { 796 + psb_intel_sdvo_write_sdvox(psb_intel_output, 797 + temp & 798 + ~SDVO_ENABLE); 799 + } 800 + } 801 + } else { 802 + bool input1, input2; 803 + int i; 804 + u8 status; 805 + 806 + temp = REG_READ(sdvo_priv->output_device); 807 + if ((temp & SDVO_ENABLE) == 0) 808 + psb_intel_sdvo_write_sdvox(psb_intel_output, 809 + temp | SDVO_ENABLE); 810 + for (i = 0; i < 2; i++) 811 + psb_intel_wait_for_vblank(dev); 812 + 813 + status = 814 + psb_intel_sdvo_get_trained_inputs(psb_intel_output, 815 + &input1, 816 + &input2); 817 + 818 + 819 + /* Warn if the device reported failure to sync. 820 + * A lot of SDVO devices fail to notify of sync, but it's 821 + * a given it the status is a success, we succeeded. 822 + */ 823 + if (status == SDVO_CMD_STATUS_SUCCESS && !input1) { 824 + DRM_DEBUG 825 + ("First %s output reported failure to sync\n", 826 + SDVO_NAME(sdvo_priv)); 827 + } 828 + 829 + if (0) 830 + psb_intel_sdvo_set_encoder_power_state( 831 + psb_intel_output, 832 + mode); 833 + psb_intel_sdvo_set_active_outputs(psb_intel_output, 834 + sdvo_priv->active_outputs); 835 + } 836 + return; 837 + } 838 + 839 + static void psb_intel_sdvo_save(struct drm_connector *connector) 840 + { 841 + struct drm_device *dev = connector->dev; 842 + struct psb_intel_output *psb_intel_output = 843 + to_psb_intel_output(connector); 844 + struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; 845 + /*int o;*/ 846 + 847 + sdvo_priv->save_sdvo_mult = 848 + psb_intel_sdvo_get_clock_rate_mult(psb_intel_output); 849 + psb_intel_sdvo_get_active_outputs(psb_intel_output, 850 + &sdvo_priv->save_active_outputs); 851 + 852 + if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) { 853 + psb_intel_sdvo_set_target_input(psb_intel_output, 854 + true, 855 + false); 856 + psb_intel_sdvo_get_input_timing(psb_intel_output, 857 + &sdvo_priv->save_input_dtd_1); 858 + } 859 + 860 + if (sdvo_priv->caps.sdvo_inputs_mask & 0x2) { 861 + psb_intel_sdvo_set_target_input(psb_intel_output, 862 + false, 863 + true); 864 + psb_intel_sdvo_get_input_timing(psb_intel_output, 865 + &sdvo_priv->save_input_dtd_2); 866 + } 867 + sdvo_priv->save_SDVOX = REG_READ(sdvo_priv->output_device); 868 + 869 + /*TODO: save the in_out_map state*/ 870 + } 871 + 872 + static void psb_intel_sdvo_restore(struct drm_connector *connector) 873 + { 874 + struct drm_device *dev = connector->dev; 875 + struct psb_intel_output *psb_intel_output = 876 + to_psb_intel_output(connector); 877 + struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; 878 + /*int o;*/ 879 + int i; 880 + bool input1, input2; 881 + u8 status; 882 + 883 + psb_intel_sdvo_set_active_outputs(psb_intel_output, 0); 884 + 885 + if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) { 886 + psb_intel_sdvo_set_target_input(psb_intel_output, true, false); 887 + psb_intel_sdvo_set_input_timing(psb_intel_output, 888 + &sdvo_priv->save_input_dtd_1); 889 + } 890 + 891 + if (sdvo_priv->caps.sdvo_inputs_mask & 0x2) { 892 + psb_intel_sdvo_set_target_input(psb_intel_output, false, true); 893 + psb_intel_sdvo_set_input_timing(psb_intel_output, 894 + &sdvo_priv->save_input_dtd_2); 895 + } 896 + 897 + psb_intel_sdvo_set_clock_rate_mult(psb_intel_output, 898 + sdvo_priv->save_sdvo_mult); 899 + 900 + REG_WRITE(sdvo_priv->output_device, sdvo_priv->save_SDVOX); 901 + 902 + if (sdvo_priv->save_SDVOX & SDVO_ENABLE) { 903 + for (i = 0; i < 2; i++) 904 + psb_intel_wait_for_vblank(dev); 905 + status = 906 + psb_intel_sdvo_get_trained_inputs(psb_intel_output, 907 + &input1, 908 + &input2); 909 + if (status == SDVO_CMD_STATUS_SUCCESS && !input1) 910 + DRM_DEBUG 911 + ("First %s output reported failure to sync\n", 912 + SDVO_NAME(sdvo_priv)); 913 + } 914 + 915 + psb_intel_sdvo_set_active_outputs(psb_intel_output, 916 + sdvo_priv->save_active_outputs); 917 + 918 + /*TODO: restore in_out_map*/ 919 + psb_intel_sdvo_write_cmd(psb_intel_output, 920 + SDVO_CMD_SET_IN_OUT_MAP, 921 + sdvo_priv->in_out_map, 922 + 4); 923 + 924 + psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); 925 + } 926 + 927 + static int psb_intel_sdvo_mode_valid(struct drm_connector *connector, 928 + struct drm_display_mode *mode) 929 + { 930 + struct psb_intel_output *psb_intel_output = 931 + to_psb_intel_output(connector); 932 + struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; 933 + 934 + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) 935 + return MODE_NO_DBLESCAN; 936 + 937 + if (sdvo_priv->pixel_clock_min > mode->clock) 938 + return MODE_CLOCK_LOW; 939 + 940 + if (sdvo_priv->pixel_clock_max < mode->clock) 941 + return MODE_CLOCK_HIGH; 942 + 943 + return MODE_OK; 944 + } 945 + 946 + static bool psb_intel_sdvo_get_capabilities( 947 + struct psb_intel_output *psb_intel_output, 948 + struct psb_intel_sdvo_caps *caps) 949 + { 950 + u8 status; 951 + 952 + psb_intel_sdvo_write_cmd(psb_intel_output, 953 + SDVO_CMD_GET_DEVICE_CAPS, 954 + NULL, 955 + 0); 956 + status = psb_intel_sdvo_read_response(psb_intel_output, 957 + caps, 958 + sizeof(*caps)); 959 + if (status != SDVO_CMD_STATUS_SUCCESS) 960 + return false; 961 + 962 + return true; 963 + } 964 + 965 + struct drm_connector *psb_intel_sdvo_find(struct drm_device *dev, int sdvoB) 966 + { 967 + struct drm_connector *connector = NULL; 968 + struct psb_intel_output *iout = NULL; 969 + struct psb_intel_sdvo_priv *sdvo; 970 + 971 + /* find the sdvo connector */ 972 + list_for_each_entry(connector, &dev->mode_config.connector_list, 973 + head) { 974 + iout = to_psb_intel_output(connector); 975 + 976 + if (iout->type != INTEL_OUTPUT_SDVO) 977 + continue; 978 + 979 + sdvo = iout->dev_priv; 980 + 981 + if (sdvo->output_device == SDVOB && sdvoB) 982 + return connector; 983 + 984 + if (sdvo->output_device == SDVOC && !sdvoB) 985 + return connector; 986 + 987 + } 988 + 989 + return NULL; 990 + } 991 + 992 + int psb_intel_sdvo_supports_hotplug(struct drm_connector *connector) 993 + { 994 + u8 response[2]; 995 + u8 status; 996 + struct psb_intel_output *psb_intel_output; 997 + 998 + if (!connector) 999 + return 0; 1000 + 1001 + psb_intel_output = to_psb_intel_output(connector); 1002 + 1003 + psb_intel_sdvo_write_cmd(psb_intel_output, 1004 + SDVO_CMD_GET_HOT_PLUG_SUPPORT, 1005 + NULL, 1006 + 0); 1007 + status = psb_intel_sdvo_read_response(psb_intel_output, 1008 + &response, 1009 + 2); 1010 + 1011 + if (response[0] != 0) 1012 + return 1; 1013 + 1014 + return 0; 1015 + } 1016 + 1017 + void psb_intel_sdvo_set_hotplug(struct drm_connector *connector, int on) 1018 + { 1019 + u8 response[2]; 1020 + u8 status; 1021 + struct psb_intel_output *psb_intel_output = 1022 + to_psb_intel_output(connector); 1023 + 1024 + psb_intel_sdvo_write_cmd(psb_intel_output, 1025 + SDVO_CMD_GET_ACTIVE_HOT_PLUG, 1026 + NULL, 1027 + 0); 1028 + psb_intel_sdvo_read_response(psb_intel_output, &response, 2); 1029 + 1030 + if (on) { 1031 + psb_intel_sdvo_write_cmd(psb_intel_output, 1032 + SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, 1033 + 0); 1034 + status = psb_intel_sdvo_read_response(psb_intel_output, 1035 + &response, 1036 + 2); 1037 + 1038 + psb_intel_sdvo_write_cmd(psb_intel_output, 1039 + SDVO_CMD_SET_ACTIVE_HOT_PLUG, 1040 + &response, 2); 1041 + } else { 1042 + response[0] = 0; 1043 + response[1] = 0; 1044 + psb_intel_sdvo_write_cmd(psb_intel_output, 1045 + SDVO_CMD_SET_ACTIVE_HOT_PLUG, 1046 + &response, 2); 1047 + } 1048 + 1049 + psb_intel_sdvo_write_cmd(psb_intel_output, 1050 + SDVO_CMD_GET_ACTIVE_HOT_PLUG, 1051 + NULL, 1052 + 0); 1053 + psb_intel_sdvo_read_response(psb_intel_output, &response, 2); 1054 + } 1055 + 1056 + static enum drm_connector_status psb_intel_sdvo_detect(struct drm_connector 1057 + *connector, bool force) 1058 + { 1059 + u8 response[2]; 1060 + u8 status; 1061 + struct psb_intel_output *psb_intel_output = 1062 + to_psb_intel_output(connector); 1063 + 1064 + psb_intel_sdvo_write_cmd(psb_intel_output, 1065 + SDVO_CMD_GET_ATTACHED_DISPLAYS, 1066 + NULL, 1067 + 0); 1068 + status = psb_intel_sdvo_read_response(psb_intel_output, &response, 2); 1069 + 1070 + DRM_DEBUG("SDVO response %d %d\n", response[0], response[1]); 1071 + if ((response[0] != 0) || (response[1] != 0)) 1072 + return connector_status_connected; 1073 + else 1074 + return connector_status_disconnected; 1075 + } 1076 + 1077 + static int psb_intel_sdvo_get_modes(struct drm_connector *connector) 1078 + { 1079 + struct psb_intel_output *psb_intel_output = 1080 + to_psb_intel_output(connector); 1081 + 1082 + /* set the bus switch and get the modes */ 1083 + psb_intel_sdvo_set_control_bus_switch(psb_intel_output, 1084 + SDVO_CONTROL_BUS_DDC2); 1085 + psb_intel_ddc_get_modes(psb_intel_output); 1086 + 1087 + if (list_empty(&connector->probed_modes)) 1088 + return 0; 1089 + return 1; 1090 + } 1091 + 1092 + static void psb_intel_sdvo_destroy(struct drm_connector *connector) 1093 + { 1094 + struct psb_intel_output *psb_intel_output = 1095 + to_psb_intel_output(connector); 1096 + 1097 + if (psb_intel_output->i2c_bus) 1098 + psb_intel_i2c_destroy(psb_intel_output->i2c_bus); 1099 + drm_sysfs_connector_remove(connector); 1100 + drm_connector_cleanup(connector); 1101 + kfree(psb_intel_output); 1102 + } 1103 + 1104 + static const struct drm_encoder_helper_funcs psb_intel_sdvo_helper_funcs = { 1105 + .dpms = psb_intel_sdvo_dpms, 1106 + .mode_fixup = psb_intel_sdvo_mode_fixup, 1107 + .prepare = psb_intel_encoder_prepare, 1108 + .mode_set = psb_intel_sdvo_mode_set, 1109 + .commit = psb_intel_encoder_commit, 1110 + }; 1111 + 1112 + static const struct drm_connector_funcs psb_intel_sdvo_connector_funcs = { 1113 + .dpms = drm_helper_connector_dpms, 1114 + .save = psb_intel_sdvo_save, 1115 + .restore = psb_intel_sdvo_restore, 1116 + .detect = psb_intel_sdvo_detect, 1117 + .fill_modes = drm_helper_probe_single_connector_modes, 1118 + .destroy = psb_intel_sdvo_destroy, 1119 + }; 1120 + 1121 + static const struct drm_connector_helper_funcs 1122 + psb_intel_sdvo_connector_helper_funcs = { 1123 + .get_modes = psb_intel_sdvo_get_modes, 1124 + .mode_valid = psb_intel_sdvo_mode_valid, 1125 + .best_encoder = psb_intel_best_encoder, 1126 + }; 1127 + 1128 + void psb_intel_sdvo_enc_destroy(struct drm_encoder *encoder) 1129 + { 1130 + drm_encoder_cleanup(encoder); 1131 + } 1132 + 1133 + static const struct drm_encoder_funcs psb_intel_sdvo_enc_funcs = { 1134 + .destroy = psb_intel_sdvo_enc_destroy, 1135 + }; 1136 + 1137 + 1138 + void psb_intel_sdvo_init(struct drm_device *dev, int output_device) 1139 + { 1140 + struct drm_connector *connector; 1141 + struct psb_intel_output *psb_intel_output; 1142 + struct psb_intel_sdvo_priv *sdvo_priv; 1143 + struct psb_intel_i2c_chan *i2cbus = NULL; 1144 + int connector_type; 1145 + u8 ch[0x40]; 1146 + int i; 1147 + int encoder_type, output_id; 1148 + 1149 + psb_intel_output = 1150 + kcalloc(sizeof(struct psb_intel_output) + 1151 + sizeof(struct psb_intel_sdvo_priv), 1, GFP_KERNEL); 1152 + if (!psb_intel_output) 1153 + return; 1154 + 1155 + connector = &psb_intel_output->base; 1156 + 1157 + drm_connector_init(dev, connector, &psb_intel_sdvo_connector_funcs, 1158 + DRM_MODE_CONNECTOR_Unknown); 1159 + drm_connector_helper_add(connector, 1160 + &psb_intel_sdvo_connector_helper_funcs); 1161 + sdvo_priv = (struct psb_intel_sdvo_priv *) (psb_intel_output + 1); 1162 + psb_intel_output->type = INTEL_OUTPUT_SDVO; 1163 + 1164 + connector->interlace_allowed = 0; 1165 + connector->doublescan_allowed = 0; 1166 + 1167 + /* setup the DDC bus. */ 1168 + if (output_device == SDVOB) 1169 + i2cbus = 1170 + psb_intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB"); 1171 + else 1172 + i2cbus = 1173 + psb_intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC"); 1174 + 1175 + if (!i2cbus) 1176 + goto err_connector; 1177 + 1178 + sdvo_priv->i2c_bus = i2cbus; 1179 + 1180 + if (output_device == SDVOB) { 1181 + output_id = 1; 1182 + sdvo_priv->by_input_wiring = SDVOB_IN0; 1183 + sdvo_priv->i2c_bus->slave_addr = 0x38; 1184 + } else { 1185 + output_id = 2; 1186 + sdvo_priv->i2c_bus->slave_addr = 0x39; 1187 + } 1188 + 1189 + sdvo_priv->output_device = output_device; 1190 + psb_intel_output->i2c_bus = i2cbus; 1191 + psb_intel_output->dev_priv = sdvo_priv; 1192 + 1193 + 1194 + /* Read the regs to test if we can talk to the device */ 1195 + for (i = 0; i < 0x40; i++) { 1196 + if (!psb_intel_sdvo_read_byte(psb_intel_output, i, &ch[i])) { 1197 + dev_dbg(dev->dev, "No SDVO device found on SDVO%c\n", 1198 + output_device == SDVOB ? 'B' : 'C'); 1199 + goto err_i2c; 1200 + } 1201 + } 1202 + 1203 + psb_intel_sdvo_get_capabilities(psb_intel_output, &sdvo_priv->caps); 1204 + 1205 + memset(&sdvo_priv->active_outputs, 0, 1206 + sizeof(sdvo_priv->active_outputs)); 1207 + 1208 + /* TODO, CVBS, SVID, YPRPB & SCART outputs. */ 1209 + if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB0) { 1210 + sdvo_priv->active_outputs = SDVO_OUTPUT_RGB0; 1211 + sdvo_priv->active_device = SDVO_DEVICE_CRT; 1212 + connector->display_info.subpixel_order = 1213 + SubPixelHorizontalRGB; 1214 + encoder_type = DRM_MODE_ENCODER_DAC; 1215 + connector_type = DRM_MODE_CONNECTOR_VGA; 1216 + } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1) { 1217 + sdvo_priv->active_outputs = SDVO_OUTPUT_RGB1; 1218 + sdvo_priv->active_outputs = SDVO_DEVICE_CRT; 1219 + connector->display_info.subpixel_order = 1220 + SubPixelHorizontalRGB; 1221 + encoder_type = DRM_MODE_ENCODER_DAC; 1222 + connector_type = DRM_MODE_CONNECTOR_VGA; 1223 + } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) { 1224 + sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS0; 1225 + sdvo_priv->active_device = SDVO_DEVICE_TMDS; 1226 + connector->display_info.subpixel_order = 1227 + SubPixelHorizontalRGB; 1228 + encoder_type = DRM_MODE_ENCODER_TMDS; 1229 + connector_type = DRM_MODE_CONNECTOR_DVID; 1230 + } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS1) { 1231 + sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS1; 1232 + sdvo_priv->active_device = SDVO_DEVICE_TMDS; 1233 + connector->display_info.subpixel_order = 1234 + SubPixelHorizontalRGB; 1235 + encoder_type = DRM_MODE_ENCODER_TMDS; 1236 + connector_type = DRM_MODE_CONNECTOR_DVID; 1237 + } else { 1238 + unsigned char bytes[2]; 1239 + 1240 + memcpy(bytes, &sdvo_priv->caps.output_flags, 2); 1241 + dev_dbg(dev->dev, "%s: No active RGB or TMDS outputs (0x%02x%02x)\n", 1242 + SDVO_NAME(sdvo_priv), bytes[0], bytes[1]); 1243 + goto err_i2c; 1244 + } 1245 + 1246 + drm_encoder_init(dev, &psb_intel_output->enc, &psb_intel_sdvo_enc_funcs, 1247 + encoder_type); 1248 + drm_encoder_helper_add(&psb_intel_output->enc, 1249 + &psb_intel_sdvo_helper_funcs); 1250 + connector->connector_type = connector_type; 1251 + 1252 + drm_mode_connector_attach_encoder(&psb_intel_output->base, 1253 + &psb_intel_output->enc); 1254 + drm_sysfs_connector_add(connector); 1255 + 1256 + /* Set the input timing to the screen. Assume always input 0. */ 1257 + psb_intel_sdvo_set_target_input(psb_intel_output, true, false); 1258 + 1259 + psb_intel_sdvo_get_input_pixel_clock_range(psb_intel_output, 1260 + &sdvo_priv->pixel_clock_min, 1261 + &sdvo_priv-> 1262 + pixel_clock_max); 1263 + 1264 + 1265 + dev_dbg(dev->dev, "%s device VID/DID: %02X:%02X.%02X, " 1266 + "clock range %dMHz - %dMHz, " 1267 + "input 1: %c, input 2: %c, " 1268 + "output 1: %c, output 2: %c\n", 1269 + SDVO_NAME(sdvo_priv), 1270 + sdvo_priv->caps.vendor_id, sdvo_priv->caps.device_id, 1271 + sdvo_priv->caps.device_rev_id, 1272 + sdvo_priv->pixel_clock_min / 1000, 1273 + sdvo_priv->pixel_clock_max / 1000, 1274 + (sdvo_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N', 1275 + (sdvo_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N', 1276 + /* check currently supported outputs */ 1277 + sdvo_priv->caps.output_flags & 1278 + (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_RGB0) ? 'Y' : 'N', 1279 + sdvo_priv->caps.output_flags & 1280 + (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N'); 1281 + 1282 + psb_intel_output->ddc_bus = i2cbus; 1283 + 1284 + return; 1285 + 1286 + err_i2c: 1287 + psb_intel_i2c_destroy(psb_intel_output->i2c_bus); 1288 + err_connector: 1289 + drm_connector_cleanup(connector); 1290 + kfree(psb_intel_output); 1291 + 1292 + return; 1293 + }
+338
drivers/gpu/drm/gma500/psb_intel_sdvo_regs.h
··· 1 + /* 2 + * SDVO command definitions and structures. 3 + * 4 + * Copyright (c) 2008, Intel Corporation 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms and conditions of the GNU General Public License, 8 + * version 2, as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope it will be useful, but WITHOUT 11 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 + * more details. 14 + * 15 + * You should have received a copy of the GNU General Public License along with 16 + * this program; if not, write to the Free Software Foundation, Inc., 17 + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 18 + * 19 + * Authors: 20 + * Eric Anholt <eric@anholt.net> 21 + */ 22 + 23 + #define SDVO_OUTPUT_FIRST (0) 24 + #define SDVO_OUTPUT_TMDS0 (1 << 0) 25 + #define SDVO_OUTPUT_RGB0 (1 << 1) 26 + #define SDVO_OUTPUT_CVBS0 (1 << 2) 27 + #define SDVO_OUTPUT_SVID0 (1 << 3) 28 + #define SDVO_OUTPUT_YPRPB0 (1 << 4) 29 + #define SDVO_OUTPUT_SCART0 (1 << 5) 30 + #define SDVO_OUTPUT_LVDS0 (1 << 6) 31 + #define SDVO_OUTPUT_TMDS1 (1 << 8) 32 + #define SDVO_OUTPUT_RGB1 (1 << 9) 33 + #define SDVO_OUTPUT_CVBS1 (1 << 10) 34 + #define SDVO_OUTPUT_SVID1 (1 << 11) 35 + #define SDVO_OUTPUT_YPRPB1 (1 << 12) 36 + #define SDVO_OUTPUT_SCART1 (1 << 13) 37 + #define SDVO_OUTPUT_LVDS1 (1 << 14) 38 + #define SDVO_OUTPUT_LAST (14) 39 + 40 + struct psb_intel_sdvo_caps { 41 + u8 vendor_id; 42 + u8 device_id; 43 + u8 device_rev_id; 44 + u8 sdvo_version_major; 45 + u8 sdvo_version_minor; 46 + unsigned int sdvo_inputs_mask:2; 47 + unsigned int smooth_scaling:1; 48 + unsigned int sharp_scaling:1; 49 + unsigned int up_scaling:1; 50 + unsigned int down_scaling:1; 51 + unsigned int stall_support:1; 52 + unsigned int pad:1; 53 + u16 output_flags; 54 + } __packed; 55 + 56 + /** This matches the EDID DTD structure, more or less */ 57 + struct psb_intel_sdvo_dtd { 58 + struct { 59 + u16 clock; /**< pixel clock, in 10kHz units */ 60 + u8 h_active; /**< lower 8 bits (pixels) */ 61 + u8 h_blank; /**< lower 8 bits (pixels) */ 62 + u8 h_high; /**< upper 4 bits each h_active, h_blank */ 63 + u8 v_active; /**< lower 8 bits (lines) */ 64 + u8 v_blank; /**< lower 8 bits (lines) */ 65 + u8 v_high; /**< upper 4 bits each v_active, v_blank */ 66 + } part1; 67 + 68 + struct { 69 + u8 h_sync_off; 70 + /**< lower 8 bits, from hblank start */ 71 + u8 h_sync_width;/**< lower 8 bits (pixels) */ 72 + /** lower 4 bits each vsync offset, vsync width */ 73 + u8 v_sync_off_width; 74 + /** 75 + * 2 high bits of hsync offset, 2 high bits of hsync width, 76 + * bits 4-5 of vsync offset, and 2 high bits of vsync width. 77 + */ 78 + u8 sync_off_width_high; 79 + u8 dtd_flags; 80 + u8 sdvo_flags; 81 + /** bits 6-7 of vsync offset at bits 6-7 */ 82 + u8 v_sync_off_high; 83 + u8 reserved; 84 + } part2; 85 + } __packed; 86 + 87 + struct psb_intel_sdvo_pixel_clock_range { 88 + u16 min; /**< pixel clock, in 10kHz units */ 89 + u16 max; /**< pixel clock, in 10kHz units */ 90 + } __packed; 91 + 92 + struct psb_intel_sdvo_preferred_input_timing_args { 93 + u16 clock; 94 + u16 width; 95 + u16 height; 96 + } __packed; 97 + 98 + /* I2C registers for SDVO */ 99 + #define SDVO_I2C_ARG_0 0x07 100 + #define SDVO_I2C_ARG_1 0x06 101 + #define SDVO_I2C_ARG_2 0x05 102 + #define SDVO_I2C_ARG_3 0x04 103 + #define SDVO_I2C_ARG_4 0x03 104 + #define SDVO_I2C_ARG_5 0x02 105 + #define SDVO_I2C_ARG_6 0x01 106 + #define SDVO_I2C_ARG_7 0x00 107 + #define SDVO_I2C_OPCODE 0x08 108 + #define SDVO_I2C_CMD_STATUS 0x09 109 + #define SDVO_I2C_RETURN_0 0x0a 110 + #define SDVO_I2C_RETURN_1 0x0b 111 + #define SDVO_I2C_RETURN_2 0x0c 112 + #define SDVO_I2C_RETURN_3 0x0d 113 + #define SDVO_I2C_RETURN_4 0x0e 114 + #define SDVO_I2C_RETURN_5 0x0f 115 + #define SDVO_I2C_RETURN_6 0x10 116 + #define SDVO_I2C_RETURN_7 0x11 117 + #define SDVO_I2C_VENDOR_BEGIN 0x20 118 + 119 + /* Status results */ 120 + #define SDVO_CMD_STATUS_POWER_ON 0x0 121 + #define SDVO_CMD_STATUS_SUCCESS 0x1 122 + #define SDVO_CMD_STATUS_NOTSUPP 0x2 123 + #define SDVO_CMD_STATUS_INVALID_ARG 0x3 124 + #define SDVO_CMD_STATUS_PENDING 0x4 125 + #define SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED 0x5 126 + #define SDVO_CMD_STATUS_SCALING_NOT_SUPP 0x6 127 + 128 + /* SDVO commands, argument/result registers */ 129 + 130 + #define SDVO_CMD_RESET 0x01 131 + 132 + /** Returns a struct psb_intel_sdvo_caps */ 133 + #define SDVO_CMD_GET_DEVICE_CAPS 0x02 134 + 135 + #define SDVO_CMD_GET_FIRMWARE_REV 0x86 136 + # define SDVO_DEVICE_FIRMWARE_MINOR SDVO_I2C_RETURN_0 137 + # define SDVO_DEVICE_FIRMWARE_MAJOR SDVO_I2C_RETURN_1 138 + # define SDVO_DEVICE_FIRMWARE_PATCH SDVO_I2C_RETURN_2 139 + 140 + /** 141 + * Reports which inputs are trained (managed to sync). 142 + * 143 + * Devices must have trained within 2 vsyncs of a mode change. 144 + */ 145 + #define SDVO_CMD_GET_TRAINED_INPUTS 0x03 146 + struct psb_intel_sdvo_get_trained_inputs_response { 147 + unsigned int input0_trained:1; 148 + unsigned int input1_trained:1; 149 + unsigned int pad:6; 150 + } __packed; 151 + 152 + /** Returns a struct psb_intel_sdvo_output_flags of active outputs. */ 153 + #define SDVO_CMD_GET_ACTIVE_OUTPUTS 0x04 154 + 155 + /** 156 + * Sets the current set of active outputs. 157 + * 158 + * Takes a struct psb_intel_sdvo_output_flags. 159 + * Must be preceded by a SET_IN_OUT_MAP 160 + * on multi-output devices. 161 + */ 162 + #define SDVO_CMD_SET_ACTIVE_OUTPUTS 0x05 163 + 164 + /** 165 + * Returns the current mapping of SDVO inputs to outputs on the device. 166 + * 167 + * Returns two struct psb_intel_sdvo_output_flags structures. 168 + */ 169 + #define SDVO_CMD_GET_IN_OUT_MAP 0x06 170 + 171 + /** 172 + * Sets the current mapping of SDVO inputs to outputs on the device. 173 + * 174 + * Takes two struct i380_sdvo_output_flags structures. 175 + */ 176 + #define SDVO_CMD_SET_IN_OUT_MAP 0x07 177 + 178 + /** 179 + * Returns a struct psb_intel_sdvo_output_flags of attached displays. 180 + */ 181 + #define SDVO_CMD_GET_ATTACHED_DISPLAYS 0x0b 182 + 183 + /** 184 + * Returns a struct psb_intel_sdvo_ouptut_flags of displays supporting hot plugging. 185 + */ 186 + #define SDVO_CMD_GET_HOT_PLUG_SUPPORT 0x0c 187 + 188 + /** 189 + * Takes a struct psb_intel_sdvo_output_flags. 190 + */ 191 + #define SDVO_CMD_SET_ACTIVE_HOT_PLUG 0x0d 192 + 193 + /** 194 + * Returns a struct psb_intel_sdvo_output_flags of displays with hot plug 195 + * interrupts enabled. 196 + */ 197 + #define SDVO_CMD_GET_ACTIVE_HOT_PLUG 0x0e 198 + 199 + #define SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE 0x0f 200 + struct psb_intel_sdvo_get_interrupt_event_source_response { 201 + u16 interrupt_status; 202 + unsigned int ambient_light_interrupt:1; 203 + unsigned int pad:7; 204 + } __packed; 205 + 206 + /** 207 + * Selects which input is affected by future input commands. 208 + * 209 + * Commands affected include SET_INPUT_TIMINGS_PART[12], 210 + * GET_INPUT_TIMINGS_PART[12], GET_PREFERRED_INPUT_TIMINGS_PART[12], 211 + * GET_INPUT_PIXEL_CLOCK_RANGE, and CREATE_PREFERRED_INPUT_TIMINGS. 212 + */ 213 + #define SDVO_CMD_SET_TARGET_INPUT 0x10 214 + struct psb_intel_sdvo_set_target_input_args { 215 + unsigned int target_1:1; 216 + unsigned int pad:7; 217 + } __packed; 218 + 219 + /** 220 + * Takes a struct psb_intel_sdvo_output_flags of which outputs are targeted by 221 + * future output commands. 222 + * 223 + * Affected commands inclue SET_OUTPUT_TIMINGS_PART[12], 224 + * GET_OUTPUT_TIMINGS_PART[12], and GET_OUTPUT_PIXEL_CLOCK_RANGE. 225 + */ 226 + #define SDVO_CMD_SET_TARGET_OUTPUT 0x11 227 + 228 + #define SDVO_CMD_GET_INPUT_TIMINGS_PART1 0x12 229 + #define SDVO_CMD_GET_INPUT_TIMINGS_PART2 0x13 230 + #define SDVO_CMD_SET_INPUT_TIMINGS_PART1 0x14 231 + #define SDVO_CMD_SET_INPUT_TIMINGS_PART2 0x15 232 + #define SDVO_CMD_SET_OUTPUT_TIMINGS_PART1 0x16 233 + #define SDVO_CMD_SET_OUTPUT_TIMINGS_PART2 0x17 234 + #define SDVO_CMD_GET_OUTPUT_TIMINGS_PART1 0x18 235 + #define SDVO_CMD_GET_OUTPUT_TIMINGS_PART2 0x19 236 + /* Part 1 */ 237 + # define SDVO_DTD_CLOCK_LOW SDVO_I2C_ARG_0 238 + # define SDVO_DTD_CLOCK_HIGH SDVO_I2C_ARG_1 239 + # define SDVO_DTD_H_ACTIVE SDVO_I2C_ARG_2 240 + # define SDVO_DTD_H_BLANK SDVO_I2C_ARG_3 241 + # define SDVO_DTD_H_HIGH SDVO_I2C_ARG_4 242 + # define SDVO_DTD_V_ACTIVE SDVO_I2C_ARG_5 243 + # define SDVO_DTD_V_BLANK SDVO_I2C_ARG_6 244 + # define SDVO_DTD_V_HIGH SDVO_I2C_ARG_7 245 + /* Part 2 */ 246 + # define SDVO_DTD_HSYNC_OFF SDVO_I2C_ARG_0 247 + # define SDVO_DTD_HSYNC_WIDTH SDVO_I2C_ARG_1 248 + # define SDVO_DTD_VSYNC_OFF_WIDTH SDVO_I2C_ARG_2 249 + # define SDVO_DTD_SYNC_OFF_WIDTH_HIGH SDVO_I2C_ARG_3 250 + # define SDVO_DTD_DTD_FLAGS SDVO_I2C_ARG_4 251 + # define SDVO_DTD_DTD_FLAG_INTERLACED (1 << 7) 252 + # define SDVO_DTD_DTD_FLAG_STEREO_MASK (3 << 5) 253 + # define SDVO_DTD_DTD_FLAG_INPUT_MASK (3 << 3) 254 + # define SDVO_DTD_DTD_FLAG_SYNC_MASK (3 << 1) 255 + # define SDVO_DTD_SDVO_FLAS SDVO_I2C_ARG_5 256 + # define SDVO_DTD_SDVO_FLAG_STALL (1 << 7) 257 + # define SDVO_DTD_SDVO_FLAG_CENTERED (0 << 6) 258 + # define SDVO_DTD_SDVO_FLAG_UPPER_LEFT (1 << 6) 259 + # define SDVO_DTD_SDVO_FLAG_SCALING_MASK (3 << 4) 260 + # define SDVO_DTD_SDVO_FLAG_SCALING_NONE (0 << 4) 261 + # define SDVO_DTD_SDVO_FLAG_SCALING_SHARP (1 << 4) 262 + # define SDVO_DTD_SDVO_FLAG_SCALING_SMOOTH (2 << 4) 263 + # define SDVO_DTD_VSYNC_OFF_HIGH SDVO_I2C_ARG_6 264 + 265 + /** 266 + * Generates a DTD based on the given width, height, and flags. 267 + * 268 + * This will be supported by any device supporting scaling or interlaced 269 + * modes. 270 + */ 271 + #define SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING 0x1a 272 + # define SDVO_PREFERRED_INPUT_TIMING_CLOCK_LOW SDVO_I2C_ARG_0 273 + # define SDVO_PREFERRED_INPUT_TIMING_CLOCK_HIGH SDVO_I2C_ARG_1 274 + # define SDVO_PREFERRED_INPUT_TIMING_WIDTH_LOW SDVO_I2C_ARG_2 275 + # define SDVO_PREFERRED_INPUT_TIMING_WIDTH_HIGH SDVO_I2C_ARG_3 276 + # define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_LOW SDVO_I2C_ARG_4 277 + # define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_HIGH SDVO_I2C_ARG_5 278 + # define SDVO_PREFERRED_INPUT_TIMING_FLAGS SDVO_I2C_ARG_6 279 + # define SDVO_PREFERRED_INPUT_TIMING_FLAGS_INTERLACED (1 << 0) 280 + # define SDVO_PREFERRED_INPUT_TIMING_FLAGS_SCALED (1 << 1) 281 + 282 + #define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1 0x1b 283 + #define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2 0x1c 284 + 285 + /** Returns a struct psb_intel_sdvo_pixel_clock_range */ 286 + #define SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE 0x1d 287 + /** Returns a struct psb_intel_sdvo_pixel_clock_range */ 288 + #define SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE 0x1e 289 + 290 + /** Returns a byte bitfield containing SDVO_CLOCK_RATE_MULT_* flags */ 291 + #define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS 0x1f 292 + 293 + /** Returns a byte containing a SDVO_CLOCK_RATE_MULT_* flag */ 294 + #define SDVO_CMD_GET_CLOCK_RATE_MULT 0x20 295 + /** Takes a byte containing a SDVO_CLOCK_RATE_MULT_* flag */ 296 + #define SDVO_CMD_SET_CLOCK_RATE_MULT 0x21 297 + # define SDVO_CLOCK_RATE_MULT_1X (1 << 0) 298 + # define SDVO_CLOCK_RATE_MULT_2X (1 << 1) 299 + # define SDVO_CLOCK_RATE_MULT_4X (1 << 3) 300 + 301 + #define SDVO_CMD_GET_SUPPORTED_TV_FORMATS 0x27 302 + 303 + #define SDVO_CMD_GET_TV_FORMAT 0x28 304 + 305 + #define SDVO_CMD_SET_TV_FORMAT 0x29 306 + 307 + #define SDVO_CMD_GET_SUPPORTED_POWER_STATES 0x2a 308 + #define SDVO_CMD_GET_ENCODER_POWER_STATE 0x2b 309 + #define SDVO_CMD_SET_ENCODER_POWER_STATE 0x2c 310 + # define SDVO_ENCODER_STATE_ON (1 << 0) 311 + # define SDVO_ENCODER_STATE_STANDBY (1 << 1) 312 + # define SDVO_ENCODER_STATE_SUSPEND (1 << 2) 313 + # define SDVO_ENCODER_STATE_OFF (1 << 3) 314 + 315 + #define SDVO_CMD_SET_TV_RESOLUTION_SUPPORT 0x93 316 + 317 + #define SDVO_CMD_SET_CONTROL_BUS_SWITCH 0x7a 318 + # define SDVO_CONTROL_BUS_PROM 0x0 319 + # define SDVO_CONTROL_BUS_DDC1 0x1 320 + # define SDVO_CONTROL_BUS_DDC2 0x2 321 + # define SDVO_CONTROL_BUS_DDC3 0x3 322 + 323 + /* SDVO Bus & SDVO Inputs wiring details*/ 324 + /* Bit 0: Is SDVOB connected to In0 (1 = yes, 0 = no*/ 325 + /* Bit 1: Is SDVOB connected to In1 (1 = yes, 0 = no*/ 326 + /* Bit 2: Is SDVOC connected to In0 (1 = yes, 0 = no*/ 327 + /* Bit 3: Is SDVOC connected to In1 (1 = yes, 0 = no*/ 328 + #define SDVOB_IN0 0x01 329 + #define SDVOB_IN1 0x02 330 + #define SDVOC_IN0 0x04 331 + #define SDVOC_IN1 0x08 332 + 333 + #define SDVO_DEVICE_NONE 0x00 334 + #define SDVO_DEVICE_CRT 0x01 335 + #define SDVO_DEVICE_TV 0x02 336 + #define SDVO_DEVICE_LVDS 0x04 337 + #define SDVO_DEVICE_TMDS 0x08 338 +
+90
drivers/gpu/drm/gma500/psb_lid.c
··· 1 + /************************************************************************** 2 + * Copyright (c) 2007, Intel Corporation. 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms and conditions of the GNU General Public License, 6 + * version 2, as published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope it will be useful, but WITHOUT 9 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 + * more details. 12 + * 13 + * You should have received a copy of the GNU General Public License along with 14 + * this program; if not, write to the Free Software Foundation, Inc., 15 + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 16 + * 17 + * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> 18 + **************************************************************************/ 19 + 20 + #include <drm/drmP.h> 21 + #include "psb_drv.h" 22 + #include "psb_reg.h" 23 + #include "psb_intel_reg.h" 24 + #include <linux/spinlock.h> 25 + 26 + static void psb_lid_timer_func(unsigned long data) 27 + { 28 + struct drm_psb_private * dev_priv = (struct drm_psb_private *)data; 29 + struct drm_device *dev = (struct drm_device *)dev_priv->dev; 30 + struct timer_list *lid_timer = &dev_priv->lid_timer; 31 + unsigned long irq_flags; 32 + u32 *lid_state = dev_priv->lid_state; 33 + u32 pp_status; 34 + 35 + if (readl(lid_state) == dev_priv->lid_last_state) 36 + goto lid_timer_schedule; 37 + 38 + if ((readl(lid_state)) & 0x01) { 39 + /*lid state is open*/ 40 + REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | POWER_TARGET_ON); 41 + do { 42 + pp_status = REG_READ(PP_STATUS); 43 + } while ((pp_status & PP_ON) == 0); 44 + 45 + /*FIXME: should be backlight level before*/ 46 + psb_intel_lvds_set_brightness(dev, 100); 47 + } else { 48 + psb_intel_lvds_set_brightness(dev, 0); 49 + 50 + REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & ~POWER_TARGET_ON); 51 + do { 52 + pp_status = REG_READ(PP_STATUS); 53 + } while ((pp_status & PP_ON) == 0); 54 + } 55 + /* printk(KERN_INFO"%s: lid: closed\n", __FUNCTION__); */ 56 + 57 + dev_priv->lid_last_state = readl(lid_state); 58 + 59 + lid_timer_schedule: 60 + spin_lock_irqsave(&dev_priv->lid_lock, irq_flags); 61 + if (!timer_pending(lid_timer)) { 62 + lid_timer->expires = jiffies + PSB_LID_DELAY; 63 + add_timer(lid_timer); 64 + } 65 + spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags); 66 + } 67 + 68 + void psb_lid_timer_init(struct drm_psb_private *dev_priv) 69 + { 70 + struct timer_list *lid_timer = &dev_priv->lid_timer; 71 + unsigned long irq_flags; 72 + 73 + spin_lock_init(&dev_priv->lid_lock); 74 + spin_lock_irqsave(&dev_priv->lid_lock, irq_flags); 75 + 76 + init_timer(lid_timer); 77 + 78 + lid_timer->data = (unsigned long)dev_priv; 79 + lid_timer->function = psb_lid_timer_func; 80 + lid_timer->expires = jiffies + PSB_LID_DELAY; 81 + 82 + add_timer(lid_timer); 83 + spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags); 84 + } 85 + 86 + void psb_lid_timer_takedown(struct drm_psb_private *dev_priv) 87 + { 88 + del_timer_sync(&dev_priv->lid_timer); 89 + } 90 +