16ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs/*
26ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * Copyright 2008 Stuart Bennett
36ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs *
46ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * Permission is hereby granted, free of charge, to any person obtaining a
56ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * copy of this software and associated documentation files (the "Software"),
66ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * to deal in the Software without restriction, including without limitation
76ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * the rights to use, copy, modify, merge, publish, distribute, sublicense,
86ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * and/or sell copies of the Software, and to permit persons to whom the
96ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * Software is furnished to do so, subject to the following conditions:
106ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs *
116ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * The above copyright notice and this permission notice shall be included in
126ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * all copies or substantial portions of the Software.
136ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs *
146ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
156ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
166ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
176ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
186ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
196ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
206ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * SOFTWARE.
216ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs */
226ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
236ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs#ifndef __NOUVEAU_HW_H__
246ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs#define __NOUVEAU_HW_H__
256ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
266ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs#include "drmP.h"
276ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs#include "nouveau_drv.h"
286ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
296ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs#define MASK(field) ( \
306ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	(0xffffffff >> (31 - ((1 ? field) - (0 ? field)))) << (0 ? field))
316ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
326ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs#define XLATE(src, srclowbit, outfield) ( \
336ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	(((src) >> (srclowbit)) << (0 ? outfield)) & MASK(outfield))
346ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
356ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsvoid NVWriteVgaSeq(struct drm_device *, int head, uint8_t index, uint8_t value);
366ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsuint8_t NVReadVgaSeq(struct drm_device *, int head, uint8_t index);
376ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsvoid NVWriteVgaGr(struct drm_device *, int head, uint8_t index, uint8_t value);
386ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsuint8_t NVReadVgaGr(struct drm_device *, int head, uint8_t index);
396ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsvoid NVSetOwner(struct drm_device *, int owner);
406ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsvoid NVBlankScreen(struct drm_device *, int head, bool blank);
416ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsvoid nouveau_hw_setpll(struct drm_device *, uint32_t reg1,
426ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		       struct nouveau_pll_vals *pv);
436ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsint nouveau_hw_get_pllvals(struct drm_device *, enum pll_types plltype,
446ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs			   struct nouveau_pll_vals *pllvals);
456ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsint nouveau_hw_pllvals_to_clk(struct nouveau_pll_vals *pllvals);
466ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsint nouveau_hw_get_clock(struct drm_device *, enum pll_types plltype);
476ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsvoid nouveau_hw_save_vga_fonts(struct drm_device *, bool save);
486ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsvoid nouveau_hw_save_state(struct drm_device *, int head,
496ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs			   struct nv04_mode_state *state);
506ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsvoid nouveau_hw_load_state(struct drm_device *, int head,
516ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs			   struct nv04_mode_state *state);
526ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsvoid nouveau_hw_load_state_palette(struct drm_device *, int head,
536ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs				   struct nv04_mode_state *state);
546ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
556ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs/* nouveau_calc.c */
566ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsextern void nouveau_calc_arb(struct drm_device *, int vclk, int bpp,
576ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs			     int *burst, int *lwm);
586ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsextern int nouveau_calc_pll_mnp(struct drm_device *, struct pll_lims *pll_lim,
596ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs				int clk, struct nouveau_pll_vals *pv);
606ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
616ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline uint32_t
626ee738610f41b59733f63718f0bdbcba7d3a3f12Ben SkeggsnvReadMC(struct drm_device *dev, uint32_t reg)
636ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
646ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	uint32_t val = nv_rd32(dev, reg);
656ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NV_REG_DEBUG(MC, dev, "reg %08x val %08x\n", reg, val);
666ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	return val;
676ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
686ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
696ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline void
706ee738610f41b59733f63718f0bdbcba7d3a3f12Ben SkeggsnvWriteMC(struct drm_device *dev, uint32_t reg, uint32_t val)
716ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
726ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NV_REG_DEBUG(MC, dev, "reg %08x val %08x\n", reg, val);
736ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	nv_wr32(dev, reg, val);
746ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
756ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
766ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline uint32_t
776ee738610f41b59733f63718f0bdbcba7d3a3f12Ben SkeggsnvReadVIDEO(struct drm_device *dev, uint32_t reg)
786ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
796ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	uint32_t val = nv_rd32(dev, reg);
806ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NV_REG_DEBUG(VIDEO, dev, "reg %08x val %08x\n", reg, val);
816ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	return val;
826ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
836ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
846ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline void
856ee738610f41b59733f63718f0bdbcba7d3a3f12Ben SkeggsnvWriteVIDEO(struct drm_device *dev, uint32_t reg, uint32_t val)
866ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
876ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NV_REG_DEBUG(VIDEO, dev, "reg %08x val %08x\n", reg, val);
886ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	nv_wr32(dev, reg, val);
896ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
906ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
916ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline uint32_t
926ee738610f41b59733f63718f0bdbcba7d3a3f12Ben SkeggsnvReadFB(struct drm_device *dev, uint32_t reg)
936ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
946ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	uint32_t val = nv_rd32(dev, reg);
956ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NV_REG_DEBUG(FB, dev, "reg %08x val %08x\n", reg, val);
966ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	return val;
976ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
986ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
996ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline void
1006ee738610f41b59733f63718f0bdbcba7d3a3f12Ben SkeggsnvWriteFB(struct drm_device *dev, uint32_t reg, uint32_t val)
1016ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
1026ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NV_REG_DEBUG(FB, dev, "reg %08x val %08x\n", reg, val);
1036ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	nv_wr32(dev, reg, val);
1046ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
1056ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
1066ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline uint32_t
1076ee738610f41b59733f63718f0bdbcba7d3a3f12Ben SkeggsnvReadEXTDEV(struct drm_device *dev, uint32_t reg)
1086ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
1096ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	uint32_t val = nv_rd32(dev, reg);
1106ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NV_REG_DEBUG(EXTDEV, dev, "reg %08x val %08x\n", reg, val);
1116ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	return val;
1126ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
1136ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
1146ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline void
1156ee738610f41b59733f63718f0bdbcba7d3a3f12Ben SkeggsnvWriteEXTDEV(struct drm_device *dev, uint32_t reg, uint32_t val)
1166ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
1176ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NV_REG_DEBUG(EXTDEV, dev, "reg %08x val %08x\n", reg, val);
1186ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	nv_wr32(dev, reg, val);
1196ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
1206ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
1216ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline uint32_t NVReadCRTC(struct drm_device *dev,
1226ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs					int head, uint32_t reg)
1236ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
1246ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	uint32_t val;
1256ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	if (head)
1266ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		reg += NV_PCRTC0_SIZE;
1276ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	val = nv_rd32(dev, reg);
1286ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NV_REG_DEBUG(CRTC, dev, "head %d reg %08x val %08x\n", head, reg, val);
1296ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	return val;
1306ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
1316ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
1326ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline void NVWriteCRTC(struct drm_device *dev,
1336ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs					int head, uint32_t reg, uint32_t val)
1346ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
1356ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	if (head)
1366ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		reg += NV_PCRTC0_SIZE;
1376ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NV_REG_DEBUG(CRTC, dev, "head %d reg %08x val %08x\n", head, reg, val);
1386ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	nv_wr32(dev, reg, val);
1396ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
1406ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
1416ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline uint32_t NVReadRAMDAC(struct drm_device *dev,
1426ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs					int head, uint32_t reg)
1436ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
1446ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	uint32_t val;
1456ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	if (head)
1466ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		reg += NV_PRAMDAC0_SIZE;
1476ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	val = nv_rd32(dev, reg);
1486ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NV_REG_DEBUG(RAMDAC, dev, "head %d reg %08x val %08x\n",
1496ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs							head, reg, val);
1506ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	return val;
1516ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
1526ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
1536ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline void NVWriteRAMDAC(struct drm_device *dev,
1546ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs					int head, uint32_t reg, uint32_t val)
1556ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
1566ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	if (head)
1576ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		reg += NV_PRAMDAC0_SIZE;
1586ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NV_REG_DEBUG(RAMDAC, dev, "head %d reg %08x val %08x\n",
1596ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs							head, reg, val);
1606ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	nv_wr32(dev, reg, val);
1616ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
1626ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
1636ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline uint8_t nv_read_tmds(struct drm_device *dev,
1646ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs					int or, int dl, uint8_t address)
1656ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
1666ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	int ramdac = (or & OUTPUT_C) >> 2;
1676ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
1686ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NVWriteRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_CONTROL + dl * 8,
1696ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE | address);
1706ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	return NVReadRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_DATA + dl * 8);
1716ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
1726ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
1736ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline void nv_write_tmds(struct drm_device *dev,
1746ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs					int or, int dl, uint8_t address,
1756ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs					uint8_t data)
1766ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
1776ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	int ramdac = (or & OUTPUT_C) >> 2;
1786ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
1796ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NVWriteRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_DATA + dl * 8, data);
1806ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NVWriteRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_CONTROL + dl * 8, address);
1816ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
1826ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
1836ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline void NVWriteVgaCrtc(struct drm_device *dev,
1846ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs					int head, uint8_t index, uint8_t value)
1856ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
1866ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NV_REG_DEBUG(VGACRTC, dev, "head %d index 0x%02x data 0x%02x\n",
1876ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs							head, index, value);
1886ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	nv_wr08(dev, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index);
1896ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	nv_wr08(dev, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE, value);
1906ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
1916ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
1926ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline uint8_t NVReadVgaCrtc(struct drm_device *dev,
1936ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs					int head, uint8_t index)
1946ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
1956ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	uint8_t val;
1966ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	nv_wr08(dev, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index);
1976ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	val = nv_rd08(dev, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE);
1986ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NV_REG_DEBUG(VGACRTC, dev, "head %d index 0x%02x data 0x%02x\n",
1996ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs							head, index, val);
2006ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	return val;
2016ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
2026ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
2036ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs/* CR57 and CR58 are a fun pair of regs. CR57 provides an index (0-0xf) for CR58
2046ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * I suspect they in fact do nothing, but are merely a way to carry useful
2056ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * per-head variables around
2066ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs *
2076ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * Known uses:
2086ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * CR57		CR58
2096ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * 0x00		index to the appropriate dcb entry (or 7f for inactive)
2106ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * 0x02		dcb entry's "or" value (or 00 for inactive)
2116ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * 0x03		bit0 set for dual link (LVDS, possibly elsewhere too)
2126ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * 0x08 or 0x09	pxclk in MHz
2136ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * 0x0f		laptop panel info -	low nibble for PEXTDEV_BOOT_0 strap
2146ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * 					high nibble for xlat strap value
2156ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs */
2166ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
2176ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline void
2186ee738610f41b59733f63718f0bdbcba7d3a3f12Ben SkeggsNVWriteVgaCrtc5758(struct drm_device *dev, int head, uint8_t index, uint8_t value)
2196ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
2206ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NVWriteVgaCrtc(dev, head, NV_CIO_CRE_57, index);
2216ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NVWriteVgaCrtc(dev, head, NV_CIO_CRE_58, value);
2226ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
2236ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
2246ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline uint8_t NVReadVgaCrtc5758(struct drm_device *dev, int head, uint8_t index)
2256ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
2266ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NVWriteVgaCrtc(dev, head, NV_CIO_CRE_57, index);
2276ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	return NVReadVgaCrtc(dev, head, NV_CIO_CRE_58);
2286ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
2296ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
2306ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline uint8_t NVReadPRMVIO(struct drm_device *dev,
2316ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs					int head, uint32_t reg)
2326ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
2336ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	struct drm_nouveau_private *dev_priv = dev->dev_private;
2346ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	uint8_t val;
2356ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
2366ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	/* Only NV4x have two pvio ranges; other twoHeads cards MUST call
2376ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	 * NVSetOwner for the relevant head to be programmed */
2386ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	if (head && dev_priv->card_type == NV_40)
2396ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		reg += NV_PRMVIO_SIZE;
2406ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
2416ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	val = nv_rd08(dev, reg);
2426ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NV_REG_DEBUG(RMVIO, dev, "head %d reg %08x val %02x\n", head, reg, val);
2436ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	return val;
2446ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
2456ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
2466ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline void NVWritePRMVIO(struct drm_device *dev,
2476ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs					int head, uint32_t reg, uint8_t value)
2486ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
2496ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	struct drm_nouveau_private *dev_priv = dev->dev_private;
2506ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
2516ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	/* Only NV4x have two pvio ranges; other twoHeads cards MUST call
2526ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	 * NVSetOwner for the relevant head to be programmed */
2536ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	if (head && dev_priv->card_type == NV_40)
2546ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		reg += NV_PRMVIO_SIZE;
2556ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
2566ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NV_REG_DEBUG(RMVIO, dev, "head %d reg %08x val %02x\n",
2576ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs						head, reg, value);
2586ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	nv_wr08(dev, reg, value);
2596ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
2606ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
2616ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline void NVSetEnablePalette(struct drm_device *dev, int head, bool enable)
2626ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
2636ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
2646ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	nv_wr08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, enable ? 0 : 0x20);
2656ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
2666ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
2676ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline bool NVGetEnablePalette(struct drm_device *dev, int head)
2686ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
2696ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
2706ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	return !(nv_rd08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE) & 0x20);
2716ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
2726ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
2736ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline void NVWriteVgaAttr(struct drm_device *dev,
2746ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs					int head, uint8_t index, uint8_t value)
2756ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
2766ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	if (NVGetEnablePalette(dev, head))
2776ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		index &= ~0x20;
2786ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	else
2796ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		index |= 0x20;
2806ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
2816ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
2826ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NV_REG_DEBUG(VGAATTR, dev, "head %d index 0x%02x data 0x%02x\n",
2836ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs							head, index, value);
2846ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	nv_wr08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index);
2856ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	nv_wr08(dev, NV_PRMCIO_AR__WRITE + head * NV_PRMCIO_SIZE, value);
2866ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
2876ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
2886ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline uint8_t NVReadVgaAttr(struct drm_device *dev,
2896ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs					int head, uint8_t index)
2906ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
2916ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	uint8_t val;
2926ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	if (NVGetEnablePalette(dev, head))
2936ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		index &= ~0x20;
2946ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	else
2956ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		index |= 0x20;
2966ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
2976ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
2986ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	nv_wr08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index);
2996ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	val = nv_rd08(dev, NV_PRMCIO_AR__READ + head * NV_PRMCIO_SIZE);
3006ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NV_REG_DEBUG(VGAATTR, dev, "head %d index 0x%02x data 0x%02x\n",
3016ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs							head, index, val);
3026ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	return val;
3036ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
3046ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
3056ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline void NVVgaSeqReset(struct drm_device *dev, int head, bool start)
3066ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
3076ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NVWriteVgaSeq(dev, head, NV_VIO_SR_RESET_INDEX, start ? 0x1 : 0x3);
3086ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
3096ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
3106ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline void NVVgaProtect(struct drm_device *dev, int head, bool protect)
3116ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
3126ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	uint8_t seq1 = NVReadVgaSeq(dev, head, NV_VIO_SR_CLOCK_INDEX);
3136ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
3146ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	if (protect) {
3156ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		NVVgaSeqReset(dev, head, true);
3166ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		NVWriteVgaSeq(dev, head, NV_VIO_SR_CLOCK_INDEX, seq1 | 0x20);
3176ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	} else {
3186ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		/* Reenable sequencer, then turn on screen */
3196ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		NVWriteVgaSeq(dev, head, NV_VIO_SR_CLOCK_INDEX, seq1 & ~0x20);   /* reenable display */
3206ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		NVVgaSeqReset(dev, head, false);
3216ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	}
3226ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NVSetEnablePalette(dev, head, protect);
3236ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
3246ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
3256ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline bool
3266ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsnv_heads_tied(struct drm_device *dev)
3276ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
3286ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	struct drm_nouveau_private *dev_priv = dev->dev_private;
3296ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
3306ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	if (dev_priv->chipset == 0x11)
3316ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		return !!(nvReadMC(dev, NV_PBUS_DEBUG_1) & (1 << 28));
3326ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
3336ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	return NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44) & 0x4;
3346ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
3356ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
3366ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs/* makes cr0-7 on the specified head read-only */
3376ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline bool
3386ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsnv_lock_vga_crtc_base(struct drm_device *dev, int head, bool lock)
3396ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
3406ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	uint8_t cr11 = NVReadVgaCrtc(dev, head, NV_CIO_CR_VRE_INDEX);
3416ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	bool waslocked = cr11 & 0x80;
3426ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
3436ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	if (lock)
3446ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		cr11 |= 0x80;
3456ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	else
3466ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		cr11 &= ~0x80;
3476ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NVWriteVgaCrtc(dev, head, NV_CIO_CR_VRE_INDEX, cr11);
3486ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
3496ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	return waslocked;
3506ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
3516ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
3526ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline void
3536ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsnv_lock_vga_crtc_shadow(struct drm_device *dev, int head, int lock)
3546ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
3556ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	/* shadow lock: connects 0x60?3d? regs to "real" 0x3d? regs
3566ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	 * bit7: unlocks HDT, HBS, HBE, HRS, HRE, HEB
3576ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	 * bit6: seems to have some effect on CR09 (double scan, VBS_9)
3586ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	 * bit5: unlocks HDE
3596ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	 * bit4: unlocks VDE
3606ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	 * bit3: unlocks VDT, OVL, VRS, ?VRE?, VBS, VBE, LSR, EBR
3616ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	 * bit2: same as bit 1 of 0x60?804
3626ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	 * bit0: same as bit 0 of 0x60?804
3636ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	 */
3646ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
3656ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	uint8_t cr21 = lock;
3666ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
3676ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	if (lock < 0)
3686ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		/* 0xfa is generic "unlock all" mask */
3696ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		cr21 = NVReadVgaCrtc(dev, head, NV_CIO_CRE_21) | 0xfa;
3706ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
3716ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NVWriteVgaCrtc(dev, head, NV_CIO_CRE_21, cr21);
3726ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
3736ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
3746ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs/* renders the extended crtc regs (cr19+) on all crtcs impervious:
3756ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs * immutable and unreadable
3766ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs */
3776ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline bool
3786ee738610f41b59733f63718f0bdbcba7d3a3f12Ben SkeggsNVLockVgaCrtcs(struct drm_device *dev, bool lock)
3796ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
3806ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	struct drm_nouveau_private *dev_priv = dev->dev_private;
3816ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	bool waslocked = !NVReadVgaCrtc(dev, 0, NV_CIO_SR_LOCK_INDEX);
3826ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
3836ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NVWriteVgaCrtc(dev, 0, NV_CIO_SR_LOCK_INDEX,
3846ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		       lock ? NV_CIO_SR_LOCK_VALUE : NV_CIO_SR_UNLOCK_RW_VALUE);
3856ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	/* NV11 has independently lockable extended crtcs, except when tied */
3866ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	if (dev_priv->chipset == 0x11 && !nv_heads_tied(dev))
3876ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		NVWriteVgaCrtc(dev, 1, NV_CIO_SR_LOCK_INDEX,
3886ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs			       lock ? NV_CIO_SR_LOCK_VALUE :
3896ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs				      NV_CIO_SR_UNLOCK_RW_VALUE);
3906ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
3916ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	return waslocked;
3926ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
3936ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
3946ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs/* nv04 cursor max dimensions of 32x32 (A1R5G5B5) */
3956ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs#define NV04_CURSOR_SIZE 32
3966ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs/* limit nv10 cursors to 64x64 (ARGB8) (we could go to 64x255) */
3976ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs#define NV10_CURSOR_SIZE 64
3986ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
3996ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline int nv_cursor_width(struct drm_device *dev)
4006ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
4016ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	struct drm_nouveau_private *dev_priv = dev->dev_private;
4026ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
4036ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	return dev_priv->card_type >= NV_10 ? NV10_CURSOR_SIZE : NV04_CURSOR_SIZE;
4046ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
4056ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
4066ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline void
4076ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsnv_fix_nv40_hw_cursor(struct drm_device *dev, int head)
4086ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
4096ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	/* on some nv40 (such as the "true" (in the NV_PFB_BOOT_0 sense) nv40,
4106ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	 * the gf6800gt) a hardware bug requires a write to PRAMDAC_CURSOR_POS
4116ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	 * for changes to the CRTC CURCTL regs to take effect, whether changing
4126ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	 * the pixmap location, or just showing/hiding the cursor
4136ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	 */
4146ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	uint32_t curpos = NVReadRAMDAC(dev, head, NV_PRAMDAC_CU_START_POS);
4156ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NVWriteRAMDAC(dev, head, NV_PRAMDAC_CU_START_POS, curpos);
4166ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
4176ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
4186ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline void
4195794b5fdb579abf7be2c27c6e0d6106f391a26e4Francisco Jereznv_set_crtc_base(struct drm_device *dev, int head, uint32_t offset)
4205794b5fdb579abf7be2c27c6e0d6106f391a26e4Francisco Jerez{
4215794b5fdb579abf7be2c27c6e0d6106f391a26e4Francisco Jerez	struct drm_nouveau_private *dev_priv = dev->dev_private;
4225794b5fdb579abf7be2c27c6e0d6106f391a26e4Francisco Jerez
4235794b5fdb579abf7be2c27c6e0d6106f391a26e4Francisco Jerez	NVWriteCRTC(dev, head, NV_PCRTC_START, offset);
4245794b5fdb579abf7be2c27c6e0d6106f391a26e4Francisco Jerez
4255794b5fdb579abf7be2c27c6e0d6106f391a26e4Francisco Jerez	if (dev_priv->card_type == NV_04) {
4265794b5fdb579abf7be2c27c6e0d6106f391a26e4Francisco Jerez		/*
4275794b5fdb579abf7be2c27c6e0d6106f391a26e4Francisco Jerez		 * Hilarious, the 24th bit doesn't want to stick to
4285794b5fdb579abf7be2c27c6e0d6106f391a26e4Francisco Jerez		 * PCRTC_START...
4295794b5fdb579abf7be2c27c6e0d6106f391a26e4Francisco Jerez		 */
4305794b5fdb579abf7be2c27c6e0d6106f391a26e4Francisco Jerez		int cre_heb = NVReadVgaCrtc(dev, head, NV_CIO_CRE_HEB__INDEX);
4315794b5fdb579abf7be2c27c6e0d6106f391a26e4Francisco Jerez
4325794b5fdb579abf7be2c27c6e0d6106f391a26e4Francisco Jerez		NVWriteVgaCrtc(dev, head, NV_CIO_CRE_HEB__INDEX,
4335794b5fdb579abf7be2c27c6e0d6106f391a26e4Francisco Jerez			       (cre_heb & ~0x40) | ((offset >> 18) & 0x40));
4345794b5fdb579abf7be2c27c6e0d6106f391a26e4Francisco Jerez	}
4355794b5fdb579abf7be2c27c6e0d6106f391a26e4Francisco Jerez}
4365794b5fdb579abf7be2c27c6e0d6106f391a26e4Francisco Jerez
4375794b5fdb579abf7be2c27c6e0d6106f391a26e4Francisco Jerezstatic inline void
4386ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsnv_show_cursor(struct drm_device *dev, int head, bool show)
4396ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
4406ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	struct drm_nouveau_private *dev_priv = dev->dev_private;
4416ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	uint8_t *curctl1 =
4426ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		&dev_priv->mode_reg.crtc_reg[head].CRTC[NV_CIO_CRE_HCUR_ADDR1_INDEX];
4436ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
4446ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	if (show)
4456ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		*curctl1 |= MASK(NV_CIO_CRE_HCUR_ADDR1_ENABLE);
4466ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	else
4476ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		*curctl1 &= ~MASK(NV_CIO_CRE_HCUR_ADDR1_ENABLE);
4486ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	NVWriteVgaCrtc(dev, head, NV_CIO_CRE_HCUR_ADDR1_INDEX, *curctl1);
4496ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
4506ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	if (dev_priv->card_type == NV_40)
4516ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		nv_fix_nv40_hw_cursor(dev, head);
4526ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
4536ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
4546ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic inline uint32_t
4556ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsnv_pitch_align(struct drm_device *dev, uint32_t width, int bpp)
4566ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
4576ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	struct drm_nouveau_private *dev_priv = dev->dev_private;
4586ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	int mask;
4596ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
4606ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	if (bpp == 15)
4616ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		bpp = 16;
4626ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	if (bpp == 24)
4636ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		bpp = 8;
4646ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
4656ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	/* Alignment requirements taken from the Haiku driver */
4666ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	if (dev_priv->card_type == NV_04)
4676ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		mask = 128 / bpp - 1;
4686ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	else
4696ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		mask = 512 / bpp - 1;
4706ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
4716ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	return (width + mask) & ~mask;
4726ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
4736ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
4746ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs#endif	/* __NOUVEAU_HW_H__ */
475