drm: merge Linux master into HEAD
Conflicts: drivers/gpu/drm/drm_info.c drivers/gpu/drm/drm_proc.c drivers/gpu/drm/i915/i915_gem_debugfs.c
This commit is contained in:
@@ -337,14 +337,10 @@ int drm_fasync(int fd, struct file *filp, int on)
|
||||
{
|
||||
struct drm_file *priv = filp->private_data;
|
||||
struct drm_device *dev = priv->minor->dev;
|
||||
int retcode;
|
||||
|
||||
DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,
|
||||
(long)old_encode_dev(priv->minor->device));
|
||||
retcode = fasync_helper(fd, filp, on, &dev->buf_async);
|
||||
if (retcode < 0)
|
||||
return retcode;
|
||||
return 0;
|
||||
return fasync_helper(fd, filp, on, &dev->buf_async);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fasync);
|
||||
|
||||
|
||||
@@ -286,9 +286,9 @@ int drm_vma_info(struct seq_file *m, void *data)
|
||||
#endif
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
seq_printf(m, "vma use count: %d, high_memory = %p, 0x%08lx\n",
|
||||
seq_printf(m, "vma use count: %d, high_memory = %p, 0x%08llx\n",
|
||||
atomic_read(&dev->vma_count),
|
||||
high_memory, virt_to_phys(high_memory));
|
||||
high_memory, (u64)virt_to_phys(high_memory));
|
||||
|
||||
list_for_each_entry(pt, &dev->vmalist, head) {
|
||||
vma = pt->vma;
|
||||
|
||||
@@ -349,8 +349,8 @@ int drm_sysfs_connector_add(struct drm_connector *connector)
|
||||
DRM_DEBUG("adding \"%s\" to sysfs\n",
|
||||
drm_get_connector_name(connector));
|
||||
|
||||
snprintf(connector->kdev.bus_id, BUS_ID_SIZE, "card%d-%s",
|
||||
dev->primary->index, drm_get_connector_name(connector));
|
||||
dev_set_name(&connector->kdev, "card%d-%s",
|
||||
dev->primary->index, drm_get_connector_name(connector));
|
||||
ret = device_register(&connector->kdev);
|
||||
|
||||
if (ret) {
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
|
||||
drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
|
||||
u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD;
|
||||
u32 last_acthd = I915_READ(acthd_reg);
|
||||
@@ -58,8 +57,12 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
|
||||
if (ring->space >= n)
|
||||
return 0;
|
||||
|
||||
if (master_priv->sarea_priv)
|
||||
master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
|
||||
if (dev->primary->master) {
|
||||
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
|
||||
if (master_priv->sarea_priv)
|
||||
master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
|
||||
}
|
||||
|
||||
|
||||
if (ring->head != last_head)
|
||||
i = 0;
|
||||
@@ -356,7 +359,7 @@ static int validate_cmd(int cmd)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwords)
|
||||
static int i915_emit_cmds(struct drm_device * dev, int *buffer, int dwords)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int i;
|
||||
@@ -370,8 +373,7 @@ static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwor
|
||||
for (i = 0; i < dwords;) {
|
||||
int cmd, sz;
|
||||
|
||||
if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd)))
|
||||
return -EINVAL;
|
||||
cmd = buffer[i];
|
||||
|
||||
if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords)
|
||||
return -EINVAL;
|
||||
@@ -379,11 +381,7 @@ static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwor
|
||||
OUT_RING(cmd);
|
||||
|
||||
while (++i, --sz) {
|
||||
if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i],
|
||||
sizeof(cmd))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
OUT_RING(cmd);
|
||||
OUT_RING(buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,17 +395,13 @@ static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwor
|
||||
|
||||
int
|
||||
i915_emit_box(struct drm_device *dev,
|
||||
struct drm_clip_rect __user *boxes,
|
||||
struct drm_clip_rect *boxes,
|
||||
int i, int DR1, int DR4)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_clip_rect box;
|
||||
struct drm_clip_rect box = boxes[i];
|
||||
RING_LOCALS;
|
||||
|
||||
if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) {
|
||||
DRM_ERROR("Bad box %d,%d..%d,%d\n",
|
||||
box.x1, box.y1, box.x2, box.y2);
|
||||
@@ -460,7 +454,9 @@ static void i915_emit_breadcrumb(struct drm_device *dev)
|
||||
}
|
||||
|
||||
static int i915_dispatch_cmdbuffer(struct drm_device * dev,
|
||||
drm_i915_cmdbuffer_t * cmd)
|
||||
drm_i915_cmdbuffer_t *cmd,
|
||||
struct drm_clip_rect *cliprects,
|
||||
void *cmdbuf)
|
||||
{
|
||||
int nbox = cmd->num_cliprects;
|
||||
int i = 0, count, ret;
|
||||
@@ -476,13 +472,13 @@ static int i915_dispatch_cmdbuffer(struct drm_device * dev,
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (i < nbox) {
|
||||
ret = i915_emit_box(dev, cmd->cliprects, i,
|
||||
ret = i915_emit_box(dev, cliprects, i,
|
||||
cmd->DR1, cmd->DR4);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = i915_emit_cmds(dev, (int __user *)cmd->buf, cmd->sz / 4);
|
||||
ret = i915_emit_cmds(dev, cmdbuf, cmd->sz / 4);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@@ -492,10 +488,10 @@ static int i915_dispatch_cmdbuffer(struct drm_device * dev,
|
||||
}
|
||||
|
||||
static int i915_dispatch_batchbuffer(struct drm_device * dev,
|
||||
drm_i915_batchbuffer_t * batch)
|
||||
drm_i915_batchbuffer_t * batch,
|
||||
struct drm_clip_rect *cliprects)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_clip_rect __user *boxes = batch->cliprects;
|
||||
int nbox = batch->num_cliprects;
|
||||
int i = 0, count;
|
||||
RING_LOCALS;
|
||||
@@ -511,7 +507,7 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev,
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (i < nbox) {
|
||||
int ret = i915_emit_box(dev, boxes, i,
|
||||
int ret = i915_emit_box(dev, cliprects, i,
|
||||
batch->DR1, batch->DR4);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -626,6 +622,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
|
||||
master_priv->sarea_priv;
|
||||
drm_i915_batchbuffer_t *batch = data;
|
||||
int ret;
|
||||
struct drm_clip_rect *cliprects = NULL;
|
||||
|
||||
if (!dev_priv->allow_batchbuffer) {
|
||||
DRM_ERROR("Batchbuffer ioctl disabled\n");
|
||||
@@ -637,17 +634,35 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
|
||||
|
||||
RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects,
|
||||
batch->num_cliprects *
|
||||
sizeof(struct drm_clip_rect)))
|
||||
return -EFAULT;
|
||||
if (batch->num_cliprects < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (batch->num_cliprects) {
|
||||
cliprects = drm_calloc(batch->num_cliprects,
|
||||
sizeof(struct drm_clip_rect),
|
||||
DRM_MEM_DRIVER);
|
||||
if (cliprects == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = copy_from_user(cliprects, batch->cliprects,
|
||||
batch->num_cliprects *
|
||||
sizeof(struct drm_clip_rect));
|
||||
if (ret != 0)
|
||||
goto fail_free;
|
||||
}
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
ret = i915_dispatch_batchbuffer(dev, batch);
|
||||
ret = i915_dispatch_batchbuffer(dev, batch, cliprects);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
if (sarea_priv)
|
||||
sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
|
||||
|
||||
fail_free:
|
||||
drm_free(cliprects,
|
||||
batch->num_cliprects * sizeof(struct drm_clip_rect),
|
||||
DRM_MEM_DRIVER);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -659,6 +674,8 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
|
||||
drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
|
||||
master_priv->sarea_priv;
|
||||
drm_i915_cmdbuffer_t *cmdbuf = data;
|
||||
struct drm_clip_rect *cliprects = NULL;
|
||||
void *batch_data;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
|
||||
@@ -666,25 +683,50 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
|
||||
|
||||
RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
if (cmdbuf->num_cliprects &&
|
||||
DRM_VERIFYAREA_READ(cmdbuf->cliprects,
|
||||
cmdbuf->num_cliprects *
|
||||
sizeof(struct drm_clip_rect))) {
|
||||
DRM_ERROR("Fault accessing cliprects\n");
|
||||
return -EFAULT;
|
||||
if (cmdbuf->num_cliprects < 0)
|
||||
return -EINVAL;
|
||||
|
||||
batch_data = drm_alloc(cmdbuf->sz, DRM_MEM_DRIVER);
|
||||
if (batch_data == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = copy_from_user(batch_data, cmdbuf->buf, cmdbuf->sz);
|
||||
if (ret != 0)
|
||||
goto fail_batch_free;
|
||||
|
||||
if (cmdbuf->num_cliprects) {
|
||||
cliprects = drm_calloc(cmdbuf->num_cliprects,
|
||||
sizeof(struct drm_clip_rect),
|
||||
DRM_MEM_DRIVER);
|
||||
if (cliprects == NULL)
|
||||
goto fail_batch_free;
|
||||
|
||||
ret = copy_from_user(cliprects, cmdbuf->cliprects,
|
||||
cmdbuf->num_cliprects *
|
||||
sizeof(struct drm_clip_rect));
|
||||
if (ret != 0)
|
||||
goto fail_clip_free;
|
||||
}
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
ret = i915_dispatch_cmdbuffer(dev, cmdbuf);
|
||||
ret = i915_dispatch_cmdbuffer(dev, cmdbuf, cliprects, batch_data);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
if (ret) {
|
||||
DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
|
||||
return ret;
|
||||
goto fail_batch_free;
|
||||
}
|
||||
|
||||
if (sarea_priv)
|
||||
sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
|
||||
return 0;
|
||||
|
||||
fail_batch_free:
|
||||
drm_free(batch_data, cmdbuf->sz, DRM_MEM_DRIVER);
|
||||
fail_clip_free:
|
||||
drm_free(cliprects,
|
||||
cmdbuf->num_cliprects * sizeof(struct drm_clip_rect),
|
||||
DRM_MEM_DRIVER);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int i915_flip_bufs(struct drm_device *dev, void *data,
|
||||
|
||||
@@ -404,7 +404,8 @@ struct drm_i915_gem_object {
|
||||
/** AGP memory structure for our GTT binding. */
|
||||
DRM_AGP_MEM *agp_mem;
|
||||
|
||||
struct page **page_list;
|
||||
struct page **pages;
|
||||
int pages_refcount;
|
||||
|
||||
/**
|
||||
* Current offset of the object in GTT space.
|
||||
@@ -519,7 +520,7 @@ extern int i915_driver_device_is_agp(struct drm_device * dev);
|
||||
extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
extern int i915_emit_box(struct drm_device *dev,
|
||||
struct drm_clip_rect __user *boxes,
|
||||
struct drm_clip_rect *boxes,
|
||||
int i, int DR1, int DR4);
|
||||
|
||||
/* i915_irq.c */
|
||||
@@ -786,15 +787,21 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
|
||||
(dev)->pci_device == 0x2E22 || \
|
||||
IS_GM45(dev))
|
||||
|
||||
#define IS_IGDG(dev) ((dev)->pci_device == 0xa001)
|
||||
#define IS_IGDGM(dev) ((dev)->pci_device == 0xa011)
|
||||
#define IS_IGD(dev) (IS_IGDG(dev) || IS_IGDGM(dev))
|
||||
|
||||
#define IS_G33(dev) ((dev)->pci_device == 0x29C2 || \
|
||||
(dev)->pci_device == 0x29B2 || \
|
||||
(dev)->pci_device == 0x29D2)
|
||||
(dev)->pci_device == 0x29D2 || \
|
||||
(IS_IGD(dev)))
|
||||
|
||||
#define IS_I9XX(dev) (IS_I915G(dev) || IS_I915GM(dev) || IS_I945G(dev) || \
|
||||
IS_I945GM(dev) || IS_I965G(dev) || IS_G33(dev))
|
||||
|
||||
#define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \
|
||||
IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev))
|
||||
IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev) || \
|
||||
IS_IGD(dev))
|
||||
|
||||
#define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev))
|
||||
/* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
|
||||
|
||||
+731
-165
File diff suppressed because it is too large
Load Diff
@@ -192,7 +192,7 @@ static int i915_gem_fence_regs_info(struct seq_file *m, void *data)
|
||||
|
||||
obj_priv = obj->driver_private;
|
||||
seq_printf(m, "Fenced object[%2d] = %p: %s "
|
||||
"%08x %08x %08x %s %08x %08x %d",
|
||||
"%08x %08zx %08x %s %08x %08x %d",
|
||||
i, obj, get_pin_flag(obj_priv),
|
||||
obj_priv->gtt_offset,
|
||||
obj->size, obj_priv->stride,
|
||||
|
||||
@@ -96,16 +96,16 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
|
||||
*/
|
||||
swizzle_x = I915_BIT_6_SWIZZLE_NONE;
|
||||
swizzle_y = I915_BIT_6_SWIZZLE_NONE;
|
||||
} else if ((!IS_I965G(dev) && !IS_G33(dev)) || IS_I965GM(dev) ||
|
||||
IS_GM45(dev)) {
|
||||
} else if (IS_MOBILE(dev)) {
|
||||
uint32_t dcc;
|
||||
|
||||
/* On 915-945 and GM965, channel interleave by the CPU is
|
||||
* determined by DCC. The CPU will alternate based on bit 6
|
||||
* in interleaved mode, and the GPU will then also alternate
|
||||
* on bit 6, 9, and 10 for X, but the CPU may also optionally
|
||||
* alternate based on bit 17 (XOR not disabled and XOR
|
||||
* bit == 17).
|
||||
/* On mobile 9xx chipsets, channel interleave by the CPU is
|
||||
* determined by DCC. For single-channel, neither the CPU
|
||||
* nor the GPU do swizzling. For dual channel interleaved,
|
||||
* the GPU's interleave is bit 9 and 10 for X tiled, and bit
|
||||
* 9 for Y tiled. The CPU's interleave is independent, and
|
||||
* can be based on either bit 11 (haven't seen this yet) or
|
||||
* bit 17 (common).
|
||||
*/
|
||||
dcc = I915_READ(DCC);
|
||||
switch (dcc & DCC_ADDRESSING_MODE_MASK) {
|
||||
@@ -115,19 +115,18 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
|
||||
swizzle_y = I915_BIT_6_SWIZZLE_NONE;
|
||||
break;
|
||||
case DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED:
|
||||
if (IS_I915G(dev) || IS_I915GM(dev) ||
|
||||
dcc & DCC_CHANNEL_XOR_DISABLE) {
|
||||
if (dcc & DCC_CHANNEL_XOR_DISABLE) {
|
||||
/* This is the base swizzling by the GPU for
|
||||
* tiled buffers.
|
||||
*/
|
||||
swizzle_x = I915_BIT_6_SWIZZLE_9_10;
|
||||
swizzle_y = I915_BIT_6_SWIZZLE_9;
|
||||
} else if ((IS_I965GM(dev) || IS_GM45(dev)) &&
|
||||
(dcc & DCC_CHANNEL_XOR_BIT_17) == 0) {
|
||||
/* GM965/GM45 does either bit 11 or bit 17
|
||||
* swizzling.
|
||||
*/
|
||||
} else if ((dcc & DCC_CHANNEL_XOR_BIT_17) == 0) {
|
||||
/* Bit 11 swizzling by the CPU in addition. */
|
||||
swizzle_x = I915_BIT_6_SWIZZLE_9_10_11;
|
||||
swizzle_y = I915_BIT_6_SWIZZLE_9_11;
|
||||
} else {
|
||||
/* Bit 17 or perhaps other swizzling */
|
||||
/* Bit 17 swizzling by the CPU in addition. */
|
||||
swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
|
||||
swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
|
||||
}
|
||||
|
||||
@@ -359,6 +359,7 @@
|
||||
#define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */
|
||||
#define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */
|
||||
#define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */
|
||||
#define DPLL_FPA01_P1_POST_DIV_MASK_IGD 0x00ff8000 /* IGD */
|
||||
|
||||
#define I915_FIFO_UNDERRUN_STATUS (1UL<<31)
|
||||
#define I915_CRC_ERROR_ENABLE (1UL<<29)
|
||||
@@ -435,6 +436,7 @@
|
||||
*/
|
||||
#define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000
|
||||
#define DPLL_FPA01_P1_POST_DIV_SHIFT 16
|
||||
#define DPLL_FPA01_P1_POST_DIV_SHIFT_IGD 15
|
||||
/* i830, required in DVO non-gang */
|
||||
#define PLL_P2_DIVIDE_BY_4 (1 << 23)
|
||||
#define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */
|
||||
@@ -501,10 +503,12 @@
|
||||
#define FPB0 0x06048
|
||||
#define FPB1 0x0604c
|
||||
#define FP_N_DIV_MASK 0x003f0000
|
||||
#define FP_N_IGD_DIV_MASK 0x00ff0000
|
||||
#define FP_N_DIV_SHIFT 16
|
||||
#define FP_M1_DIV_MASK 0x00003f00
|
||||
#define FP_M1_DIV_SHIFT 8
|
||||
#define FP_M2_DIV_MASK 0x0000003f
|
||||
#define FP_M2_IGD_DIV_MASK 0x000000ff
|
||||
#define FP_M2_DIV_SHIFT 0
|
||||
#define DPLL_TEST 0x606c
|
||||
#define DPLLB_TEST_SDVO_DIV_1 (0 << 22)
|
||||
@@ -629,6 +633,22 @@
|
||||
#define TV_HOTPLUG_INT_EN (1 << 18)
|
||||
#define CRT_HOTPLUG_INT_EN (1 << 9)
|
||||
#define CRT_HOTPLUG_FORCE_DETECT (1 << 3)
|
||||
#define CRT_HOTPLUG_ACTIVATION_PERIOD_32 (0 << 8)
|
||||
/* must use period 64 on GM45 according to docs */
|
||||
#define CRT_HOTPLUG_ACTIVATION_PERIOD_64 (1 << 8)
|
||||
#define CRT_HOTPLUG_DAC_ON_TIME_2M (0 << 7)
|
||||
#define CRT_HOTPLUG_DAC_ON_TIME_4M (1 << 7)
|
||||
#define CRT_HOTPLUG_VOLTAGE_COMPARE_40 (0 << 5)
|
||||
#define CRT_HOTPLUG_VOLTAGE_COMPARE_50 (1 << 5)
|
||||
#define CRT_HOTPLUG_VOLTAGE_COMPARE_60 (2 << 5)
|
||||
#define CRT_HOTPLUG_VOLTAGE_COMPARE_70 (3 << 5)
|
||||
#define CRT_HOTPLUG_VOLTAGE_COMPARE_MASK (3 << 5)
|
||||
#define CRT_HOTPLUG_DETECT_DELAY_1G (0 << 4)
|
||||
#define CRT_HOTPLUG_DETECT_DELAY_2G (1 << 4)
|
||||
#define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2)
|
||||
#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2)
|
||||
#define CRT_HOTPLUG_MASK (0x3fc) /* Bits 9-2 */
|
||||
|
||||
|
||||
#define PORT_HOTPLUG_STAT 0x61114
|
||||
#define HDMIB_HOTPLUG_INT_STATUS (1 << 29)
|
||||
@@ -856,7 +876,7 @@
|
||||
*/
|
||||
# define TV_ENC_C0_FIX (1 << 10)
|
||||
/** Bits that must be preserved by software */
|
||||
# define TV_CTL_SAVE ((3 << 8) | (3 << 6))
|
||||
# define TV_CTL_SAVE ((1 << 11) | (3 << 9) | (7 << 6) | 0xf)
|
||||
# define TV_FUSE_STATE_MASK (3 << 4)
|
||||
/** Read-only state that reports all features enabled */
|
||||
# define TV_FUSE_STATE_ENABLED (0 << 4)
|
||||
|
||||
@@ -162,13 +162,13 @@ struct bdb_lvds_options {
|
||||
u8 panel_type;
|
||||
u8 rsvd1;
|
||||
/* LVDS capabilities, stored in a dword */
|
||||
u8 rsvd2:1;
|
||||
u8 lvds_edid:1;
|
||||
u8 pixel_dither:1;
|
||||
u8 pfit_ratio_auto:1;
|
||||
u8 pfit_gfx_mode_enhanced:1;
|
||||
u8 pfit_text_mode_enhanced:1;
|
||||
u8 pfit_mode:2;
|
||||
u8 pfit_text_mode_enhanced:1;
|
||||
u8 pfit_gfx_mode_enhanced:1;
|
||||
u8 pfit_ratio_auto:1;
|
||||
u8 pixel_dither:1;
|
||||
u8 lvds_edid:1;
|
||||
u8 rsvd2:1;
|
||||
u8 rsvd4;
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
@@ -64,11 +64,21 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode)
|
||||
static int intel_crt_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
|
||||
int max_clock = 0;
|
||||
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
return MODE_NO_DBLESCAN;
|
||||
|
||||
if (mode->clock > 400000 || mode->clock < 25000)
|
||||
return MODE_CLOCK_RANGE;
|
||||
if (mode->clock < 25000)
|
||||
return MODE_CLOCK_LOW;
|
||||
|
||||
if (!IS_I9XX(dev))
|
||||
max_clock = 350000;
|
||||
else
|
||||
max_clock = 400000;
|
||||
if (mode->clock > max_clock)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
@@ -113,10 +123,13 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
|
||||
adpa |= ADPA_VSYNC_ACTIVE_HIGH;
|
||||
|
||||
if (intel_crtc->pipe == 0)
|
||||
if (intel_crtc->pipe == 0) {
|
||||
adpa |= ADPA_PIPE_A_SELECT;
|
||||
else
|
||||
I915_WRITE(BCLRPAT_A, 0);
|
||||
} else {
|
||||
adpa |= ADPA_PIPE_B_SELECT;
|
||||
I915_WRITE(BCLRPAT_B, 0);
|
||||
}
|
||||
|
||||
I915_WRITE(ADPA, adpa);
|
||||
}
|
||||
@@ -133,20 +146,39 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 temp;
|
||||
u32 hotplug_en;
|
||||
int i, tries = 0;
|
||||
/*
|
||||
* On 4 series desktop, CRT detect sequence need to be done twice
|
||||
* to get a reliable result.
|
||||
*/
|
||||
|
||||
unsigned long timeout = jiffies + msecs_to_jiffies(1000);
|
||||
if (IS_G4X(dev) && !IS_GM45(dev))
|
||||
tries = 2;
|
||||
else
|
||||
tries = 1;
|
||||
hotplug_en = I915_READ(PORT_HOTPLUG_EN);
|
||||
hotplug_en &= ~(CRT_HOTPLUG_MASK);
|
||||
hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;
|
||||
|
||||
temp = I915_READ(PORT_HOTPLUG_EN);
|
||||
if (IS_GM45(dev))
|
||||
hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
|
||||
|
||||
I915_WRITE(PORT_HOTPLUG_EN,
|
||||
temp | CRT_HOTPLUG_FORCE_DETECT | (1 << 5));
|
||||
hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
|
||||
|
||||
do {
|
||||
if (!(I915_READ(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT))
|
||||
break;
|
||||
msleep(1);
|
||||
} while (time_after(timeout, jiffies));
|
||||
for (i = 0; i < tries ; i++) {
|
||||
unsigned long timeout;
|
||||
/* turn on the FORCE_DETECT */
|
||||
I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
|
||||
timeout = jiffies + msecs_to_jiffies(1000);
|
||||
/* wait for FORCE_DETECT to go off */
|
||||
do {
|
||||
if (!(I915_READ(PORT_HOTPLUG_EN) &
|
||||
CRT_HOTPLUG_FORCE_DETECT))
|
||||
break;
|
||||
msleep(1);
|
||||
} while (time_after(timeout, jiffies));
|
||||
}
|
||||
|
||||
if ((I915_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) ==
|
||||
CRT_HOTPLUG_MONITOR_COLOR)
|
||||
|
||||
@@ -56,11 +56,13 @@ typedef struct {
|
||||
} intel_p2_t;
|
||||
|
||||
#define INTEL_P2_NUM 2
|
||||
|
||||
typedef struct {
|
||||
typedef struct intel_limit intel_limit_t;
|
||||
struct intel_limit {
|
||||
intel_range_t dot, vco, n, m, m1, m2, p, p1;
|
||||
intel_p2_t p2;
|
||||
} intel_limit_t;
|
||||
bool (* find_pll)(const intel_limit_t *, struct drm_crtc *,
|
||||
int, int, intel_clock_t *);
|
||||
};
|
||||
|
||||
#define I8XX_DOT_MIN 25000
|
||||
#define I8XX_DOT_MAX 350000
|
||||
@@ -90,18 +92,32 @@ typedef struct {
|
||||
#define I9XX_DOT_MAX 400000
|
||||
#define I9XX_VCO_MIN 1400000
|
||||
#define I9XX_VCO_MAX 2800000
|
||||
#define IGD_VCO_MIN 1700000
|
||||
#define IGD_VCO_MAX 3500000
|
||||
#define I9XX_N_MIN 1
|
||||
#define I9XX_N_MAX 6
|
||||
/* IGD's Ncounter is a ring counter */
|
||||
#define IGD_N_MIN 3
|
||||
#define IGD_N_MAX 6
|
||||
#define I9XX_M_MIN 70
|
||||
#define I9XX_M_MAX 120
|
||||
#define IGD_M_MIN 2
|
||||
#define IGD_M_MAX 256
|
||||
#define I9XX_M1_MIN 10
|
||||
#define I9XX_M1_MAX 22
|
||||
#define I9XX_M2_MIN 5
|
||||
#define I9XX_M2_MAX 9
|
||||
/* IGD M1 is reserved, and must be 0 */
|
||||
#define IGD_M1_MIN 0
|
||||
#define IGD_M1_MAX 0
|
||||
#define IGD_M2_MIN 0
|
||||
#define IGD_M2_MAX 254
|
||||
#define I9XX_P_SDVO_DAC_MIN 5
|
||||
#define I9XX_P_SDVO_DAC_MAX 80
|
||||
#define I9XX_P_LVDS_MIN 7
|
||||
#define I9XX_P_LVDS_MAX 98
|
||||
#define IGD_P_LVDS_MIN 7
|
||||
#define IGD_P_LVDS_MAX 112
|
||||
#define I9XX_P1_MIN 1
|
||||
#define I9XX_P1_MAX 8
|
||||
#define I9XX_P2_SDVO_DAC_SLOW 10
|
||||
@@ -115,6 +131,97 @@ typedef struct {
|
||||
#define INTEL_LIMIT_I8XX_LVDS 1
|
||||
#define INTEL_LIMIT_I9XX_SDVO_DAC 2
|
||||
#define INTEL_LIMIT_I9XX_LVDS 3
|
||||
#define INTEL_LIMIT_G4X_SDVO 4
|
||||
#define INTEL_LIMIT_G4X_HDMI_DAC 5
|
||||
#define INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS 6
|
||||
#define INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS 7
|
||||
#define INTEL_LIMIT_IGD_SDVO_DAC 8
|
||||
#define INTEL_LIMIT_IGD_LVDS 9
|
||||
|
||||
/*The parameter is for SDVO on G4x platform*/
|
||||
#define G4X_DOT_SDVO_MIN 25000
|
||||
#define G4X_DOT_SDVO_MAX 270000
|
||||
#define G4X_VCO_MIN 1750000
|
||||
#define G4X_VCO_MAX 3500000
|
||||
#define G4X_N_SDVO_MIN 1
|
||||
#define G4X_N_SDVO_MAX 4
|
||||
#define G4X_M_SDVO_MIN 104
|
||||
#define G4X_M_SDVO_MAX 138
|
||||
#define G4X_M1_SDVO_MIN 17
|
||||
#define G4X_M1_SDVO_MAX 23
|
||||
#define G4X_M2_SDVO_MIN 5
|
||||
#define G4X_M2_SDVO_MAX 11
|
||||
#define G4X_P_SDVO_MIN 10
|
||||
#define G4X_P_SDVO_MAX 30
|
||||
#define G4X_P1_SDVO_MIN 1
|
||||
#define G4X_P1_SDVO_MAX 3
|
||||
#define G4X_P2_SDVO_SLOW 10
|
||||
#define G4X_P2_SDVO_FAST 10
|
||||
#define G4X_P2_SDVO_LIMIT 270000
|
||||
|
||||
/*The parameter is for HDMI_DAC on G4x platform*/
|
||||
#define G4X_DOT_HDMI_DAC_MIN 22000
|
||||
#define G4X_DOT_HDMI_DAC_MAX 400000
|
||||
#define G4X_N_HDMI_DAC_MIN 1
|
||||
#define G4X_N_HDMI_DAC_MAX 4
|
||||
#define G4X_M_HDMI_DAC_MIN 104
|
||||
#define G4X_M_HDMI_DAC_MAX 138
|
||||
#define G4X_M1_HDMI_DAC_MIN 16
|
||||
#define G4X_M1_HDMI_DAC_MAX 23
|
||||
#define G4X_M2_HDMI_DAC_MIN 5
|
||||
#define G4X_M2_HDMI_DAC_MAX 11
|
||||
#define G4X_P_HDMI_DAC_MIN 5
|
||||
#define G4X_P_HDMI_DAC_MAX 80
|
||||
#define G4X_P1_HDMI_DAC_MIN 1
|
||||
#define G4X_P1_HDMI_DAC_MAX 8
|
||||
#define G4X_P2_HDMI_DAC_SLOW 10
|
||||
#define G4X_P2_HDMI_DAC_FAST 5
|
||||
#define G4X_P2_HDMI_DAC_LIMIT 165000
|
||||
|
||||
/*The parameter is for SINGLE_CHANNEL_LVDS on G4x platform*/
|
||||
#define G4X_DOT_SINGLE_CHANNEL_LVDS_MIN 20000
|
||||
#define G4X_DOT_SINGLE_CHANNEL_LVDS_MAX 115000
|
||||
#define G4X_N_SINGLE_CHANNEL_LVDS_MIN 1
|
||||
#define G4X_N_SINGLE_CHANNEL_LVDS_MAX 3
|
||||
#define G4X_M_SINGLE_CHANNEL_LVDS_MIN 104
|
||||
#define G4X_M_SINGLE_CHANNEL_LVDS_MAX 138
|
||||
#define G4X_M1_SINGLE_CHANNEL_LVDS_MIN 17
|
||||
#define G4X_M1_SINGLE_CHANNEL_LVDS_MAX 23
|
||||
#define G4X_M2_SINGLE_CHANNEL_LVDS_MIN 5
|
||||
#define G4X_M2_SINGLE_CHANNEL_LVDS_MAX 11
|
||||
#define G4X_P_SINGLE_CHANNEL_LVDS_MIN 28
|
||||
#define G4X_P_SINGLE_CHANNEL_LVDS_MAX 112
|
||||
#define G4X_P1_SINGLE_CHANNEL_LVDS_MIN 2
|
||||
#define G4X_P1_SINGLE_CHANNEL_LVDS_MAX 8
|
||||
#define G4X_P2_SINGLE_CHANNEL_LVDS_SLOW 14
|
||||
#define G4X_P2_SINGLE_CHANNEL_LVDS_FAST 14
|
||||
#define G4X_P2_SINGLE_CHANNEL_LVDS_LIMIT 0
|
||||
|
||||
/*The parameter is for DUAL_CHANNEL_LVDS on G4x platform*/
|
||||
#define G4X_DOT_DUAL_CHANNEL_LVDS_MIN 80000
|
||||
#define G4X_DOT_DUAL_CHANNEL_LVDS_MAX 224000
|
||||
#define G4X_N_DUAL_CHANNEL_LVDS_MIN 1
|
||||
#define G4X_N_DUAL_CHANNEL_LVDS_MAX 3
|
||||
#define G4X_M_DUAL_CHANNEL_LVDS_MIN 104
|
||||
#define G4X_M_DUAL_CHANNEL_LVDS_MAX 138
|
||||
#define G4X_M1_DUAL_CHANNEL_LVDS_MIN 17
|
||||
#define G4X_M1_DUAL_CHANNEL_LVDS_MAX 23
|
||||
#define G4X_M2_DUAL_CHANNEL_LVDS_MIN 5
|
||||
#define G4X_M2_DUAL_CHANNEL_LVDS_MAX 11
|
||||
#define G4X_P_DUAL_CHANNEL_LVDS_MIN 14
|
||||
#define G4X_P_DUAL_CHANNEL_LVDS_MAX 42
|
||||
#define G4X_P1_DUAL_CHANNEL_LVDS_MIN 2
|
||||
#define G4X_P1_DUAL_CHANNEL_LVDS_MAX 6
|
||||
#define G4X_P2_DUAL_CHANNEL_LVDS_SLOW 7
|
||||
#define G4X_P2_DUAL_CHANNEL_LVDS_FAST 7
|
||||
#define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT 0
|
||||
|
||||
static bool
|
||||
intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
||||
int target, int refclk, intel_clock_t *best_clock);
|
||||
static bool
|
||||
intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
||||
int target, int refclk, intel_clock_t *best_clock);
|
||||
|
||||
static const intel_limit_t intel_limits[] = {
|
||||
{ /* INTEL_LIMIT_I8XX_DVO_DAC */
|
||||
@@ -128,6 +235,7 @@ static const intel_limit_t intel_limits[] = {
|
||||
.p1 = { .min = I8XX_P1_MIN, .max = I8XX_P1_MAX },
|
||||
.p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT,
|
||||
.p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST },
|
||||
.find_pll = intel_find_best_PLL,
|
||||
},
|
||||
{ /* INTEL_LIMIT_I8XX_LVDS */
|
||||
.dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX },
|
||||
@@ -140,6 +248,7 @@ static const intel_limit_t intel_limits[] = {
|
||||
.p1 = { .min = I8XX_P1_LVDS_MIN, .max = I8XX_P1_LVDS_MAX },
|
||||
.p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT,
|
||||
.p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST },
|
||||
.find_pll = intel_find_best_PLL,
|
||||
},
|
||||
{ /* INTEL_LIMIT_I9XX_SDVO_DAC */
|
||||
.dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX },
|
||||
@@ -152,6 +261,7 @@ static const intel_limit_t intel_limits[] = {
|
||||
.p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX },
|
||||
.p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
|
||||
.p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST },
|
||||
.find_pll = intel_find_best_PLL,
|
||||
},
|
||||
{ /* INTEL_LIMIT_I9XX_LVDS */
|
||||
.dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX },
|
||||
@@ -167,19 +277,157 @@ static const intel_limit_t intel_limits[] = {
|
||||
*/
|
||||
.p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
|
||||
.p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST },
|
||||
.find_pll = intel_find_best_PLL,
|
||||
},
|
||||
/* below parameter and function is for G4X Chipset Family*/
|
||||
{ /* INTEL_LIMIT_G4X_SDVO */
|
||||
.dot = { .min = G4X_DOT_SDVO_MIN, .max = G4X_DOT_SDVO_MAX },
|
||||
.vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX},
|
||||
.n = { .min = G4X_N_SDVO_MIN, .max = G4X_N_SDVO_MAX },
|
||||
.m = { .min = G4X_M_SDVO_MIN, .max = G4X_M_SDVO_MAX },
|
||||
.m1 = { .min = G4X_M1_SDVO_MIN, .max = G4X_M1_SDVO_MAX },
|
||||
.m2 = { .min = G4X_M2_SDVO_MIN, .max = G4X_M2_SDVO_MAX },
|
||||
.p = { .min = G4X_P_SDVO_MIN, .max = G4X_P_SDVO_MAX },
|
||||
.p1 = { .min = G4X_P1_SDVO_MIN, .max = G4X_P1_SDVO_MAX},
|
||||
.p2 = { .dot_limit = G4X_P2_SDVO_LIMIT,
|
||||
.p2_slow = G4X_P2_SDVO_SLOW,
|
||||
.p2_fast = G4X_P2_SDVO_FAST
|
||||
},
|
||||
.find_pll = intel_g4x_find_best_PLL,
|
||||
},
|
||||
{ /* INTEL_LIMIT_G4X_HDMI_DAC */
|
||||
.dot = { .min = G4X_DOT_HDMI_DAC_MIN, .max = G4X_DOT_HDMI_DAC_MAX },
|
||||
.vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX},
|
||||
.n = { .min = G4X_N_HDMI_DAC_MIN, .max = G4X_N_HDMI_DAC_MAX },
|
||||
.m = { .min = G4X_M_HDMI_DAC_MIN, .max = G4X_M_HDMI_DAC_MAX },
|
||||
.m1 = { .min = G4X_M1_HDMI_DAC_MIN, .max = G4X_M1_HDMI_DAC_MAX },
|
||||
.m2 = { .min = G4X_M2_HDMI_DAC_MIN, .max = G4X_M2_HDMI_DAC_MAX },
|
||||
.p = { .min = G4X_P_HDMI_DAC_MIN, .max = G4X_P_HDMI_DAC_MAX },
|
||||
.p1 = { .min = G4X_P1_HDMI_DAC_MIN, .max = G4X_P1_HDMI_DAC_MAX},
|
||||
.p2 = { .dot_limit = G4X_P2_HDMI_DAC_LIMIT,
|
||||
.p2_slow = G4X_P2_HDMI_DAC_SLOW,
|
||||
.p2_fast = G4X_P2_HDMI_DAC_FAST
|
||||
},
|
||||
.find_pll = intel_g4x_find_best_PLL,
|
||||
},
|
||||
{ /* INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS */
|
||||
.dot = { .min = G4X_DOT_SINGLE_CHANNEL_LVDS_MIN,
|
||||
.max = G4X_DOT_SINGLE_CHANNEL_LVDS_MAX },
|
||||
.vco = { .min = G4X_VCO_MIN,
|
||||
.max = G4X_VCO_MAX },
|
||||
.n = { .min = G4X_N_SINGLE_CHANNEL_LVDS_MIN,
|
||||
.max = G4X_N_SINGLE_CHANNEL_LVDS_MAX },
|
||||
.m = { .min = G4X_M_SINGLE_CHANNEL_LVDS_MIN,
|
||||
.max = G4X_M_SINGLE_CHANNEL_LVDS_MAX },
|
||||
.m1 = { .min = G4X_M1_SINGLE_CHANNEL_LVDS_MIN,
|
||||
.max = G4X_M1_SINGLE_CHANNEL_LVDS_MAX },
|
||||
.m2 = { .min = G4X_M2_SINGLE_CHANNEL_LVDS_MIN,
|
||||
.max = G4X_M2_SINGLE_CHANNEL_LVDS_MAX },
|
||||
.p = { .min = G4X_P_SINGLE_CHANNEL_LVDS_MIN,
|
||||
.max = G4X_P_SINGLE_CHANNEL_LVDS_MAX },
|
||||
.p1 = { .min = G4X_P1_SINGLE_CHANNEL_LVDS_MIN,
|
||||
.max = G4X_P1_SINGLE_CHANNEL_LVDS_MAX },
|
||||
.p2 = { .dot_limit = G4X_P2_SINGLE_CHANNEL_LVDS_LIMIT,
|
||||
.p2_slow = G4X_P2_SINGLE_CHANNEL_LVDS_SLOW,
|
||||
.p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST
|
||||
},
|
||||
.find_pll = intel_g4x_find_best_PLL,
|
||||
},
|
||||
{ /* INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS */
|
||||
.dot = { .min = G4X_DOT_DUAL_CHANNEL_LVDS_MIN,
|
||||
.max = G4X_DOT_DUAL_CHANNEL_LVDS_MAX },
|
||||
.vco = { .min = G4X_VCO_MIN,
|
||||
.max = G4X_VCO_MAX },
|
||||
.n = { .min = G4X_N_DUAL_CHANNEL_LVDS_MIN,
|
||||
.max = G4X_N_DUAL_CHANNEL_LVDS_MAX },
|
||||
.m = { .min = G4X_M_DUAL_CHANNEL_LVDS_MIN,
|
||||
.max = G4X_M_DUAL_CHANNEL_LVDS_MAX },
|
||||
.m1 = { .min = G4X_M1_DUAL_CHANNEL_LVDS_MIN,
|
||||
.max = G4X_M1_DUAL_CHANNEL_LVDS_MAX },
|
||||
.m2 = { .min = G4X_M2_DUAL_CHANNEL_LVDS_MIN,
|
||||
.max = G4X_M2_DUAL_CHANNEL_LVDS_MAX },
|
||||
.p = { .min = G4X_P_DUAL_CHANNEL_LVDS_MIN,
|
||||
.max = G4X_P_DUAL_CHANNEL_LVDS_MAX },
|
||||
.p1 = { .min = G4X_P1_DUAL_CHANNEL_LVDS_MIN,
|
||||
.max = G4X_P1_DUAL_CHANNEL_LVDS_MAX },
|
||||
.p2 = { .dot_limit = G4X_P2_DUAL_CHANNEL_LVDS_LIMIT,
|
||||
.p2_slow = G4X_P2_DUAL_CHANNEL_LVDS_SLOW,
|
||||
.p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST
|
||||
},
|
||||
.find_pll = intel_g4x_find_best_PLL,
|
||||
},
|
||||
{ /* INTEL_LIMIT_IGD_SDVO */
|
||||
.dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX},
|
||||
.vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX },
|
||||
.n = { .min = IGD_N_MIN, .max = IGD_N_MAX },
|
||||
.m = { .min = IGD_M_MIN, .max = IGD_M_MAX },
|
||||
.m1 = { .min = IGD_M1_MIN, .max = IGD_M1_MAX },
|
||||
.m2 = { .min = IGD_M2_MIN, .max = IGD_M2_MAX },
|
||||
.p = { .min = I9XX_P_SDVO_DAC_MIN, .max = I9XX_P_SDVO_DAC_MAX },
|
||||
.p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX },
|
||||
.p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
|
||||
.p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST },
|
||||
},
|
||||
{ /* INTEL_LIMIT_IGD_LVDS */
|
||||
.dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX },
|
||||
.vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX },
|
||||
.n = { .min = IGD_N_MIN, .max = IGD_N_MAX },
|
||||
.m = { .min = IGD_M_MIN, .max = IGD_M_MAX },
|
||||
.m1 = { .min = IGD_M1_MIN, .max = IGD_M1_MAX },
|
||||
.m2 = { .min = IGD_M2_MIN, .max = IGD_M2_MAX },
|
||||
.p = { .min = IGD_P_LVDS_MIN, .max = IGD_P_LVDS_MAX },
|
||||
.p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX },
|
||||
/* IGD only supports single-channel mode. */
|
||||
.p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
|
||||
.p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW },
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
const intel_limit_t *limit;
|
||||
|
||||
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
|
||||
if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
|
||||
LVDS_CLKB_POWER_UP)
|
||||
/* LVDS with dual channel */
|
||||
limit = &intel_limits
|
||||
[INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS];
|
||||
else
|
||||
/* LVDS with dual channel */
|
||||
limit = &intel_limits
|
||||
[INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS];
|
||||
} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI) ||
|
||||
intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) {
|
||||
limit = &intel_limits[INTEL_LIMIT_G4X_HDMI_DAC];
|
||||
} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) {
|
||||
limit = &intel_limits[INTEL_LIMIT_G4X_SDVO];
|
||||
} else /* The option is for other outputs */
|
||||
limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC];
|
||||
|
||||
return limit;
|
||||
}
|
||||
|
||||
static const intel_limit_t *intel_limit(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
const intel_limit_t *limit;
|
||||
|
||||
if (IS_I9XX(dev)) {
|
||||
if (IS_G4X(dev)) {
|
||||
limit = intel_g4x_limit(crtc);
|
||||
} else if (IS_I9XX(dev) && !IS_IGD(dev)) {
|
||||
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
|
||||
limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS];
|
||||
else
|
||||
limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC];
|
||||
} else if (IS_IGD(dev)) {
|
||||
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
|
||||
limit = &intel_limits[INTEL_LIMIT_IGD_LVDS];
|
||||
else
|
||||
limit = &intel_limits[INTEL_LIMIT_IGD_SDVO_DAC];
|
||||
} else {
|
||||
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
|
||||
limit = &intel_limits[INTEL_LIMIT_I8XX_LVDS];
|
||||
@@ -189,8 +437,21 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc)
|
||||
return limit;
|
||||
}
|
||||
|
||||
static void intel_clock(int refclk, intel_clock_t *clock)
|
||||
/* m1 is reserved as 0 in IGD, n is a ring counter */
|
||||
static void igd_clock(int refclk, intel_clock_t *clock)
|
||||
{
|
||||
clock->m = clock->m2 + 2;
|
||||
clock->p = clock->p1 * clock->p2;
|
||||
clock->vco = refclk * clock->m / clock->n;
|
||||
clock->dot = clock->vco / clock->p;
|
||||
}
|
||||
|
||||
static void intel_clock(struct drm_device *dev, int refclk, intel_clock_t *clock)
|
||||
{
|
||||
if (IS_IGD(dev)) {
|
||||
igd_clock(refclk, clock);
|
||||
return;
|
||||
}
|
||||
clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
|
||||
clock->p = clock->p1 * clock->p2;
|
||||
clock->vco = refclk * clock->m / (clock->n + 2);
|
||||
@@ -226,6 +487,7 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type)
|
||||
static bool intel_PLL_is_valid(struct drm_crtc *crtc, intel_clock_t *clock)
|
||||
{
|
||||
const intel_limit_t *limit = intel_limit (crtc);
|
||||
struct drm_device *dev = crtc->dev;
|
||||
|
||||
if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1)
|
||||
INTELPllInvalid ("p1 out of range\n");
|
||||
@@ -235,7 +497,7 @@ static bool intel_PLL_is_valid(struct drm_crtc *crtc, intel_clock_t *clock)
|
||||
INTELPllInvalid ("m2 out of range\n");
|
||||
if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1)
|
||||
INTELPllInvalid ("m1 out of range\n");
|
||||
if (clock->m1 <= clock->m2)
|
||||
if (clock->m1 <= clock->m2 && !IS_IGD(dev))
|
||||
INTELPllInvalid ("m1 <= m2\n");
|
||||
if (clock->m < limit->m.min || limit->m.max < clock->m)
|
||||
INTELPllInvalid ("m out of range\n");
|
||||
@@ -252,18 +514,14 @@ static bool intel_PLL_is_valid(struct drm_crtc *crtc, intel_clock_t *clock)
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a set of divisors for the desired target clock with the given
|
||||
* refclk, or FALSE. The returned values represent the clock equation:
|
||||
* reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
|
||||
*/
|
||||
static bool intel_find_best_PLL(struct drm_crtc *crtc, int target,
|
||||
int refclk, intel_clock_t *best_clock)
|
||||
static bool
|
||||
intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
||||
int target, int refclk, intel_clock_t *best_clock)
|
||||
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
intel_clock_t clock;
|
||||
const intel_limit_t *limit = intel_limit(crtc);
|
||||
int err = target;
|
||||
|
||||
if (IS_I9XX(dev) && intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
|
||||
@@ -289,15 +547,17 @@ static bool intel_find_best_PLL(struct drm_crtc *crtc, int target,
|
||||
memset (best_clock, 0, sizeof (*best_clock));
|
||||
|
||||
for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) {
|
||||
for (clock.m2 = limit->m2.min; clock.m2 < clock.m1 &&
|
||||
clock.m2 <= limit->m2.max; clock.m2++) {
|
||||
for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max; clock.m2++) {
|
||||
/* m1 is always 0 in IGD */
|
||||
if (clock.m2 >= clock.m1 && !IS_IGD(dev))
|
||||
break;
|
||||
for (clock.n = limit->n.min; clock.n <= limit->n.max;
|
||||
clock.n++) {
|
||||
for (clock.p1 = limit->p1.min;
|
||||
clock.p1 <= limit->p1.max; clock.p1++) {
|
||||
int this_err;
|
||||
|
||||
intel_clock(refclk, &clock);
|
||||
intel_clock(dev, refclk, &clock);
|
||||
|
||||
if (!intel_PLL_is_valid(crtc, &clock))
|
||||
continue;
|
||||
@@ -315,6 +575,63 @@ static bool intel_find_best_PLL(struct drm_crtc *crtc, int target,
|
||||
return (err != target);
|
||||
}
|
||||
|
||||
static bool
|
||||
intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
||||
int target, int refclk, intel_clock_t *best_clock)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
intel_clock_t clock;
|
||||
int max_n;
|
||||
bool found;
|
||||
/* approximately equals target * 0.00488 */
|
||||
int err_most = (target >> 8) + (target >> 10);
|
||||
found = false;
|
||||
|
||||
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
|
||||
if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
|
||||
LVDS_CLKB_POWER_UP)
|
||||
clock.p2 = limit->p2.p2_fast;
|
||||
else
|
||||
clock.p2 = limit->p2.p2_slow;
|
||||
} else {
|
||||
if (target < limit->p2.dot_limit)
|
||||
clock.p2 = limit->p2.p2_slow;
|
||||
else
|
||||
clock.p2 = limit->p2.p2_fast;
|
||||
}
|
||||
|
||||
memset(best_clock, 0, sizeof(*best_clock));
|
||||
max_n = limit->n.max;
|
||||
/* based on hardware requriment prefer smaller n to precision */
|
||||
for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
|
||||
/* based on hardware requirment prefere larger m1,m2, p1 */
|
||||
for (clock.m1 = limit->m1.max;
|
||||
clock.m1 >= limit->m1.min; clock.m1--) {
|
||||
for (clock.m2 = limit->m2.max;
|
||||
clock.m2 >= limit->m2.min; clock.m2--) {
|
||||
for (clock.p1 = limit->p1.max;
|
||||
clock.p1 >= limit->p1.min; clock.p1--) {
|
||||
int this_err;
|
||||
|
||||
intel_clock(dev, refclk, &clock);
|
||||
if (!intel_PLL_is_valid(crtc, &clock))
|
||||
continue;
|
||||
this_err = abs(clock.dot - target) ;
|
||||
if (this_err < err_most) {
|
||||
*best_clock = clock;
|
||||
err_most = this_err;
|
||||
max_n = clock.n;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
void
|
||||
intel_wait_for_vblank(struct drm_device *dev)
|
||||
{
|
||||
@@ -634,7 +951,7 @@ static int intel_get_core_clock_speed(struct drm_device *dev)
|
||||
return 400000;
|
||||
else if (IS_I915G(dev))
|
||||
return 333000;
|
||||
else if (IS_I945GM(dev) || IS_845G(dev))
|
||||
else if (IS_I945GM(dev) || IS_845G(dev) || IS_IGDGM(dev))
|
||||
return 200000;
|
||||
else if (IS_I915GM(dev)) {
|
||||
u16 gcfgc = 0;
|
||||
@@ -733,6 +1050,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
bool is_crt = false, is_lvds = false, is_tv = false;
|
||||
struct drm_mode_config *mode_config = &dev->mode_config;
|
||||
struct drm_connector *connector;
|
||||
const intel_limit_t *limit;
|
||||
int ret;
|
||||
|
||||
drm_vblank_pre_modeset(dev, pipe);
|
||||
@@ -776,13 +1094,22 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
refclk = 48000;
|
||||
}
|
||||
|
||||
ok = intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, &clock);
|
||||
/*
|
||||
* Returns a set of divisors for the desired target clock with the given
|
||||
* refclk, or FALSE. The returned values represent the clock equation:
|
||||
* reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
|
||||
*/
|
||||
limit = intel_limit(crtc);
|
||||
ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock);
|
||||
if (!ok) {
|
||||
DRM_ERROR("Couldn't find PLL settings for mode!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
|
||||
if (IS_IGD(dev))
|
||||
fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2;
|
||||
else
|
||||
fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
|
||||
|
||||
dpll = DPLL_VGA_MODE_DIS;
|
||||
if (IS_I9XX(dev)) {
|
||||
@@ -799,7 +1126,10 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
}
|
||||
|
||||
/* compute bitmask from p1 value */
|
||||
dpll |= (1 << (clock.p1 - 1)) << 16;
|
||||
if (IS_IGD(dev))
|
||||
dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_IGD;
|
||||
else
|
||||
dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
|
||||
switch (clock.p2) {
|
||||
case 5:
|
||||
dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
|
||||
@@ -1279,10 +1609,20 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
|
||||
fp = I915_READ((pipe == 0) ? FPA1 : FPB1);
|
||||
|
||||
clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
|
||||
clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
|
||||
clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
|
||||
if (IS_IGD(dev)) {
|
||||
clock.n = ffs((fp & FP_N_IGD_DIV_MASK) >> FP_N_DIV_SHIFT) - 1;
|
||||
clock.m2 = (fp & FP_M2_IGD_DIV_MASK) >> FP_M2_DIV_SHIFT;
|
||||
} else {
|
||||
clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
|
||||
clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
|
||||
}
|
||||
|
||||
if (IS_I9XX(dev)) {
|
||||
clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >>
|
||||
if (IS_IGD(dev))
|
||||
clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_IGD) >>
|
||||
DPLL_FPA01_P1_POST_DIV_SHIFT_IGD);
|
||||
else
|
||||
clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >>
|
||||
DPLL_FPA01_P1_POST_DIV_SHIFT);
|
||||
|
||||
switch (dpll & DPLL_MODE_MASK) {
|
||||
@@ -1301,7 +1641,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
|
||||
}
|
||||
|
||||
/* XXX: Handle the 100Mhz refclk */
|
||||
intel_clock(96000, &clock);
|
||||
intel_clock(dev, 96000, &clock);
|
||||
} else {
|
||||
bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN);
|
||||
|
||||
@@ -1313,9 +1653,9 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
|
||||
if ((dpll & PLL_REF_INPUT_MASK) ==
|
||||
PLLB_REF_INPUT_SPREADSPECTRUMIN) {
|
||||
/* XXX: might not be 66MHz */
|
||||
intel_clock(66000, &clock);
|
||||
intel_clock(dev, 66000, &clock);
|
||||
} else
|
||||
intel_clock(48000, &clock);
|
||||
intel_clock(dev, 48000, &clock);
|
||||
} else {
|
||||
if (dpll & PLL_P1_DIVIDE_BY_TWO)
|
||||
clock.p1 = 2;
|
||||
@@ -1328,7 +1668,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
|
||||
else
|
||||
clock.p2 = 2;
|
||||
|
||||
intel_clock(48000, &clock);
|
||||
intel_clock(dev, 48000, &clock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1474,13 +1814,21 @@ static void intel_setup_outputs(struct drm_device *dev)
|
||||
|
||||
if (IS_I9XX(dev)) {
|
||||
int found;
|
||||
u32 reg;
|
||||
|
||||
if (I915_READ(SDVOB) & SDVO_DETECTED) {
|
||||
found = intel_sdvo_init(dev, SDVOB);
|
||||
if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
|
||||
intel_hdmi_init(dev, SDVOB);
|
||||
}
|
||||
if (!IS_G4X(dev) || (I915_READ(SDVOB) & SDVO_DETECTED)) {
|
||||
|
||||
/* Before G4X SDVOC doesn't have its own detect register */
|
||||
if (IS_G4X(dev))
|
||||
reg = SDVOC;
|
||||
else
|
||||
reg = SDVOB;
|
||||
|
||||
if (I915_READ(reg) & SDVO_DETECTED) {
|
||||
found = intel_sdvo_init(dev, SDVOC);
|
||||
if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
|
||||
intel_hdmi_init(dev, SDVOC);
|
||||
|
||||
@@ -265,7 +265,7 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
|
||||
pfit_control = 0;
|
||||
|
||||
if (!IS_I965G(dev)) {
|
||||
if (dev_priv->panel_wants_dither)
|
||||
if (dev_priv->panel_wants_dither || dev_priv->lvds_dither)
|
||||
pfit_control |= PANEL_8TO6_DITHER_ENABLE;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -217,8 +217,8 @@ static const u32 filter_table[] = {
|
||||
*/
|
||||
static const struct color_conversion ntsc_m_csc_composite = {
|
||||
.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0104,
|
||||
.ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0f00,
|
||||
.rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0f00,
|
||||
.ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0200,
|
||||
.rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0200,
|
||||
};
|
||||
|
||||
static const struct video_levels ntsc_m_levels_composite = {
|
||||
@@ -226,9 +226,9 @@ static const struct video_levels ntsc_m_levels_composite = {
|
||||
};
|
||||
|
||||
static const struct color_conversion ntsc_m_csc_svideo = {
|
||||
.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0134,
|
||||
.ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0f00,
|
||||
.rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0f00,
|
||||
.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0133,
|
||||
.ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0200,
|
||||
.rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0200,
|
||||
};
|
||||
|
||||
static const struct video_levels ntsc_m_levels_svideo = {
|
||||
@@ -237,8 +237,8 @@ static const struct video_levels ntsc_m_levels_svideo = {
|
||||
|
||||
static const struct color_conversion ntsc_j_csc_composite = {
|
||||
.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0119,
|
||||
.ru = 0x074c, .gu = 0x0546, .bu = 0x05ec, .au = 0x0f00,
|
||||
.rv = 0x035a, .gv = 0x0322, .bv = 0x06e1, .av = 0x0f00,
|
||||
.ru = 0x074c, .gu = 0x0546, .bu = 0x05ec, .au = 0x0200,
|
||||
.rv = 0x035a, .gv = 0x0322, .bv = 0x06e1, .av = 0x0200,
|
||||
};
|
||||
|
||||
static const struct video_levels ntsc_j_levels_composite = {
|
||||
@@ -247,8 +247,8 @@ static const struct video_levels ntsc_j_levels_composite = {
|
||||
|
||||
static const struct color_conversion ntsc_j_csc_svideo = {
|
||||
.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x014c,
|
||||
.ru = 0x0788, .gu = 0x0581, .bu = 0x0322, .au = 0x0f00,
|
||||
.rv = 0x0399, .gv = 0x0356, .bv = 0x070a, .av = 0x0f00,
|
||||
.ru = 0x0788, .gu = 0x0581, .bu = 0x0322, .au = 0x0200,
|
||||
.rv = 0x0399, .gv = 0x0356, .bv = 0x070a, .av = 0x0200,
|
||||
};
|
||||
|
||||
static const struct video_levels ntsc_j_levels_svideo = {
|
||||
@@ -257,8 +257,8 @@ static const struct video_levels ntsc_j_levels_svideo = {
|
||||
|
||||
static const struct color_conversion pal_csc_composite = {
|
||||
.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0113,
|
||||
.ru = 0x0745, .gu = 0x053f, .bu = 0x05e1, .au = 0x0f00,
|
||||
.rv = 0x0353, .gv = 0x031c, .bv = 0x06dc, .av = 0x0f00,
|
||||
.ru = 0x0745, .gu = 0x053f, .bu = 0x05e1, .au = 0x0200,
|
||||
.rv = 0x0353, .gv = 0x031c, .bv = 0x06dc, .av = 0x0200,
|
||||
};
|
||||
|
||||
static const struct video_levels pal_levels_composite = {
|
||||
@@ -267,8 +267,8 @@ static const struct video_levels pal_levels_composite = {
|
||||
|
||||
static const struct color_conversion pal_csc_svideo = {
|
||||
.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0145,
|
||||
.ru = 0x0780, .gu = 0x0579, .bu = 0x031c, .au = 0x0f00,
|
||||
.rv = 0x0390, .gv = 0x034f, .bv = 0x0705, .av = 0x0f00,
|
||||
.ru = 0x0780, .gu = 0x0579, .bu = 0x031c, .au = 0x0200,
|
||||
.rv = 0x0390, .gv = 0x034f, .bv = 0x0705, .av = 0x0200,
|
||||
};
|
||||
|
||||
static const struct video_levels pal_levels_svideo = {
|
||||
@@ -277,8 +277,8 @@ static const struct video_levels pal_levels_svideo = {
|
||||
|
||||
static const struct color_conversion pal_m_csc_composite = {
|
||||
.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0104,
|
||||
.ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0f00,
|
||||
.rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0f00,
|
||||
.ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0200,
|
||||
.rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0200,
|
||||
};
|
||||
|
||||
static const struct video_levels pal_m_levels_composite = {
|
||||
@@ -286,9 +286,9 @@ static const struct video_levels pal_m_levels_composite = {
|
||||
};
|
||||
|
||||
static const struct color_conversion pal_m_csc_svideo = {
|
||||
.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0134,
|
||||
.ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0f00,
|
||||
.rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0f00,
|
||||
.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0133,
|
||||
.ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0200,
|
||||
.rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0200,
|
||||
};
|
||||
|
||||
static const struct video_levels pal_m_levels_svideo = {
|
||||
@@ -297,8 +297,8 @@ static const struct video_levels pal_m_levels_svideo = {
|
||||
|
||||
static const struct color_conversion pal_n_csc_composite = {
|
||||
.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0104,
|
||||
.ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0f00,
|
||||
.rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0f00,
|
||||
.ru = 0x0733, .gu = 0x052d, .bu = 0x05c7, .au = 0x0200,
|
||||
.rv = 0x0340, .gv = 0x030c, .bv = 0x06d0, .av = 0x0200,
|
||||
};
|
||||
|
||||
static const struct video_levels pal_n_levels_composite = {
|
||||
@@ -306,9 +306,9 @@ static const struct video_levels pal_n_levels_composite = {
|
||||
};
|
||||
|
||||
static const struct color_conversion pal_n_csc_svideo = {
|
||||
.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0134,
|
||||
.ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0f00,
|
||||
.rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0f00,
|
||||
.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0133,
|
||||
.ru = 0x076a, .gu = 0x0564, .bu = 0x030d, .au = 0x0200,
|
||||
.rv = 0x037a, .gv = 0x033d, .bv = 0x06f6, .av = 0x0200,
|
||||
};
|
||||
|
||||
static const struct video_levels pal_n_levels_svideo = {
|
||||
@@ -319,9 +319,9 @@ static const struct video_levels pal_n_levels_svideo = {
|
||||
* Component connections
|
||||
*/
|
||||
static const struct color_conversion sdtv_csc_yprpb = {
|
||||
.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0146,
|
||||
.ru = 0x0559, .gu = 0x0353, .bu = 0x0100, .au = 0x0f00,
|
||||
.rv = 0x0100, .gv = 0x03ad, .bv = 0x074d, .av = 0x0f00,
|
||||
.ry = 0x0332, .gy = 0x012d, .by = 0x07d3, .ay = 0x0145,
|
||||
.ru = 0x0559, .gu = 0x0353, .bu = 0x0100, .au = 0x0200,
|
||||
.rv = 0x0100, .gv = 0x03ad, .bv = 0x074d, .av = 0x0200,
|
||||
};
|
||||
|
||||
static const struct color_conversion sdtv_csc_rgb = {
|
||||
@@ -331,9 +331,9 @@ static const struct color_conversion sdtv_csc_rgb = {
|
||||
};
|
||||
|
||||
static const struct color_conversion hdtv_csc_yprpb = {
|
||||
.ry = 0x05b3, .gy = 0x016e, .by = 0x0728, .ay = 0x0146,
|
||||
.ru = 0x07d5, .gu = 0x038b, .bu = 0x0100, .au = 0x0f00,
|
||||
.rv = 0x0100, .gv = 0x03d1, .bv = 0x06bc, .av = 0x0f00,
|
||||
.ry = 0x05b3, .gy = 0x016e, .by = 0x0728, .ay = 0x0145,
|
||||
.ru = 0x07d5, .gu = 0x038b, .bu = 0x0100, .au = 0x0200,
|
||||
.rv = 0x0100, .gv = 0x03d1, .bv = 0x06bc, .av = 0x0200,
|
||||
};
|
||||
|
||||
static const struct color_conversion hdtv_csc_rgb = {
|
||||
@@ -414,7 +414,7 @@ struct tv_mode {
|
||||
static const struct tv_mode tv_modes[] = {
|
||||
{
|
||||
.name = "NTSC-M",
|
||||
.clock = 107520,
|
||||
.clock = 108000,
|
||||
.refresh = 29970,
|
||||
.oversample = TV_OVERSAMPLE_8X,
|
||||
.component_only = 0,
|
||||
@@ -442,8 +442,8 @@ static const struct tv_mode tv_modes[] = {
|
||||
.vburst_start_f4 = 10, .vburst_end_f4 = 240,
|
||||
|
||||
/* desired 3.5800000 actual 3.5800000 clock 107.52 */
|
||||
.dda1_inc = 136,
|
||||
.dda2_inc = 7624, .dda2_size = 20013,
|
||||
.dda1_inc = 135,
|
||||
.dda2_inc = 20800, .dda2_size = 27456,
|
||||
.dda3_inc = 0, .dda3_size = 0,
|
||||
.sc_reset = TV_SC_RESET_EVERY_4,
|
||||
.pal_burst = false,
|
||||
@@ -457,7 +457,7 @@ static const struct tv_mode tv_modes[] = {
|
||||
},
|
||||
{
|
||||
.name = "NTSC-443",
|
||||
.clock = 107520,
|
||||
.clock = 108000,
|
||||
.refresh = 29970,
|
||||
.oversample = TV_OVERSAMPLE_8X,
|
||||
.component_only = 0,
|
||||
@@ -485,10 +485,10 @@ static const struct tv_mode tv_modes[] = {
|
||||
|
||||
/* desired 4.4336180 actual 4.4336180 clock 107.52 */
|
||||
.dda1_inc = 168,
|
||||
.dda2_inc = 18557, .dda2_size = 20625,
|
||||
.dda3_inc = 0, .dda3_size = 0,
|
||||
.sc_reset = TV_SC_RESET_EVERY_8,
|
||||
.pal_burst = true,
|
||||
.dda2_inc = 4093, .dda2_size = 27456,
|
||||
.dda3_inc = 310, .dda3_size = 525,
|
||||
.sc_reset = TV_SC_RESET_NEVER,
|
||||
.pal_burst = false,
|
||||
|
||||
.composite_levels = &ntsc_m_levels_composite,
|
||||
.composite_color = &ntsc_m_csc_composite,
|
||||
@@ -499,7 +499,7 @@ static const struct tv_mode tv_modes[] = {
|
||||
},
|
||||
{
|
||||
.name = "NTSC-J",
|
||||
.clock = 107520,
|
||||
.clock = 108000,
|
||||
.refresh = 29970,
|
||||
.oversample = TV_OVERSAMPLE_8X,
|
||||
.component_only = 0,
|
||||
@@ -527,8 +527,8 @@ static const struct tv_mode tv_modes[] = {
|
||||
.vburst_start_f4 = 10, .vburst_end_f4 = 240,
|
||||
|
||||
/* desired 3.5800000 actual 3.5800000 clock 107.52 */
|
||||
.dda1_inc = 136,
|
||||
.dda2_inc = 7624, .dda2_size = 20013,
|
||||
.dda1_inc = 135,
|
||||
.dda2_inc = 20800, .dda2_size = 27456,
|
||||
.dda3_inc = 0, .dda3_size = 0,
|
||||
.sc_reset = TV_SC_RESET_EVERY_4,
|
||||
.pal_burst = false,
|
||||
@@ -542,7 +542,7 @@ static const struct tv_mode tv_modes[] = {
|
||||
},
|
||||
{
|
||||
.name = "PAL-M",
|
||||
.clock = 107520,
|
||||
.clock = 108000,
|
||||
.refresh = 29970,
|
||||
.oversample = TV_OVERSAMPLE_8X,
|
||||
.component_only = 0,
|
||||
@@ -570,11 +570,11 @@ static const struct tv_mode tv_modes[] = {
|
||||
.vburst_start_f4 = 10, .vburst_end_f4 = 240,
|
||||
|
||||
/* desired 3.5800000 actual 3.5800000 clock 107.52 */
|
||||
.dda1_inc = 136,
|
||||
.dda2_inc = 7624, .dda2_size = 20013,
|
||||
.dda1_inc = 135,
|
||||
.dda2_inc = 16704, .dda2_size = 27456,
|
||||
.dda3_inc = 0, .dda3_size = 0,
|
||||
.sc_reset = TV_SC_RESET_EVERY_4,
|
||||
.pal_burst = false,
|
||||
.sc_reset = TV_SC_RESET_EVERY_8,
|
||||
.pal_burst = true,
|
||||
|
||||
.composite_levels = &pal_m_levels_composite,
|
||||
.composite_color = &pal_m_csc_composite,
|
||||
@@ -586,7 +586,7 @@ static const struct tv_mode tv_modes[] = {
|
||||
{
|
||||
/* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
|
||||
.name = "PAL-N",
|
||||
.clock = 107520,
|
||||
.clock = 108000,
|
||||
.refresh = 25000,
|
||||
.oversample = TV_OVERSAMPLE_8X,
|
||||
.component_only = 0,
|
||||
@@ -615,9 +615,9 @@ static const struct tv_mode tv_modes[] = {
|
||||
|
||||
|
||||
/* desired 4.4336180 actual 4.4336180 clock 107.52 */
|
||||
.dda1_inc = 168,
|
||||
.dda2_inc = 18557, .dda2_size = 20625,
|
||||
.dda3_inc = 0, .dda3_size = 0,
|
||||
.dda1_inc = 135,
|
||||
.dda2_inc = 23578, .dda2_size = 27648,
|
||||
.dda3_inc = 134, .dda3_size = 625,
|
||||
.sc_reset = TV_SC_RESET_EVERY_8,
|
||||
.pal_burst = true,
|
||||
|
||||
@@ -631,12 +631,12 @@ static const struct tv_mode tv_modes[] = {
|
||||
{
|
||||
/* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
|
||||
.name = "PAL",
|
||||
.clock = 107520,
|
||||
.clock = 108000,
|
||||
.refresh = 25000,
|
||||
.oversample = TV_OVERSAMPLE_8X,
|
||||
.component_only = 0,
|
||||
|
||||
.hsync_end = 64, .hblank_end = 128,
|
||||
.hsync_end = 64, .hblank_end = 142,
|
||||
.hblank_start = 844, .htotal = 863,
|
||||
|
||||
.progressive = false, .trilevel_sync = false,
|
||||
@@ -659,8 +659,8 @@ static const struct tv_mode tv_modes[] = {
|
||||
|
||||
/* desired 4.4336180 actual 4.4336180 clock 107.52 */
|
||||
.dda1_inc = 168,
|
||||
.dda2_inc = 18557, .dda2_size = 20625,
|
||||
.dda3_inc = 0, .dda3_size = 0,
|
||||
.dda2_inc = 4122, .dda2_size = 27648,
|
||||
.dda3_inc = 67, .dda3_size = 625,
|
||||
.sc_reset = TV_SC_RESET_EVERY_8,
|
||||
.pal_burst = true,
|
||||
|
||||
@@ -689,7 +689,7 @@ static const struct tv_mode tv_modes[] = {
|
||||
.veq_ena = false,
|
||||
|
||||
.vi_end_f1 = 44, .vi_end_f2 = 44,
|
||||
.nbr_end = 496,
|
||||
.nbr_end = 479,
|
||||
|
||||
.burst_ena = false,
|
||||
|
||||
@@ -713,7 +713,7 @@ static const struct tv_mode tv_modes[] = {
|
||||
.veq_ena = false,
|
||||
|
||||
.vi_end_f1 = 44, .vi_end_f2 = 44,
|
||||
.nbr_end = 496,
|
||||
.nbr_end = 479,
|
||||
|
||||
.burst_ena = false,
|
||||
|
||||
@@ -876,7 +876,7 @@ static const struct tv_mode tv_modes[] = {
|
||||
.component_only = 1,
|
||||
|
||||
.hsync_end = 88, .hblank_end = 235,
|
||||
.hblank_start = 2155, .htotal = 2200,
|
||||
.hblank_start = 2155, .htotal = 2201,
|
||||
|
||||
.progressive = false, .trilevel_sync = true,
|
||||
|
||||
@@ -1082,7 +1082,7 @@ intel_tv_mode_valid(struct drm_connector *connector, struct drm_display_mode *mo
|
||||
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_output);
|
||||
|
||||
/* Ensure TV refresh is close to desired refresh */
|
||||
if (tv_mode && abs(tv_mode->refresh - drm_mode_vrefresh(mode)) < 1)
|
||||
if (tv_mode && abs(tv_mode->refresh - drm_mode_vrefresh(mode)) < 10)
|
||||
return MODE_OK;
|
||||
return MODE_CLOCK_RANGE;
|
||||
}
|
||||
@@ -1135,7 +1135,8 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
|
||||
if (!tv_mode)
|
||||
return; /* can't happen (mode_prepare prevents this) */
|
||||
|
||||
tv_ctl = 0;
|
||||
tv_ctl = I915_READ(TV_CTL);
|
||||
tv_ctl &= TV_CTL_SAVE;
|
||||
|
||||
switch (tv_priv->type) {
|
||||
default:
|
||||
@@ -1215,7 +1216,6 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
|
||||
/* dda1 implies valid video levels */
|
||||
if (tv_mode->dda1_inc) {
|
||||
scctl1 |= TV_SC_DDA1_EN;
|
||||
scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT;
|
||||
}
|
||||
|
||||
if (tv_mode->dda2_inc)
|
||||
@@ -1225,6 +1225,7 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
|
||||
scctl1 |= TV_SC_DDA3_EN;
|
||||
|
||||
scctl1 |= tv_mode->sc_reset;
|
||||
scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT;
|
||||
scctl1 |= tv_mode->dda1_inc << TV_SCDDA1_INC_SHIFT;
|
||||
|
||||
scctl2 = tv_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT |
|
||||
@@ -1266,7 +1267,11 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
|
||||
color_conversion->av);
|
||||
}
|
||||
|
||||
I915_WRITE(TV_CLR_KNOBS, 0x00606000);
|
||||
if (IS_I965G(dev))
|
||||
I915_WRITE(TV_CLR_KNOBS, 0x00404000);
|
||||
else
|
||||
I915_WRITE(TV_CLR_KNOBS, 0x00606000);
|
||||
|
||||
if (video_levels)
|
||||
I915_WRITE(TV_CLR_LEVEL,
|
||||
((video_levels->black << TV_BLACK_LEVEL_SHIFT) |
|
||||
@@ -1401,6 +1406,7 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct intel_output *intel_output)
|
||||
tv_dac = I915_READ(TV_DAC);
|
||||
I915_WRITE(TV_DAC, save_tv_dac);
|
||||
I915_WRITE(TV_CTL, save_tv_ctl);
|
||||
intel_wait_for_vblank(dev);
|
||||
}
|
||||
/*
|
||||
* A B C
|
||||
@@ -1451,7 +1457,7 @@ intel_tv_detect(struct drm_connector *connector)
|
||||
mode = reported_modes[0];
|
||||
drm_mode_set_crtcinfo(&mode, CRTC_INTERLACE_HALVE_V);
|
||||
|
||||
if (encoder->crtc) {
|
||||
if (encoder->crtc && encoder->crtc->enabled) {
|
||||
type = intel_tv_detect_type(encoder->crtc, intel_output);
|
||||
} else {
|
||||
crtc = intel_get_load_detect_pipe(intel_output, &mode, &dpms_mode);
|
||||
@@ -1462,6 +1468,8 @@ intel_tv_detect(struct drm_connector *connector)
|
||||
type = -1;
|
||||
}
|
||||
|
||||
tv_priv->type = type;
|
||||
|
||||
if (type < 0)
|
||||
return connector_status_disconnected;
|
||||
|
||||
@@ -1495,7 +1503,8 @@ intel_tv_get_modes(struct drm_connector *connector)
|
||||
struct drm_display_mode *mode_ptr;
|
||||
struct intel_output *intel_output = to_intel_output(connector);
|
||||
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_output);
|
||||
int j;
|
||||
int j, count = 0;
|
||||
u64 tmp;
|
||||
|
||||
for (j = 0; j < sizeof(input_res_table) / sizeof(input_res_table[0]);
|
||||
j++) {
|
||||
@@ -1510,8 +1519,9 @@ intel_tv_get_modes(struct drm_connector *connector)
|
||||
&& !tv_mode->component_only))
|
||||
continue;
|
||||
|
||||
mode_ptr = drm_calloc(1, sizeof(struct drm_display_mode),
|
||||
DRM_MEM_DRIVER);
|
||||
mode_ptr = drm_mode_create(connector->dev);
|
||||
if (!mode_ptr)
|
||||
continue;
|
||||
strncpy(mode_ptr->name, input->name, DRM_DISPLAY_MODE_LEN);
|
||||
|
||||
mode_ptr->hdisplay = hactive_s;
|
||||
@@ -1528,15 +1538,17 @@ intel_tv_get_modes(struct drm_connector *connector)
|
||||
mode_ptr->vsync_end = mode_ptr->vsync_start + 1;
|
||||
mode_ptr->vtotal = vactive_s + 33;
|
||||
|
||||
mode_ptr->clock = (int) (tv_mode->refresh *
|
||||
mode_ptr->vtotal *
|
||||
mode_ptr->htotal / 1000) / 1000;
|
||||
tmp = (u64) tv_mode->refresh * mode_ptr->vtotal;
|
||||
tmp *= mode_ptr->htotal;
|
||||
tmp = div_u64(tmp, 1000000);
|
||||
mode_ptr->clock = (int) tmp;
|
||||
|
||||
mode_ptr->type = DRM_MODE_TYPE_DRIVER;
|
||||
drm_mode_probed_add(connector, mode_ptr);
|
||||
count++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return count;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
Reference in New Issue
Block a user