diff options
| author | Arnd Bergmann <arnd@arndb.de> | 2013-04-08 13:30:48 -0400 |
|---|---|---|
| committer | Arnd Bergmann <arnd@arndb.de> | 2013-04-08 13:30:48 -0400 |
| commit | dc2d3db8137fba0f62d7517e1bea8a47f69fcbc4 (patch) | |
| tree | aee802680d09fe7c1288138cbfc0db17702e8075 /drivers/gpu | |
| parent | 8355ae69afca3b6bcb7b68712f30223455caebda (diff) | |
| parent | 7f585bbfc54fec9dcf387fd2edb2d6f4908badf8 (diff) | |
Merge tag 'omap-for-v3.10/timer-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into next/drivers
From Tony Lindgren <tony@atomide.com>:
Clean-up for omap2+ timers from Jon Hunter <jon-hunter@ti.com>:
This series consists mainly of clean-ups for clockevents and
clocksource timers on OMAP2+ devices. The most significant change
in functionality comes from the 5th patch which is changing the
selection of the clocksource timer for OMAP3 and AM335x devices
when gptimers are used for clocksource.
Note that this series depends on 7185684 (ARM: OMAP: use
consistent error checking) in RMK's tree and 960cba6 (ARM:
OMAP5: timer: Update the clocksource name as per clock data)
in omap-for-v3.10/fixes-non-critical. So this branch is based
on a merge of 7185684 and omap-for-v3.10/fixes-non-critical
to avoid non-trivial merge conflicts.
* tag 'omap-for-v3.10/timer-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap:
ARM: OMAP4+: Fix sparse warning in system timers
ARM: OMAP2+: Store ID of system timers in timer structure
ARM: OMAP3: Update clocksource timer selection
ARM: OMAP2+: Simplify system timers definitions
ARM: OMAP2+: Simplify system timer clock definitions
ARM: OMAP2+: Remove hard-coded test on timer ID
ARM: OMAP2+: Display correct system timer name
ARM: OMAP2+: fix typo "CONFIG_BRIDGE_DVFS"
ARM: OMAP1: remove "config MACH_OMAP_HTCWIZARD"
ARM: OMAP: dpll: enable bypass clock only when attempting dpll bypass
ARM: OMAP2+: powerdomain: avoid testing whether an unsigned char is less than 0
ARM: OMAP2+: hwmod: Remove unused _HWMOD_WAKEUP_ENABLED flag
ARM: OMAP2+: am335x: Change the wdt1 func clk src to per_32k clk
ARM: OMAP2+: AM33xx: hwmod: Add missing sysc definition to wdt1 entry
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'drivers/gpu')
| -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; |
