diff options
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fimd.c | 21 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_g2d.c | 370 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_gem.c | 21 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_gem.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_vidi.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_mixer.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_panel.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_pm.c | 3 |
11 files changed, 384 insertions, 73 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 36493ce71f9a..98cc14725ba9 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c | |||
@@ -38,11 +38,12 @@ | |||
38 | /* position control register for hardware window 0, 2 ~ 4.*/ | 38 | /* position control register for hardware window 0, 2 ~ 4.*/ |
39 | #define VIDOSD_A(win) (VIDOSD_BASE + 0x00 + (win) * 16) | 39 | #define VIDOSD_A(win) (VIDOSD_BASE + 0x00 + (win) * 16) |
40 | #define VIDOSD_B(win) (VIDOSD_BASE + 0x04 + (win) * 16) | 40 | #define VIDOSD_B(win) (VIDOSD_BASE + 0x04 + (win) * 16) |
41 | /* size control register for hardware window 0. */ | 41 | /* |
42 | #define VIDOSD_C_SIZE_W0 (VIDOSD_BASE + 0x08) | 42 | * size control register for hardware windows 0 and alpha control register |
43 | /* alpha control register for hardware window 1 ~ 4. */ | 43 | * for hardware windows 1 ~ 4 |
44 | #define VIDOSD_C(win) (VIDOSD_BASE + 0x18 + (win) * 16) | 44 | */ |
45 | /* size control register for hardware window 1 ~ 4. */ | 45 | #define VIDOSD_C(win) (VIDOSD_BASE + 0x08 + (win) * 16) |
46 | /* size control register for hardware windows 1 ~ 2. */ | ||
46 | #define VIDOSD_D(win) (VIDOSD_BASE + 0x0C + (win) * 16) | 47 | #define VIDOSD_D(win) (VIDOSD_BASE + 0x0C + (win) * 16) |
47 | 48 | ||
48 | #define VIDWx_BUF_START(win, buf) (VIDW_BUF_START(buf) + (win) * 8) | 49 | #define VIDWx_BUF_START(win, buf) (VIDW_BUF_START(buf) + (win) * 8) |
@@ -50,9 +51,9 @@ | |||
50 | #define VIDWx_BUF_SIZE(win, buf) (VIDW_BUF_SIZE(buf) + (win) * 4) | 51 | #define VIDWx_BUF_SIZE(win, buf) (VIDW_BUF_SIZE(buf) + (win) * 4) |
51 | 52 | ||
52 | /* color key control register for hardware window 1 ~ 4. */ | 53 | /* color key control register for hardware window 1 ~ 4. */ |
53 | #define WKEYCON0_BASE(x) ((WKEYCON0 + 0x140) + (x * 8)) | 54 | #define WKEYCON0_BASE(x) ((WKEYCON0 + 0x140) + ((x - 1) * 8)) |
54 | /* color key value register for hardware window 1 ~ 4. */ | 55 | /* color key value register for hardware window 1 ~ 4. */ |
55 | #define WKEYCON1_BASE(x) ((WKEYCON1 + 0x140) + (x * 8)) | 56 | #define WKEYCON1_BASE(x) ((WKEYCON1 + 0x140) + ((x - 1) * 8)) |
56 | 57 | ||
57 | /* FIMD has totally five hardware windows. */ | 58 | /* FIMD has totally five hardware windows. */ |
58 | #define WINDOWS_NR 5 | 59 | #define WINDOWS_NR 5 |
@@ -109,9 +110,9 @@ struct fimd_context { | |||
109 | 110 | ||
110 | #ifdef CONFIG_OF | 111 | #ifdef CONFIG_OF |
111 | static const struct of_device_id fimd_driver_dt_match[] = { | 112 | static const struct of_device_id fimd_driver_dt_match[] = { |
112 | { .compatible = "samsung,exynos4-fimd", | 113 | { .compatible = "samsung,exynos4210-fimd", |
113 | .data = &exynos4_fimd_driver_data }, | 114 | .data = &exynos4_fimd_driver_data }, |
114 | { .compatible = "samsung,exynos5-fimd", | 115 | { .compatible = "samsung,exynos5250-fimd", |
115 | .data = &exynos5_fimd_driver_data }, | 116 | .data = &exynos5_fimd_driver_data }, |
116 | {}, | 117 | {}, |
117 | }; | 118 | }; |
@@ -581,7 +582,7 @@ static void fimd_win_commit(struct device *dev, int zpos) | |||
581 | if (win != 3 && win != 4) { | 582 | if (win != 3 && win != 4) { |
582 | u32 offset = VIDOSD_D(win); | 583 | u32 offset = VIDOSD_D(win); |
583 | if (win == 0) | 584 | if (win == 0) |
584 | offset = VIDOSD_C_SIZE_W0; | 585 | offset = VIDOSD_C(win); |
585 | val = win_data->ovl_width * win_data->ovl_height; | 586 | val = win_data->ovl_width * win_data->ovl_height; |
586 | writel(val, ctx->regs + offset); | 587 | writel(val, ctx->regs + offset); |
587 | 588 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 3b0da0378acf..47a493c8a71f 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c | |||
@@ -48,8 +48,14 @@ | |||
48 | 48 | ||
49 | /* registers for base address */ | 49 | /* registers for base address */ |
50 | #define G2D_SRC_BASE_ADDR 0x0304 | 50 | #define G2D_SRC_BASE_ADDR 0x0304 |
51 | #define G2D_SRC_COLOR_MODE 0x030C | ||
52 | #define G2D_SRC_LEFT_TOP 0x0310 | ||
53 | #define G2D_SRC_RIGHT_BOTTOM 0x0314 | ||
51 | #define G2D_SRC_PLANE2_BASE_ADDR 0x0318 | 54 | #define G2D_SRC_PLANE2_BASE_ADDR 0x0318 |
52 | #define G2D_DST_BASE_ADDR 0x0404 | 55 | #define G2D_DST_BASE_ADDR 0x0404 |
56 | #define G2D_DST_COLOR_MODE 0x040C | ||
57 | #define G2D_DST_LEFT_TOP 0x0410 | ||
58 | #define G2D_DST_RIGHT_BOTTOM 0x0414 | ||
53 | #define G2D_DST_PLANE2_BASE_ADDR 0x0418 | 59 | #define G2D_DST_PLANE2_BASE_ADDR 0x0418 |
54 | #define G2D_PAT_BASE_ADDR 0x0500 | 60 | #define G2D_PAT_BASE_ADDR 0x0500 |
55 | #define G2D_MSK_BASE_ADDR 0x0520 | 61 | #define G2D_MSK_BASE_ADDR 0x0520 |
@@ -82,7 +88,7 @@ | |||
82 | #define G2D_DMA_LIST_DONE_COUNT_OFFSET 17 | 88 | #define G2D_DMA_LIST_DONE_COUNT_OFFSET 17 |
83 | 89 | ||
84 | /* G2D_DMA_HOLD_CMD */ | 90 | /* G2D_DMA_HOLD_CMD */ |
85 | #define G2D_USET_HOLD (1 << 2) | 91 | #define G2D_USER_HOLD (1 << 2) |
86 | #define G2D_LIST_HOLD (1 << 1) | 92 | #define G2D_LIST_HOLD (1 << 1) |
87 | #define G2D_BITBLT_HOLD (1 << 0) | 93 | #define G2D_BITBLT_HOLD (1 << 0) |
88 | 94 | ||
@@ -91,13 +97,27 @@ | |||
91 | #define G2D_START_NHOLT (1 << 1) | 97 | #define G2D_START_NHOLT (1 << 1) |
92 | #define G2D_START_BITBLT (1 << 0) | 98 | #define G2D_START_BITBLT (1 << 0) |
93 | 99 | ||
100 | /* buffer color format */ | ||
101 | #define G2D_FMT_XRGB8888 0 | ||
102 | #define G2D_FMT_ARGB8888 1 | ||
103 | #define G2D_FMT_RGB565 2 | ||
104 | #define G2D_FMT_XRGB1555 3 | ||
105 | #define G2D_FMT_ARGB1555 4 | ||
106 | #define G2D_FMT_XRGB4444 5 | ||
107 | #define G2D_FMT_ARGB4444 6 | ||
108 | #define G2D_FMT_PACKED_RGB888 7 | ||
109 | #define G2D_FMT_A8 11 | ||
110 | #define G2D_FMT_L8 12 | ||
111 | |||
112 | /* buffer valid length */ | ||
113 | #define G2D_LEN_MIN 1 | ||
114 | #define G2D_LEN_MAX 8000 | ||
115 | |||
94 | #define G2D_CMDLIST_SIZE (PAGE_SIZE / 4) | 116 | #define G2D_CMDLIST_SIZE (PAGE_SIZE / 4) |
95 | #define G2D_CMDLIST_NUM 64 | 117 | #define G2D_CMDLIST_NUM 64 |
96 | #define G2D_CMDLIST_POOL_SIZE (G2D_CMDLIST_SIZE * G2D_CMDLIST_NUM) | 118 | #define G2D_CMDLIST_POOL_SIZE (G2D_CMDLIST_SIZE * G2D_CMDLIST_NUM) |
97 | #define G2D_CMDLIST_DATA_NUM (G2D_CMDLIST_SIZE / sizeof(u32) - 2) | 119 | #define G2D_CMDLIST_DATA_NUM (G2D_CMDLIST_SIZE / sizeof(u32) - 2) |
98 | 120 | ||
99 | #define MAX_BUF_ADDR_NR 6 | ||
100 | |||
101 | /* maximum buffer pool size of userptr is 64MB as default */ | 121 | /* maximum buffer pool size of userptr is 64MB as default */ |
102 | #define MAX_POOL (64 * 1024 * 1024) | 122 | #define MAX_POOL (64 * 1024 * 1024) |
103 | 123 | ||
@@ -106,6 +126,17 @@ enum { | |||
106 | BUF_TYPE_USERPTR, | 126 | BUF_TYPE_USERPTR, |
107 | }; | 127 | }; |
108 | 128 | ||
129 | enum g2d_reg_type { | ||
130 | REG_TYPE_NONE = -1, | ||
131 | REG_TYPE_SRC, | ||
132 | REG_TYPE_SRC_PLANE2, | ||
133 | REG_TYPE_DST, | ||
134 | REG_TYPE_DST_PLANE2, | ||
135 | REG_TYPE_PAT, | ||
136 | REG_TYPE_MSK, | ||
137 | MAX_REG_TYPE_NR | ||
138 | }; | ||
139 | |||
109 | /* cmdlist data structure */ | 140 | /* cmdlist data structure */ |
110 | struct g2d_cmdlist { | 141 | struct g2d_cmdlist { |
111 | u32 head; | 142 | u32 head; |
@@ -113,6 +144,42 @@ struct g2d_cmdlist { | |||
113 | u32 last; /* last data offset */ | 144 | u32 last; /* last data offset */ |
114 | }; | 145 | }; |
115 | 146 | ||
147 | /* | ||
148 | * A structure of buffer description | ||
149 | * | ||
150 | * @format: color format | ||
151 | * @left_x: the x coordinates of left top corner | ||
152 | * @top_y: the y coordinates of left top corner | ||
153 | * @right_x: the x coordinates of right bottom corner | ||
154 | * @bottom_y: the y coordinates of right bottom corner | ||
155 | * | ||
156 | */ | ||
157 | struct g2d_buf_desc { | ||
158 | unsigned int format; | ||
159 | unsigned int left_x; | ||
160 | unsigned int top_y; | ||
161 | unsigned int right_x; | ||
162 | unsigned int bottom_y; | ||
163 | }; | ||
164 | |||
165 | /* | ||
166 | * A structure of buffer information | ||
167 | * | ||
168 | * @map_nr: manages the number of mapped buffers | ||
169 | * @reg_types: stores regitster type in the order of requested command | ||
170 | * @handles: stores buffer handle in its reg_type position | ||
171 | * @types: stores buffer type in its reg_type position | ||
172 | * @descs: stores buffer description in its reg_type position | ||
173 | * | ||
174 | */ | ||
175 | struct g2d_buf_info { | ||
176 | unsigned int map_nr; | ||
177 | enum g2d_reg_type reg_types[MAX_REG_TYPE_NR]; | ||
178 | unsigned long handles[MAX_REG_TYPE_NR]; | ||
179 | unsigned int types[MAX_REG_TYPE_NR]; | ||
180 | struct g2d_buf_desc descs[MAX_REG_TYPE_NR]; | ||
181 | }; | ||
182 | |||
116 | struct drm_exynos_pending_g2d_event { | 183 | struct drm_exynos_pending_g2d_event { |
117 | struct drm_pending_event base; | 184 | struct drm_pending_event base; |
118 | struct drm_exynos_g2d_event event; | 185 | struct drm_exynos_g2d_event event; |
@@ -131,14 +198,11 @@ struct g2d_cmdlist_userptr { | |||
131 | bool in_pool; | 198 | bool in_pool; |
132 | bool out_of_list; | 199 | bool out_of_list; |
133 | }; | 200 | }; |
134 | |||
135 | struct g2d_cmdlist_node { | 201 | struct g2d_cmdlist_node { |
136 | struct list_head list; | 202 | struct list_head list; |
137 | struct g2d_cmdlist *cmdlist; | 203 | struct g2d_cmdlist *cmdlist; |
138 | unsigned int map_nr; | ||
139 | unsigned long handles[MAX_BUF_ADDR_NR]; | ||
140 | unsigned int obj_type[MAX_BUF_ADDR_NR]; | ||
141 | dma_addr_t dma_addr; | 204 | dma_addr_t dma_addr; |
205 | struct g2d_buf_info buf_info; | ||
142 | 206 | ||
143 | struct drm_exynos_pending_g2d_event *event; | 207 | struct drm_exynos_pending_g2d_event *event; |
144 | }; | 208 | }; |
@@ -188,6 +252,7 @@ static int g2d_init_cmdlist(struct g2d_data *g2d) | |||
188 | struct exynos_drm_subdrv *subdrv = &g2d->subdrv; | 252 | struct exynos_drm_subdrv *subdrv = &g2d->subdrv; |
189 | int nr; | 253 | int nr; |
190 | int ret; | 254 | int ret; |
255 | struct g2d_buf_info *buf_info; | ||
191 | 256 | ||
192 | init_dma_attrs(&g2d->cmdlist_dma_attrs); | 257 | init_dma_attrs(&g2d->cmdlist_dma_attrs); |
193 | dma_set_attr(DMA_ATTR_WRITE_COMBINE, &g2d->cmdlist_dma_attrs); | 258 | dma_set_attr(DMA_ATTR_WRITE_COMBINE, &g2d->cmdlist_dma_attrs); |
@@ -209,11 +274,17 @@ static int g2d_init_cmdlist(struct g2d_data *g2d) | |||
209 | } | 274 | } |
210 | 275 | ||
211 | for (nr = 0; nr < G2D_CMDLIST_NUM; nr++) { | 276 | for (nr = 0; nr < G2D_CMDLIST_NUM; nr++) { |
277 | unsigned int i; | ||
278 | |||
212 | node[nr].cmdlist = | 279 | node[nr].cmdlist = |
213 | g2d->cmdlist_pool_virt + nr * G2D_CMDLIST_SIZE; | 280 | g2d->cmdlist_pool_virt + nr * G2D_CMDLIST_SIZE; |
214 | node[nr].dma_addr = | 281 | node[nr].dma_addr = |
215 | g2d->cmdlist_pool + nr * G2D_CMDLIST_SIZE; | 282 | g2d->cmdlist_pool + nr * G2D_CMDLIST_SIZE; |
216 | 283 | ||
284 | buf_info = &node[nr].buf_info; | ||
285 | for (i = 0; i < MAX_REG_TYPE_NR; i++) | ||
286 | buf_info->reg_types[i] = REG_TYPE_NONE; | ||
287 | |||
217 | list_add_tail(&node[nr].list, &g2d->free_cmdlist); | 288 | list_add_tail(&node[nr].list, &g2d->free_cmdlist); |
218 | } | 289 | } |
219 | 290 | ||
@@ -450,7 +521,7 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev, | |||
450 | DMA_BIDIRECTIONAL); | 521 | DMA_BIDIRECTIONAL); |
451 | if (ret < 0) { | 522 | if (ret < 0) { |
452 | DRM_ERROR("failed to map sgt with dma region.\n"); | 523 | DRM_ERROR("failed to map sgt with dma region.\n"); |
453 | goto err_free_sgt; | 524 | goto err_sg_free_table; |
454 | } | 525 | } |
455 | 526 | ||
456 | g2d_userptr->dma_addr = sgt->sgl[0].dma_address; | 527 | g2d_userptr->dma_addr = sgt->sgl[0].dma_address; |
@@ -467,8 +538,10 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev, | |||
467 | 538 | ||
468 | return &g2d_userptr->dma_addr; | 539 | return &g2d_userptr->dma_addr; |
469 | 540 | ||
470 | err_free_sgt: | 541 | err_sg_free_table: |
471 | sg_free_table(sgt); | 542 | sg_free_table(sgt); |
543 | |||
544 | err_free_sgt: | ||
472 | kfree(sgt); | 545 | kfree(sgt); |
473 | sgt = NULL; | 546 | sgt = NULL; |
474 | 547 | ||
@@ -506,36 +579,172 @@ static void g2d_userptr_free_all(struct drm_device *drm_dev, | |||
506 | g2d->current_pool = 0; | 579 | g2d->current_pool = 0; |
507 | } | 580 | } |
508 | 581 | ||
582 | static enum g2d_reg_type g2d_get_reg_type(int reg_offset) | ||
583 | { | ||
584 | enum g2d_reg_type reg_type; | ||
585 | |||
586 | switch (reg_offset) { | ||
587 | case G2D_SRC_BASE_ADDR: | ||
588 | case G2D_SRC_COLOR_MODE: | ||
589 | case G2D_SRC_LEFT_TOP: | ||
590 | case G2D_SRC_RIGHT_BOTTOM: | ||
591 | reg_type = REG_TYPE_SRC; | ||
592 | break; | ||
593 | case G2D_SRC_PLANE2_BASE_ADDR: | ||
594 | reg_type = REG_TYPE_SRC_PLANE2; | ||
595 | break; | ||
596 | case G2D_DST_BASE_ADDR: | ||
597 | case G2D_DST_COLOR_MODE: | ||
598 | case G2D_DST_LEFT_TOP: | ||
599 | case G2D_DST_RIGHT_BOTTOM: | ||
600 | reg_type = REG_TYPE_DST; | ||
601 | break; | ||
602 | case G2D_DST_PLANE2_BASE_ADDR: | ||
603 | reg_type = REG_TYPE_DST_PLANE2; | ||
604 | break; | ||
605 | case G2D_PAT_BASE_ADDR: | ||
606 | reg_type = REG_TYPE_PAT; | ||
607 | break; | ||
608 | case G2D_MSK_BASE_ADDR: | ||
609 | reg_type = REG_TYPE_MSK; | ||
610 | break; | ||
611 | default: | ||
612 | reg_type = REG_TYPE_NONE; | ||
613 | DRM_ERROR("Unknown register offset![%d]\n", reg_offset); | ||
614 | break; | ||
615 | }; | ||
616 | |||
617 | return reg_type; | ||
618 | } | ||
619 | |||
620 | static unsigned long g2d_get_buf_bpp(unsigned int format) | ||
621 | { | ||
622 | unsigned long bpp; | ||
623 | |||
624 | switch (format) { | ||
625 | case G2D_FMT_XRGB8888: | ||
626 | case G2D_FMT_ARGB8888: | ||
627 | bpp = 4; | ||
628 | break; | ||
629 | case G2D_FMT_RGB565: | ||
630 | case G2D_FMT_XRGB1555: | ||
631 | case G2D_FMT_ARGB1555: | ||
632 | case G2D_FMT_XRGB4444: | ||
633 | case G2D_FMT_ARGB4444: | ||
634 | bpp = 2; | ||
635 | break; | ||
636 | case G2D_FMT_PACKED_RGB888: | ||
637 | bpp = 3; | ||
638 | break; | ||
639 | default: | ||
640 | bpp = 1; | ||
641 | break; | ||
642 | } | ||
643 | |||
644 | return bpp; | ||
645 | } | ||
646 | |||
647 | static bool g2d_check_buf_desc_is_valid(struct g2d_buf_desc *buf_desc, | ||
648 | enum g2d_reg_type reg_type, | ||
649 | unsigned long size) | ||
650 | { | ||
651 | unsigned int width, height; | ||
652 | unsigned long area; | ||
653 | |||
654 | /* | ||
655 | * check source and destination buffers only. | ||
656 | * so the others are always valid. | ||
657 | */ | ||
658 | if (reg_type != REG_TYPE_SRC && reg_type != REG_TYPE_DST) | ||
659 | return true; | ||
660 | |||
661 | width = buf_desc->right_x - buf_desc->left_x; | ||
662 | if (width < G2D_LEN_MIN || width > G2D_LEN_MAX) { | ||
663 | DRM_ERROR("width[%u] is out of range!\n", width); | ||
664 | return false; | ||
665 | } | ||
666 | |||
667 | height = buf_desc->bottom_y - buf_desc->top_y; | ||
668 | if (height < G2D_LEN_MIN || height > G2D_LEN_MAX) { | ||
669 | DRM_ERROR("height[%u] is out of range!\n", height); | ||
670 | return false; | ||
671 | } | ||
672 | |||
673 | area = (unsigned long)width * (unsigned long)height * | ||
674 | g2d_get_buf_bpp(buf_desc->format); | ||
675 | if (area > size) { | ||
676 | DRM_ERROR("area[%lu] is out of range[%lu]!\n", area, size); | ||
677 | return false; | ||
678 | } | ||
679 | |||
680 | return true; | ||
681 | } | ||
682 | |||
509 | static int g2d_map_cmdlist_gem(struct g2d_data *g2d, | 683 | static int g2d_map_cmdlist_gem(struct g2d_data *g2d, |
510 | struct g2d_cmdlist_node *node, | 684 | struct g2d_cmdlist_node *node, |
511 | struct drm_device *drm_dev, | 685 | struct drm_device *drm_dev, |
512 | struct drm_file *file) | 686 | struct drm_file *file) |
513 | { | 687 | { |
514 | struct g2d_cmdlist *cmdlist = node->cmdlist; | 688 | struct g2d_cmdlist *cmdlist = node->cmdlist; |
689 | struct g2d_buf_info *buf_info = &node->buf_info; | ||
515 | int offset; | 690 | int offset; |
691 | int ret; | ||
516 | int i; | 692 | int i; |
517 | 693 | ||
518 | for (i = 0; i < node->map_nr; i++) { | 694 | for (i = 0; i < buf_info->map_nr; i++) { |
695 | struct g2d_buf_desc *buf_desc; | ||
696 | enum g2d_reg_type reg_type; | ||
697 | int reg_pos; | ||
519 | unsigned long handle; | 698 | unsigned long handle; |
520 | dma_addr_t *addr; | 699 | dma_addr_t *addr; |
521 | 700 | ||
522 | offset = cmdlist->last - (i * 2 + 1); | 701 | reg_pos = cmdlist->last - 2 * (i + 1); |
523 | handle = cmdlist->data[offset]; | 702 | |
703 | offset = cmdlist->data[reg_pos]; | ||
704 | handle = cmdlist->data[reg_pos + 1]; | ||
705 | |||
706 | reg_type = g2d_get_reg_type(offset); | ||
707 | if (reg_type == REG_TYPE_NONE) { | ||
708 | ret = -EFAULT; | ||
709 | goto err; | ||
710 | } | ||
711 | |||
712 | buf_desc = &buf_info->descs[reg_type]; | ||
713 | |||
714 | if (buf_info->types[reg_type] == BUF_TYPE_GEM) { | ||
715 | unsigned long size; | ||
716 | |||
717 | size = exynos_drm_gem_get_size(drm_dev, handle, file); | ||
718 | if (!size) { | ||
719 | ret = -EFAULT; | ||
720 | goto err; | ||
721 | } | ||
722 | |||
723 | if (!g2d_check_buf_desc_is_valid(buf_desc, reg_type, | ||
724 | size)) { | ||
725 | ret = -EFAULT; | ||
726 | goto err; | ||
727 | } | ||
524 | 728 | ||
525 | if (node->obj_type[i] == BUF_TYPE_GEM) { | ||
526 | addr = exynos_drm_gem_get_dma_addr(drm_dev, handle, | 729 | addr = exynos_drm_gem_get_dma_addr(drm_dev, handle, |
527 | file); | 730 | file); |
528 | if (IS_ERR(addr)) { | 731 | if (IS_ERR(addr)) { |
529 | node->map_nr = i; | 732 | ret = -EFAULT; |
530 | return -EFAULT; | 733 | goto err; |
531 | } | 734 | } |
532 | } else { | 735 | } else { |
533 | struct drm_exynos_g2d_userptr g2d_userptr; | 736 | struct drm_exynos_g2d_userptr g2d_userptr; |
534 | 737 | ||
535 | if (copy_from_user(&g2d_userptr, (void __user *)handle, | 738 | if (copy_from_user(&g2d_userptr, (void __user *)handle, |
536 | sizeof(struct drm_exynos_g2d_userptr))) { | 739 | sizeof(struct drm_exynos_g2d_userptr))) { |
537 | node->map_nr = i; | 740 | ret = -EFAULT; |
538 | return -EFAULT; | 741 | goto err; |
742 | } | ||
743 | |||
744 | if (!g2d_check_buf_desc_is_valid(buf_desc, reg_type, | ||
745 | g2d_userptr.size)) { | ||
746 | ret = -EFAULT; | ||
747 | goto err; | ||
539 | } | 748 | } |
540 | 749 | ||
541 | addr = g2d_userptr_get_dma_addr(drm_dev, | 750 | addr = g2d_userptr_get_dma_addr(drm_dev, |
@@ -544,16 +753,21 @@ static int g2d_map_cmdlist_gem(struct g2d_data *g2d, | |||
544 | file, | 753 | file, |
545 | &handle); | 754 | &handle); |
546 | if (IS_ERR(addr)) { | 755 | if (IS_ERR(addr)) { |
547 | node->map_nr = i; | 756 | ret = -EFAULT; |
548 | return -EFAULT; | 757 | goto err; |
549 | } | 758 | } |
550 | } | 759 | } |
551 | 760 | ||
552 | cmdlist->data[offset] = *addr; | 761 | cmdlist->data[reg_pos + 1] = *addr; |
553 | node->handles[i] = handle; | 762 | buf_info->reg_types[i] = reg_type; |
763 | buf_info->handles[reg_type] = handle; | ||
554 | } | 764 | } |
555 | 765 | ||
556 | return 0; | 766 | return 0; |
767 | |||
768 | err: | ||
769 | buf_info->map_nr = i; | ||
770 | return ret; | ||
557 | } | 771 | } |
558 | 772 | ||
559 | static void g2d_unmap_cmdlist_gem(struct g2d_data *g2d, | 773 | static void g2d_unmap_cmdlist_gem(struct g2d_data *g2d, |
@@ -561,22 +775,33 @@ static void g2d_unmap_cmdlist_gem(struct g2d_data *g2d, | |||
561 | struct drm_file *filp) | 775 | struct drm_file *filp) |
562 | { | 776 | { |
563 | struct exynos_drm_subdrv *subdrv = &g2d->subdrv; | 777 | struct exynos_drm_subdrv *subdrv = &g2d->subdrv; |
778 | struct g2d_buf_info *buf_info = &node->buf_info; | ||
564 | int i; | 779 | int i; |
565 | 780 | ||
566 | for (i = 0; i < node->map_nr; i++) { | 781 | for (i = 0; i < buf_info->map_nr; i++) { |
567 | unsigned long handle = node->handles[i]; | 782 | struct g2d_buf_desc *buf_desc; |
783 | enum g2d_reg_type reg_type; | ||
784 | unsigned long handle; | ||
785 | |||
786 | reg_type = buf_info->reg_types[i]; | ||
787 | |||
788 | buf_desc = &buf_info->descs[reg_type]; | ||
789 | handle = buf_info->handles[reg_type]; | ||
568 | 790 | ||
569 | if (node->obj_type[i] == BUF_TYPE_GEM) | 791 | if (buf_info->types[reg_type] == BUF_TYPE_GEM) |
570 | exynos_drm_gem_put_dma_addr(subdrv->drm_dev, handle, | 792 | exynos_drm_gem_put_dma_addr(subdrv->drm_dev, handle, |
571 | filp); | 793 | filp); |
572 | else | 794 | else |
573 | g2d_userptr_put_dma_addr(subdrv->drm_dev, handle, | 795 | g2d_userptr_put_dma_addr(subdrv->drm_dev, handle, |
574 | false); | 796 | false); |
575 | 797 | ||
576 | node->handles[i] = 0; | 798 | buf_info->reg_types[i] = REG_TYPE_NONE; |
799 | buf_info->handles[reg_type] = 0; | ||
800 | buf_info->types[reg_type] = 0; | ||
801 | memset(buf_desc, 0x00, sizeof(*buf_desc)); | ||
577 | } | 802 | } |
578 | 803 | ||
579 | node->map_nr = 0; | 804 | buf_info->map_nr = 0; |
580 | } | 805 | } |
581 | 806 | ||
582 | static void g2d_dma_start(struct g2d_data *g2d, | 807 | static void g2d_dma_start(struct g2d_data *g2d, |
@@ -589,10 +814,6 @@ static void g2d_dma_start(struct g2d_data *g2d, | |||
589 | pm_runtime_get_sync(g2d->dev); | 814 | pm_runtime_get_sync(g2d->dev); |
590 | clk_enable(g2d->gate_clk); | 815 | clk_enable(g2d->gate_clk); |
591 | 816 | ||
592 | /* interrupt enable */ | ||
593 | writel_relaxed(G2D_INTEN_ACF | G2D_INTEN_UCF | G2D_INTEN_GCF, | ||
594 | g2d->regs + G2D_INTEN); | ||
595 | |||
596 | writel_relaxed(node->dma_addr, g2d->regs + G2D_DMA_SFR_BASE_ADDR); | 817 | writel_relaxed(node->dma_addr, g2d->regs + G2D_DMA_SFR_BASE_ADDR); |
597 | writel_relaxed(G2D_DMA_START, g2d->regs + G2D_DMA_COMMAND); | 818 | writel_relaxed(G2D_DMA_START, g2d->regs + G2D_DMA_COMMAND); |
598 | } | 819 | } |
@@ -643,7 +864,6 @@ static void g2d_runqueue_worker(struct work_struct *work) | |||
643 | struct g2d_data *g2d = container_of(work, struct g2d_data, | 864 | struct g2d_data *g2d = container_of(work, struct g2d_data, |
644 | runqueue_work); | 865 | runqueue_work); |
645 | 866 | ||
646 | |||
647 | mutex_lock(&g2d->runqueue_mutex); | 867 | mutex_lock(&g2d->runqueue_mutex); |
648 | clk_disable(g2d->gate_clk); | 868 | clk_disable(g2d->gate_clk); |
649 | pm_runtime_put_sync(g2d->dev); | 869 | pm_runtime_put_sync(g2d->dev); |
@@ -724,20 +944,14 @@ static int g2d_check_reg_offset(struct device *dev, | |||
724 | int i; | 944 | int i; |
725 | 945 | ||
726 | for (i = 0; i < nr; i++) { | 946 | for (i = 0; i < nr; i++) { |
727 | index = cmdlist->last - 2 * (i + 1); | 947 | struct g2d_buf_info *buf_info = &node->buf_info; |
948 | struct g2d_buf_desc *buf_desc; | ||
949 | enum g2d_reg_type reg_type; | ||
950 | unsigned long value; | ||
728 | 951 | ||
729 | if (for_addr) { | 952 | index = cmdlist->last - 2 * (i + 1); |
730 | /* check userptr buffer type. */ | ||
731 | reg_offset = (cmdlist->data[index] & | ||
732 | ~0x7fffffff) >> 31; | ||
733 | if (reg_offset) { | ||
734 | node->obj_type[i] = BUF_TYPE_USERPTR; | ||
735 | cmdlist->data[index] &= ~G2D_BUF_USERPTR; | ||
736 | } | ||
737 | } | ||
738 | 953 | ||
739 | reg_offset = cmdlist->data[index] & ~0xfffff000; | 954 | reg_offset = cmdlist->data[index] & ~0xfffff000; |
740 | |||
741 | if (reg_offset < G2D_VALID_START || reg_offset > G2D_VALID_END) | 955 | if (reg_offset < G2D_VALID_START || reg_offset > G2D_VALID_END) |
742 | goto err; | 956 | goto err; |
743 | if (reg_offset % 4) | 957 | if (reg_offset % 4) |
@@ -753,8 +967,60 @@ static int g2d_check_reg_offset(struct device *dev, | |||
753 | if (!for_addr) | 967 | if (!for_addr) |
754 | goto err; | 968 | goto err; |
755 | 969 | ||
756 | if (node->obj_type[i] != BUF_TYPE_USERPTR) | 970 | reg_type = g2d_get_reg_type(reg_offset); |
757 | node->obj_type[i] = BUF_TYPE_GEM; | 971 | if (reg_type == REG_TYPE_NONE) |
972 | goto err; | ||
973 | |||
974 | /* check userptr buffer type. */ | ||
975 | if ((cmdlist->data[index] & ~0x7fffffff) >> 31) { | ||
976 | buf_info->types[reg_type] = BUF_TYPE_USERPTR; | ||
977 | cmdlist->data[index] &= ~G2D_BUF_USERPTR; | ||
978 | } else | ||
979 | buf_info->types[reg_type] = BUF_TYPE_GEM; | ||
980 | break; | ||
981 | case G2D_SRC_COLOR_MODE: | ||
982 | case G2D_DST_COLOR_MODE: | ||
983 | if (for_addr) | ||
984 | goto err; | ||
985 | |||
986 | reg_type = g2d_get_reg_type(reg_offset); | ||
987 | if (reg_type == REG_TYPE_NONE) | ||
988 | goto err; | ||
989 | |||
990 | buf_desc = &buf_info->descs[reg_type]; | ||
991 | value = cmdlist->data[index + 1]; | ||
992 | |||
993 | buf_desc->format = value & 0xf; | ||
994 | break; | ||
995 | case G2D_SRC_LEFT_TOP: | ||
996 | case G2D_DST_LEFT_TOP: | ||
997 | if (for_addr) | ||
998 | goto err; | ||
999 | |||
1000 | reg_type = g2d_get_reg_type(reg_offset); | ||
1001 | if (reg_type == REG_TYPE_NONE) | ||
1002 | goto err; | ||
1003 | |||
1004 | buf_desc = &buf_info->descs[reg_type]; | ||
1005 | value = cmdlist->data[index + 1]; | ||
1006 | |||
1007 | buf_desc->left_x = value & 0x1fff; | ||
1008 | buf_desc->top_y = (value & 0x1fff0000) >> 16; | ||
1009 | break; | ||
1010 | case G2D_SRC_RIGHT_BOTTOM: | ||
1011 | case G2D_DST_RIGHT_BOTTOM: | ||
1012 | if (for_addr) | ||
1013 | goto err; | ||
1014 | |||
1015 | reg_type = g2d_get_reg_type(reg_offset); | ||
1016 | if (reg_type == REG_TYPE_NONE) | ||
1017 | goto err; | ||
1018 | |||
1019 | buf_desc = &buf_info->descs[reg_type]; | ||
1020 | value = cmdlist->data[index + 1]; | ||
1021 | |||
1022 | buf_desc->right_x = value & 0x1fff; | ||
1023 | buf_desc->bottom_y = (value & 0x1fff0000) >> 16; | ||
758 | break; | 1024 | break; |
759 | default: | 1025 | default: |
760 | if (for_addr) | 1026 | if (for_addr) |
@@ -860,9 +1126,23 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data, | |||
860 | cmdlist->data[cmdlist->last++] = G2D_SRC_BASE_ADDR; | 1126 | cmdlist->data[cmdlist->last++] = G2D_SRC_BASE_ADDR; |
861 | cmdlist->data[cmdlist->last++] = 0; | 1127 | cmdlist->data[cmdlist->last++] = 0; |
862 | 1128 | ||
1129 | /* | ||
1130 | * 'LIST_HOLD' command should be set to the DMA_HOLD_CMD_REG | ||
1131 | * and GCF bit should be set to INTEN register if user wants | ||
1132 | * G2D interrupt event once current command list execution is | ||
1133 | * finished. | ||
1134 | * Otherwise only ACF bit should be set to INTEN register so | ||
1135 | * that one interrupt is occured after all command lists | ||
1136 | * have been completed. | ||
1137 | */ | ||
863 | if (node->event) { | 1138 | if (node->event) { |
1139 | cmdlist->data[cmdlist->last++] = G2D_INTEN; | ||
1140 | cmdlist->data[cmdlist->last++] = G2D_INTEN_ACF | G2D_INTEN_GCF; | ||
864 | cmdlist->data[cmdlist->last++] = G2D_DMA_HOLD_CMD; | 1141 | cmdlist->data[cmdlist->last++] = G2D_DMA_HOLD_CMD; |
865 | cmdlist->data[cmdlist->last++] = G2D_LIST_HOLD; | 1142 | cmdlist->data[cmdlist->last++] = G2D_LIST_HOLD; |
1143 | } else { | ||
1144 | cmdlist->data[cmdlist->last++] = G2D_INTEN; | ||
1145 | cmdlist->data[cmdlist->last++] = G2D_INTEN_ACF; | ||
866 | } | 1146 | } |
867 | 1147 | ||
868 | /* Check size of cmdlist: last 2 is about G2D_BITBLT_START */ | 1148 | /* Check size of cmdlist: last 2 is about G2D_BITBLT_START */ |
@@ -887,7 +1167,7 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data, | |||
887 | if (ret < 0) | 1167 | if (ret < 0) |
888 | goto err_free_event; | 1168 | goto err_free_event; |
889 | 1169 | ||
890 | node->map_nr = req->cmd_buf_nr; | 1170 | node->buf_info.map_nr = req->cmd_buf_nr; |
891 | if (req->cmd_buf_nr) { | 1171 | if (req->cmd_buf_nr) { |
892 | struct drm_exynos_g2d_cmd *cmd_buf; | 1172 | struct drm_exynos_g2d_cmd *cmd_buf; |
893 | 1173 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index 67e17ce112b6..0e6fe000578c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c | |||
@@ -164,6 +164,27 @@ out: | |||
164 | exynos_gem_obj = NULL; | 164 | exynos_gem_obj = NULL; |
165 | } | 165 | } |
166 | 166 | ||
167 | unsigned long exynos_drm_gem_get_size(struct drm_device *dev, | ||
168 | unsigned int gem_handle, | ||
169 | struct drm_file *file_priv) | ||
170 | { | ||
171 | struct exynos_drm_gem_obj *exynos_gem_obj; | ||
172 | struct drm_gem_object *obj; | ||
173 | |||
174 | obj = drm_gem_object_lookup(dev, file_priv, gem_handle); | ||
175 | if (!obj) { | ||
176 | DRM_ERROR("failed to lookup gem object.\n"); | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | exynos_gem_obj = to_exynos_gem_obj(obj); | ||
181 | |||
182 | drm_gem_object_unreference_unlocked(obj); | ||
183 | |||
184 | return exynos_gem_obj->buffer->size; | ||
185 | } | ||
186 | |||
187 | |||
167 | struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev, | 188 | struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev, |
168 | unsigned long size) | 189 | unsigned long size) |
169 | { | 190 | { |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h index 35ebac47dc2b..468766bee450 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.h +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h | |||
@@ -130,6 +130,11 @@ int exynos_drm_gem_userptr_ioctl(struct drm_device *dev, void *data, | |||
130 | int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data, | 130 | int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data, |
131 | struct drm_file *file_priv); | 131 | struct drm_file *file_priv); |
132 | 132 | ||
133 | /* get buffer size to gem handle. */ | ||
134 | unsigned long exynos_drm_gem_get_size(struct drm_device *dev, | ||
135 | unsigned int gem_handle, | ||
136 | struct drm_file *file_priv); | ||
137 | |||
133 | /* initialize gem object. */ | 138 | /* initialize gem object. */ |
134 | int exynos_drm_gem_init_object(struct drm_gem_object *obj); | 139 | int exynos_drm_gem_init_object(struct drm_gem_object *obj); |
135 | 140 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index 13ccbd4bcfaa..9504b0cd825a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c | |||
@@ -117,13 +117,12 @@ static struct edid *vidi_get_edid(struct device *dev, | |||
117 | } | 117 | } |
118 | 118 | ||
119 | edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH; | 119 | edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH; |
120 | edid = kzalloc(edid_len, GFP_KERNEL); | 120 | edid = kmemdup(ctx->raw_edid, edid_len, GFP_KERNEL); |
121 | if (!edid) { | 121 | if (!edid) { |
122 | DRM_DEBUG_KMS("failed to allocate edid\n"); | 122 | DRM_DEBUG_KMS("failed to allocate edid\n"); |
123 | return ERR_PTR(-ENOMEM); | 123 | return ERR_PTR(-ENOMEM); |
124 | } | 124 | } |
125 | 125 | ||
126 | memcpy(edid, ctx->raw_edid, edid_len); | ||
127 | return edid; | 126 | return edid; |
128 | } | 127 | } |
129 | 128 | ||
@@ -563,12 +562,11 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, | |||
563 | return -EINVAL; | 562 | return -EINVAL; |
564 | } | 563 | } |
565 | edid_len = (1 + raw_edid->extensions) * EDID_LENGTH; | 564 | edid_len = (1 + raw_edid->extensions) * EDID_LENGTH; |
566 | ctx->raw_edid = kzalloc(edid_len, GFP_KERNEL); | 565 | ctx->raw_edid = kmemdup(raw_edid, edid_len, GFP_KERNEL); |
567 | if (!ctx->raw_edid) { | 566 | if (!ctx->raw_edid) { |
568 | DRM_DEBUG_KMS("failed to allocate raw_edid.\n"); | 567 | DRM_DEBUG_KMS("failed to allocate raw_edid.\n"); |
569 | return -ENOMEM; | 568 | return -ENOMEM; |
570 | } | 569 | } |
571 | memcpy(ctx->raw_edid, raw_edid, edid_len); | ||
572 | } else { | 570 | } else { |
573 | /* | 571 | /* |
574 | * with connection = 0, free raw_edid | 572 | * with connection = 0, free raw_edid |
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index e919aba29b3d..2f4f72f07047 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c | |||
@@ -818,7 +818,7 @@ static void mixer_win_disable(void *ctx, int win) | |||
818 | mixer_ctx->win_data[win].enabled = false; | 818 | mixer_ctx->win_data[win].enabled = false; |
819 | } | 819 | } |
820 | 820 | ||
821 | int mixer_check_timing(void *ctx, struct fb_videomode *timing) | 821 | static int mixer_check_timing(void *ctx, struct fb_videomode *timing) |
822 | { | 822 | { |
823 | struct mixer_context *mixer_ctx = ctx; | 823 | struct mixer_context *mixer_ctx = ctx; |
824 | u32 w, h; | 824 | u32 w, h; |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 0a8eceb75902..e9b57893db2b 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
@@ -125,6 +125,11 @@ MODULE_PARM_DESC(preliminary_hw_support, | |||
125 | "Enable Haswell and ValleyView Support. " | 125 | "Enable Haswell and ValleyView Support. " |
126 | "(default: false)"); | 126 | "(default: false)"); |
127 | 127 | ||
128 | int i915_disable_power_well __read_mostly = 0; | ||
129 | module_param_named(disable_power_well, i915_disable_power_well, int, 0600); | ||
130 | MODULE_PARM_DESC(disable_power_well, | ||
131 | "Disable the power well when possible (default: false)"); | ||
132 | |||
128 | static struct drm_driver driver; | 133 | static struct drm_driver driver; |
129 | extern int intel_agp_enabled; | 134 | extern int intel_agp_enabled; |
130 | 135 | ||
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e95337c97459..01769e2a9953 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -1398,6 +1398,7 @@ extern int i915_enable_fbc __read_mostly; | |||
1398 | extern bool i915_enable_hangcheck __read_mostly; | 1398 | extern bool i915_enable_hangcheck __read_mostly; |
1399 | extern int i915_enable_ppgtt __read_mostly; | 1399 | extern int i915_enable_ppgtt __read_mostly; |
1400 | extern unsigned int i915_preliminary_hw_support __read_mostly; | 1400 | extern unsigned int i915_preliminary_hw_support __read_mostly; |
1401 | extern int i915_disable_power_well __read_mostly; | ||
1401 | 1402 | ||
1402 | extern int i915_suspend(struct drm_device *dev, pm_message_t state); | 1403 | extern int i915_suspend(struct drm_device *dev, pm_message_t state); |
1403 | extern int i915_resume(struct drm_device *dev); | 1404 | extern int i915_resume(struct drm_device *dev); |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 287b42c9d1a8..b20d50192fcc 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -5771,6 +5771,11 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc, | |||
5771 | num_connectors++; | 5771 | num_connectors++; |
5772 | } | 5772 | } |
5773 | 5773 | ||
5774 | if (is_cpu_edp) | ||
5775 | intel_crtc->cpu_transcoder = TRANSCODER_EDP; | ||
5776 | else | ||
5777 | intel_crtc->cpu_transcoder = pipe; | ||
5778 | |||
5774 | /* We are not sure yet this won't happen. */ | 5779 | /* We are not sure yet this won't happen. */ |
5775 | WARN(!HAS_PCH_LPT(dev), "Unexpected PCH type %d\n", | 5780 | WARN(!HAS_PCH_LPT(dev), "Unexpected PCH type %d\n", |
5776 | INTEL_PCH_TYPE(dev)); | 5781 | INTEL_PCH_TYPE(dev)); |
@@ -5837,11 +5842,6 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
5837 | int pipe = intel_crtc->pipe; | 5842 | int pipe = intel_crtc->pipe; |
5838 | int ret; | 5843 | int ret; |
5839 | 5844 | ||
5840 | if (IS_HASWELL(dev) && intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) | ||
5841 | intel_crtc->cpu_transcoder = TRANSCODER_EDP; | ||
5842 | else | ||
5843 | intel_crtc->cpu_transcoder = pipe; | ||
5844 | |||
5845 | drm_vblank_pre_modeset(dev, pipe); | 5845 | drm_vblank_pre_modeset(dev, pipe); |
5846 | 5846 | ||
5847 | ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode, | 5847 | ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode, |
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index a3730e0289e5..bee8cb6108a7 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c | |||
@@ -321,9 +321,6 @@ void intel_panel_enable_backlight(struct drm_device *dev, | |||
321 | if (dev_priv->backlight_level == 0) | 321 | if (dev_priv->backlight_level == 0) |
322 | dev_priv->backlight_level = intel_panel_get_max_backlight(dev); | 322 | dev_priv->backlight_level = intel_panel_get_max_backlight(dev); |
323 | 323 | ||
324 | dev_priv->backlight_enabled = true; | ||
325 | intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); | ||
326 | |||
327 | if (INTEL_INFO(dev)->gen >= 4) { | 324 | if (INTEL_INFO(dev)->gen >= 4) { |
328 | uint32_t reg, tmp; | 325 | uint32_t reg, tmp; |
329 | 326 | ||
@@ -359,12 +356,12 @@ void intel_panel_enable_backlight(struct drm_device *dev, | |||
359 | } | 356 | } |
360 | 357 | ||
361 | set_level: | 358 | set_level: |
362 | /* Check the current backlight level and try to set again if it's zero. | 359 | /* Call below after setting BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1. |
363 | * On some machines, BLC_PWM_CPU_CTL is cleared to zero automatically | 360 | * BLC_PWM_CPU_CTL may be cleared to zero automatically when these |
364 | * when BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1 are written. | 361 | * registers are set. |
365 | */ | 362 | */ |
366 | if (!intel_panel_get_backlight(dev)) | 363 | dev_priv->backlight_enabled = true; |
367 | intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); | 364 | intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); |
368 | } | 365 | } |
369 | 366 | ||
370 | static void intel_panel_init_backlight(struct drm_device *dev) | 367 | static void intel_panel_init_backlight(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a1794c6df1bf..adca00783e61 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
@@ -4079,6 +4079,9 @@ void intel_set_power_well(struct drm_device *dev, bool enable) | |||
4079 | if (!IS_HASWELL(dev)) | 4079 | if (!IS_HASWELL(dev)) |
4080 | return; | 4080 | return; |
4081 | 4081 | ||
4082 | if (!i915_disable_power_well && !enable) | ||
4083 | return; | ||
4084 | |||
4082 | tmp = I915_READ(HSW_PWR_WELL_DRIVER); | 4085 | tmp = I915_READ(HSW_PWR_WELL_DRIVER); |
4083 | is_enabled = tmp & HSW_PWR_WELL_STATE; | 4086 | is_enabled = tmp & HSW_PWR_WELL_STATE; |
4084 | enable_requested = tmp & HSW_PWR_WELL_ENABLE; | 4087 | enable_requested = tmp & HSW_PWR_WELL_ENABLE; |