Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cad2c8fd authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6:
  drm/kms: teardown crtc correctly when fb is destroyed.
  drm/kms/radeon: cleanup combios TV table like DDX.
  drm/radeon/kms: memset the allocated framebuffer before using it.
  drm/radeon/kms: although LVDS might be possible on crtc 1 don't do it.
  drm/radeon/kms: implement bo busy check + current domain
  drm/radeon/kms: cut down indirects in register accesses.
  drm/radeon/kms: Fix up vertical blank interrupt support.
  drm/radeon/kms: add rv530 R300_SU_REG_DEST + reloc for ZPASS_ADDR
  drm/edid: fixup detailed timings like the X server.
  drm/radeon/kms: Add specific rs690 authorized register table
parents 4aa2d56b 5ef5f72f
Loading
Loading
Loading
Loading
+12 −28
Original line number Diff line number Diff line
@@ -257,31 +257,6 @@ void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type)
}
EXPORT_SYMBOL(drm_mode_object_find);

/**
 * drm_crtc_from_fb - find the CRTC structure associated with an fb
 * @dev: DRM device
 * @fb: framebuffer in question
 *
 * LOCKING:
 * Caller must hold mode_config lock.
 *
 * Find CRTC in the mode_config structure that matches @fb.
 *
 * RETURNS:
 * Pointer to the CRTC or NULL if it wasn't found.
 */
struct drm_crtc *drm_crtc_from_fb(struct drm_device *dev,
				  struct drm_framebuffer *fb)
{
	struct drm_crtc *crtc;

	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
		if (crtc->fb == fb)
			return crtc;
	}
	return NULL;
}

/**
 * drm_framebuffer_init - initialize a framebuffer
 * @dev: DRM device
@@ -328,11 +303,20 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
{
	struct drm_device *dev = fb->dev;
	struct drm_crtc *crtc;
	struct drm_mode_set set;
	int ret;

	/* remove from any CRTC */
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
		if (crtc->fb == fb)
			crtc->fb = NULL;
		if (crtc->fb == fb) {
			/* should turn off the crtc */
			memset(&set, 0, sizeof(struct drm_mode_set));
			set.crtc = crtc;
			set.fb = NULL;
			ret = crtc->funcs->set_config(&set);
			if (ret)
				DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc);
		}
	}

	drm_mode_object_put(dev, &fb->base);
+34 −38
Original line number Diff line number Diff line
@@ -502,25 +502,9 @@ static int add_detailed_info(struct drm_connector *connector,
		struct detailed_non_pixel *data = &timing->data.other_data;
		struct drm_display_mode *newmode;

		/* EDID up to and including 1.2 may put monitor info here */
		if (edid->version == 1 && edid->revision < 3)
			continue;

		/* Detailed mode timing */
		if (timing->pixel_clock) {
			newmode = drm_mode_detailed(dev, edid, timing, quirks);
			if (!newmode)
				continue;

			/* First detailed mode is preferred */
			if (i == 0 && (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING))
				newmode->type |= DRM_MODE_TYPE_PREFERRED;
			drm_mode_probed_add(connector, newmode);

			modes++;
			continue;
		}

		/* X server check is version 1.1 or higher */
		if (edid->version == 1 && edid->revision >= 1 &&
		    !timing->pixel_clock) {
			/* Other timing or info */
			switch (data->type) {
			case EDID_DETAIL_MONITOR_SERIAL:
@@ -551,6 +535,18 @@ static int add_detailed_info(struct drm_connector *connector,
			default:
				break;
			}
		} else {
			newmode = drm_mode_detailed(dev, edid, timing, quirks);
			if (!newmode)
				continue;

			/* First detailed mode is preferred */
			if (i == 0 && (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING))
				newmode->type |= DRM_MODE_TYPE_PREFERRED;
			drm_mode_probed_add(connector, newmode);

			modes++;
		}
	}

	return modes;
+66 −20
Original line number Diff line number Diff line
@@ -253,6 +253,72 @@ void r100_mc_fini(struct radeon_device *rdev)
}


/*
 * Interrupts
 */
int r100_irq_set(struct radeon_device *rdev)
{
	uint32_t tmp = 0;

	if (rdev->irq.sw_int) {
		tmp |= RADEON_SW_INT_ENABLE;
	}
	if (rdev->irq.crtc_vblank_int[0]) {
		tmp |= RADEON_CRTC_VBLANK_MASK;
	}
	if (rdev->irq.crtc_vblank_int[1]) {
		tmp |= RADEON_CRTC2_VBLANK_MASK;
	}
	WREG32(RADEON_GEN_INT_CNTL, tmp);
	return 0;
}

static inline uint32_t r100_irq_ack(struct radeon_device *rdev)
{
	uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS);
	uint32_t irq_mask = RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT |
		RADEON_CRTC2_VBLANK_STAT;

	if (irqs) {
		WREG32(RADEON_GEN_INT_STATUS, irqs);
	}
	return irqs & irq_mask;
}

int r100_irq_process(struct radeon_device *rdev)
{
	uint32_t status;

	status = r100_irq_ack(rdev);
	if (!status) {
		return IRQ_NONE;
	}
	while (status) {
		/* SW interrupt */
		if (status & RADEON_SW_INT_TEST) {
			radeon_fence_process(rdev);
		}
		/* Vertical blank interrupts */
		if (status & RADEON_CRTC_VBLANK_STAT) {
			drm_handle_vblank(rdev->ddev, 0);
		}
		if (status & RADEON_CRTC2_VBLANK_STAT) {
			drm_handle_vblank(rdev->ddev, 1);
		}
		status = r100_irq_ack(rdev);
	}
	return IRQ_HANDLED;
}

u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc)
{
	if (crtc == 0)
		return RREG32(RADEON_CRTC_CRNT_FRAME);
	else
		return RREG32(RADEON_CRTC2_CRNT_FRAME);
}


/*
 * Fence emission
 */
@@ -1556,26 +1622,6 @@ void r100_pll_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
	r100_pll_errata_after_data(rdev);
}

uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
{
	if (reg < 0x10000)
		return readl(((void __iomem *)rdev->rmmio) + reg);
	else {
		writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
		return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
	}
}

void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
{
	if (reg < 0x10000)
		writel(v, ((void __iomem *)rdev->rmmio) + reg);
	else {
		writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
		writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
	}
}

int r100_init(struct radeon_device *rdev)
{
	return 0;
+16 −22
Original line number Diff line number Diff line
@@ -83,8 +83,8 @@ void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev)
		WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp | RADEON_PCIE_TX_GART_INVALIDATE_TLB);
		(void)RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
		WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
		mb();
	}
	mb();
}

int rv370_pcie_gart_enable(struct radeon_device *rdev)
@@ -592,27 +592,6 @@ void r300_vram_info(struct radeon_device *rdev)
}


/*
 * Indirect registers accessor
 */
uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg)
{
	uint32_t r;

	WREG8(RADEON_PCIE_INDEX, ((reg) & 0xff));
	(void)RREG32(RADEON_PCIE_INDEX);
	r = RREG32(RADEON_PCIE_DATA);
	return r;
}

void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
{
	WREG8(RADEON_PCIE_INDEX, ((reg) & 0xff));
	(void)RREG32(RADEON_PCIE_INDEX);
	WREG32(RADEON_PCIE_DATA, (v));
	(void)RREG32(RADEON_PCIE_DATA);
}

/*
 * PCIE Lanes
 */
@@ -1403,6 +1382,21 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
		tmp = (ib_chunk->kdata[idx] >> 22) & 0xF;
		track->textures[i].txdepth = tmp;
		break;
	case R300_ZB_ZPASS_ADDR:
		r = r100_cs_packet_next_reloc(p, &reloc);
		if (r) {
			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
					idx, reg);
			r100_cs_dump_packet(p, pkt);
			return r;
		}
		ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
		break;
	case 0x4be8:
		/* valid register only on RV530 */
		if (p->rdev->family == CHIP_RV530)
			break;
		/* fallthrough do not move */
	default:
		printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
		       reg, idx);
+12 −4
Original line number Diff line number Diff line
@@ -350,6 +350,7 @@
#define AVIVO_D1CRTC_BLANK_CONTROL                              0x6084
#define AVIVO_D1CRTC_INTERLACE_CONTROL                          0x6088
#define AVIVO_D1CRTC_INTERLACE_STATUS                           0x608c
#define AVIVO_D1CRTC_FRAME_COUNT                                0x60a4
#define AVIVO_D1CRTC_STEREO_CONTROL                             0x60c4

/* master controls */
@@ -438,14 +439,15 @@
#       define AVIVO_DC_LB_DISP1_END_ADR_SHIFT  4
#       define AVIVO_DC_LB_DISP1_END_ADR_MASK   0x7ff

#define R500_DxMODE_INT_MASK 0x6540
#define R500_D1MODE_INT_MASK (1<<0)
#define R500_D2MODE_INT_MASK (1<<8)

#define AVIVO_D1MODE_DATA_FORMAT                0x6528
#       define AVIVO_D1MODE_INTERLEAVE_EN       (1 << 0)
#define AVIVO_D1MODE_DESKTOP_HEIGHT             0x652C
#define AVIVO_D1MODE_VBLANK_STATUS              0x6534
#       define AVIVO_VBLANK_ACK                 (1 << 4)
#define AVIVO_D1MODE_VLINE_START_END            0x6538
#define AVIVO_DxMODE_INT_MASK                   0x6540
#       define AVIVO_D1MODE_INT_MASK            (1 << 0)
#       define AVIVO_D2MODE_INT_MASK            (1 << 8)
#define AVIVO_D1MODE_VIEWPORT_START             0x6580
#define AVIVO_D1MODE_VIEWPORT_SIZE              0x6584
#define AVIVO_D1MODE_EXT_OVERSCAN_LEFT_RIGHT    0x6588
@@ -475,6 +477,7 @@
#define AVIVO_D2CRTC_BLANK_CONTROL                              0x6884
#define AVIVO_D2CRTC_INTERLACE_CONTROL                          0x6888
#define AVIVO_D2CRTC_INTERLACE_STATUS                           0x688c
#define AVIVO_D2CRTC_FRAME_COUNT                                0x68a4
#define AVIVO_D2CRTC_STEREO_CONTROL                             0x68c4

#define AVIVO_D2GRPH_ENABLE                                     0x6900
@@ -497,6 +500,7 @@
#define AVIVO_D2CUR_SIZE                        0x6c10
#define AVIVO_D2CUR_POSITION                    0x6c14

#define AVIVO_D2MODE_VBLANK_STATUS              0x6d34
#define AVIVO_D2MODE_VLINE_START_END            0x6d38
#define AVIVO_D2MODE_VIEWPORT_START             0x6d80
#define AVIVO_D2MODE_VIEWPORT_SIZE              0x6d84
@@ -748,4 +752,8 @@
#	define AVIVO_I2C_EN							(1 << 0)
#	define AVIVO_I2C_RESET						(1 << 8)

#define AVIVO_DISP_INTERRUPT_STATUS                             0x7edc
#       define AVIVO_D1_VBLANK_INTERRUPT                        (1 << 4)
#       define AVIVO_D2_VBLANK_INTERRUPT                        (1 << 5)

#endif
Loading