Commit f34bc78741815d0ad07298a42101a1ee2e2bcdd2

Authored by Thierry Reding
1 parent 894752bb57

drm/tegra: Add plane support

Add support for the B and C planes which support RGB and YUV pixel
formats and can be used as overlays or hardware cursor. Currently 32-bit
XRGB as well as UYVY, YUV420 and YUV422 pixel formats are advertised.
Other formats should be easy to add but these are the most common ones
and should cover the majority of use-cases.

Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>

Showing 3 changed files with 372 additions and 95 deletions Side-by-side Diff

drivers/gpu/drm/tegra/dc.c
... ... @@ -18,26 +18,143 @@
18 18 #include "drm.h"
19 19 #include "dc.h"
20 20  
21   -struct tegra_dc_window {
22   - fixed20_12 x;
23   - fixed20_12 y;
24   - fixed20_12 w;
25   - fixed20_12 h;
26   - unsigned int outx;
27   - unsigned int outy;
28   - unsigned int outw;
29   - unsigned int outh;
30   - unsigned int stride;
31   - unsigned int fmt;
  21 +struct tegra_plane {
  22 + struct drm_plane base;
  23 + unsigned int index;
32 24 };
33 25  
  26 +static inline struct tegra_plane *to_tegra_plane(struct drm_plane *plane)
  27 +{
  28 + return container_of(plane, struct tegra_plane, base);
  29 +}
  30 +
  31 +static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
  32 + struct drm_framebuffer *fb, int crtc_x,
  33 + int crtc_y, unsigned int crtc_w,
  34 + unsigned int crtc_h, uint32_t src_x,
  35 + uint32_t src_y, uint32_t src_w, uint32_t src_h)
  36 +{
  37 + struct tegra_plane *p = to_tegra_plane(plane);
  38 + struct tegra_dc *dc = to_tegra_dc(crtc);
  39 + struct tegra_dc_window window;
  40 + unsigned int i;
  41 +
  42 + memset(&window, 0, sizeof(window));
  43 + window.src.x = src_x >> 16;
  44 + window.src.y = src_y >> 16;
  45 + window.src.w = src_w >> 16;
  46 + window.src.h = src_h >> 16;
  47 + window.dst.x = crtc_x;
  48 + window.dst.y = crtc_y;
  49 + window.dst.w = crtc_w;
  50 + window.dst.h = crtc_h;
  51 + window.format = tegra_dc_format(fb->pixel_format);
  52 + window.bits_per_pixel = fb->bits_per_pixel;
  53 +
  54 + for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) {
  55 + struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(fb, i);
  56 +
  57 + window.base[i] = gem->paddr + fb->offsets[i];
  58 +
  59 + /*
  60 + * Tegra doesn't support different strides for U and V planes
  61 + * so we display a warning if the user tries to display a
  62 + * framebuffer with such a configuration.
  63 + */
  64 + if (i >= 2) {
  65 + if (fb->pitches[i] != window.stride[1])
  66 + DRM_ERROR("unsupported UV-plane configuration\n");
  67 + } else {
  68 + window.stride[i] = fb->pitches[i];
  69 + }
  70 + }
  71 +
  72 + return tegra_dc_setup_window(dc, p->index, &window);
  73 +}
  74 +
  75 +static int tegra_plane_disable(struct drm_plane *plane)
  76 +{
  77 + struct tegra_dc *dc = to_tegra_dc(plane->crtc);
  78 + struct tegra_plane *p = to_tegra_plane(plane);
  79 + unsigned long value;
  80 +
  81 + value = WINDOW_A_SELECT << p->index;
  82 + tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);
  83 +
  84 + value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS);
  85 + value &= ~WIN_ENABLE;
  86 + tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
  87 +
  88 + tegra_dc_writel(dc, WIN_A_UPDATE << p->index, DC_CMD_STATE_CONTROL);
  89 + tegra_dc_writel(dc, WIN_A_ACT_REQ << p->index, DC_CMD_STATE_CONTROL);
  90 +
  91 + return 0;
  92 +}
  93 +
  94 +static void tegra_plane_destroy(struct drm_plane *plane)
  95 +{
  96 + tegra_plane_disable(plane);
  97 + drm_plane_cleanup(plane);
  98 +}
  99 +
  100 +static const struct drm_plane_funcs tegra_plane_funcs = {
  101 + .update_plane = tegra_plane_update,
  102 + .disable_plane = tegra_plane_disable,
  103 + .destroy = tegra_plane_destroy,
  104 +};
  105 +
  106 +static const uint32_t plane_formats[] = {
  107 + DRM_FORMAT_XRGB8888,
  108 + DRM_FORMAT_UYVY,
  109 + DRM_FORMAT_YUV420,
  110 + DRM_FORMAT_YUV422,
  111 +};
  112 +
  113 +static int tegra_dc_add_planes(struct drm_device *drm, struct tegra_dc *dc)
  114 +{
  115 + unsigned int i;
  116 + int err = 0;
  117 +
  118 + for (i = 0; i < 2; i++) {
  119 + struct tegra_plane *plane;
  120 +
  121 + plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL);
  122 + if (!plane)
  123 + return -ENOMEM;
  124 +
  125 + plane->index = 1 + i;
  126 +
  127 + err = drm_plane_init(drm, &plane->base, 1 << dc->pipe,
  128 + &tegra_plane_funcs, plane_formats,
  129 + ARRAY_SIZE(plane_formats), false);
  130 + if (err < 0)
  131 + return err;
  132 + }
  133 +
  134 + return 0;
  135 +}
  136 +
34 137 static const struct drm_crtc_funcs tegra_crtc_funcs = {
35 138 .set_config = drm_crtc_helper_set_config,
36 139 .destroy = drm_crtc_cleanup,
37 140 };
38 141  
39   -static void tegra_crtc_dpms(struct drm_crtc *crtc, int mode)
  142 +static void tegra_crtc_disable(struct drm_crtc *crtc)
40 143 {
  144 + struct drm_device *drm = crtc->dev;
  145 + struct drm_plane *plane;
  146 +
  147 + list_for_each_entry(plane, &drm->mode_config.plane_list, head) {
  148 + if (plane->crtc == crtc) {
  149 + tegra_plane_disable(plane);
  150 + plane->crtc = NULL;
  151 +
  152 + if (plane->fb) {
  153 + drm_framebuffer_unreference(plane->fb);
  154 + plane->fb = NULL;
  155 + }
  156 + }
  157 + }
41 158 }
42 159  
43 160 static bool tegra_crtc_mode_fixup(struct drm_crtc *crtc,
44 161  
... ... @@ -47,10 +164,11 @@
47 164 return true;
48 165 }
49 166  
50   -static inline u32 compute_dda_inc(fixed20_12 inf, unsigned int out, bool v,
  167 +static inline u32 compute_dda_inc(unsigned int in, unsigned int out, bool v,
51 168 unsigned int bpp)
52 169 {
53 170 fixed20_12 outf = dfixed_init(out);
  171 + fixed20_12 inf = dfixed_init(in);
54 172 u32 dda_inc;
55 173 int max;
56 174  
57 175  
... ... @@ -80,9 +198,10 @@
80 198 return dda_inc;
81 199 }
82 200  
83   -static inline u32 compute_initial_dda(fixed20_12 in)
  201 +static inline u32 compute_initial_dda(unsigned int in)
84 202 {
85   - return dfixed_frac(in);
  203 + fixed20_12 inf = dfixed_init(in);
  204 + return dfixed_frac(inf);
86 205 }
87 206  
88 207 static int tegra_dc_set_timings(struct tegra_dc *dc,
... ... @@ -153,6 +272,185 @@
153 272 return 0;
154 273 }
155 274  
  275 +static bool tegra_dc_format_is_yuv(unsigned int format, bool *planar)
  276 +{
  277 + switch (format) {
  278 + case WIN_COLOR_DEPTH_YCbCr422:
  279 + case WIN_COLOR_DEPTH_YUV422:
  280 + if (planar)
  281 + *planar = false;
  282 +
  283 + return true;
  284 +
  285 + case WIN_COLOR_DEPTH_YCbCr420P:
  286 + case WIN_COLOR_DEPTH_YUV420P:
  287 + case WIN_COLOR_DEPTH_YCbCr422P:
  288 + case WIN_COLOR_DEPTH_YUV422P:
  289 + case WIN_COLOR_DEPTH_YCbCr422R:
  290 + case WIN_COLOR_DEPTH_YUV422R:
  291 + case WIN_COLOR_DEPTH_YCbCr422RA:
  292 + case WIN_COLOR_DEPTH_YUV422RA:
  293 + if (planar)
  294 + *planar = true;
  295 +
  296 + return true;
  297 + }
  298 +
  299 + return false;
  300 +}
  301 +
  302 +int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
  303 + const struct tegra_dc_window *window)
  304 +{
  305 + unsigned h_offset, v_offset, h_size, v_size, h_dda, v_dda, bpp;
  306 + unsigned long value;
  307 + bool yuv, planar;
  308 +
  309 + /*
  310 + * For YUV planar modes, the number of bytes per pixel takes into
  311 + * account only the luma component and therefore is 1.
  312 + */
  313 + yuv = tegra_dc_format_is_yuv(window->format, &planar);
  314 + if (!yuv)
  315 + bpp = window->bits_per_pixel / 8;
  316 + else
  317 + bpp = planar ? 1 : 2;
  318 +
  319 + value = WINDOW_A_SELECT << index;
  320 + tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);
  321 +
  322 + tegra_dc_writel(dc, window->format, DC_WIN_COLOR_DEPTH);
  323 + tegra_dc_writel(dc, 0, DC_WIN_BYTE_SWAP);
  324 +
  325 + value = V_POSITION(window->dst.y) | H_POSITION(window->dst.x);
  326 + tegra_dc_writel(dc, value, DC_WIN_POSITION);
  327 +
  328 + value = V_SIZE(window->dst.h) | H_SIZE(window->dst.w);
  329 + tegra_dc_writel(dc, value, DC_WIN_SIZE);
  330 +
  331 + h_offset = window->src.x * bpp;
  332 + v_offset = window->src.y;
  333 + h_size = window->src.w * bpp;
  334 + v_size = window->src.h;
  335 +
  336 + value = V_PRESCALED_SIZE(v_size) | H_PRESCALED_SIZE(h_size);
  337 + tegra_dc_writel(dc, value, DC_WIN_PRESCALED_SIZE);
  338 +
  339 + /*
  340 + * For DDA computations the number of bytes per pixel for YUV planar
  341 + * modes needs to take into account all Y, U and V components.
  342 + */
  343 + if (yuv && planar)
  344 + bpp = 2;
  345 +
  346 + h_dda = compute_dda_inc(window->src.w, window->dst.w, false, bpp);
  347 + v_dda = compute_dda_inc(window->src.h, window->dst.h, true, bpp);
  348 +
  349 + value = V_DDA_INC(v_dda) | H_DDA_INC(h_dda);
  350 + tegra_dc_writel(dc, value, DC_WIN_DDA_INC);
  351 +
  352 + h_dda = compute_initial_dda(window->src.x);
  353 + v_dda = compute_initial_dda(window->src.y);
  354 +
  355 + tegra_dc_writel(dc, h_dda, DC_WIN_H_INITIAL_DDA);
  356 + tegra_dc_writel(dc, v_dda, DC_WIN_V_INITIAL_DDA);
  357 +
  358 + tegra_dc_writel(dc, 0, DC_WIN_UV_BUF_STRIDE);
  359 + tegra_dc_writel(dc, 0, DC_WIN_BUF_STRIDE);
  360 +
  361 + tegra_dc_writel(dc, window->base[0], DC_WINBUF_START_ADDR);
  362 +
  363 + if (yuv && planar) {
  364 + tegra_dc_writel(dc, window->base[1], DC_WINBUF_START_ADDR_U);
  365 + tegra_dc_writel(dc, window->base[2], DC_WINBUF_START_ADDR_V);
  366 + value = window->stride[1] << 16 | window->stride[0];
  367 + tegra_dc_writel(dc, value, DC_WIN_LINE_STRIDE);
  368 + } else {
  369 + tegra_dc_writel(dc, window->stride[0], DC_WIN_LINE_STRIDE);
  370 + }
  371 +
  372 + tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET);
  373 + tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET);
  374 +
  375 + value = WIN_ENABLE;
  376 +
  377 + if (yuv) {
  378 + /* setup default colorspace conversion coefficients */
  379 + tegra_dc_writel(dc, 0x00f0, DC_WIN_CSC_YOF);
  380 + tegra_dc_writel(dc, 0x012a, DC_WIN_CSC_KYRGB);
  381 + tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KUR);
  382 + tegra_dc_writel(dc, 0x0198, DC_WIN_CSC_KVR);
  383 + tegra_dc_writel(dc, 0x039b, DC_WIN_CSC_KUG);
  384 + tegra_dc_writel(dc, 0x032f, DC_WIN_CSC_KVG);
  385 + tegra_dc_writel(dc, 0x0204, DC_WIN_CSC_KUB);
  386 + tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KVB);
  387 +
  388 + value |= CSC_ENABLE;
  389 + } else if (bpp < 24) {
  390 + value |= COLOR_EXPAND;
  391 + }
  392 +
  393 + tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
  394 +
  395 + /*
  396 + * Disable blending and assume Window A is the bottom-most window,
  397 + * Window C is the top-most window and Window B is in the middle.
  398 + */
  399 + tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_NOKEY);
  400 + tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_1WIN);
  401 +
  402 + switch (index) {
  403 + case 0:
  404 + tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_X);
  405 + tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_Y);
  406 + tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_3WIN_XY);
  407 + break;
  408 +
  409 + case 1:
  410 + tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_X);
  411 + tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_Y);
  412 + tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_3WIN_XY);
  413 + break;
  414 +
  415 + case 2:
  416 + tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_X);
  417 + tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_Y);
  418 + tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_3WIN_XY);
  419 + break;
  420 + }
  421 +
  422 + tegra_dc_writel(dc, WIN_A_UPDATE << index, DC_CMD_STATE_CONTROL);
  423 + tegra_dc_writel(dc, WIN_A_ACT_REQ << index, DC_CMD_STATE_CONTROL);
  424 +
  425 + return 0;
  426 +}
  427 +
  428 +unsigned int tegra_dc_format(uint32_t format)
  429 +{
  430 + switch (format) {
  431 + case DRM_FORMAT_XRGB8888:
  432 + return WIN_COLOR_DEPTH_B8G8R8A8;
  433 +
  434 + case DRM_FORMAT_RGB565:
  435 + return WIN_COLOR_DEPTH_B5G6R5;
  436 +
  437 + case DRM_FORMAT_UYVY:
  438 + return WIN_COLOR_DEPTH_YCbCr422;
  439 +
  440 + case DRM_FORMAT_YUV420:
  441 + return WIN_COLOR_DEPTH_YCbCr420P;
  442 +
  443 + case DRM_FORMAT_YUV422:
  444 + return WIN_COLOR_DEPTH_YCbCr422P;
  445 +
  446 + default:
  447 + break;
  448 + }
  449 +
  450 + WARN(1, "unsupported pixel format %u, using default\n", format);
  451 + return WIN_COLOR_DEPTH_B8G8R8A8;
  452 +}
  453 +
156 454 static int tegra_crtc_mode_set(struct drm_crtc *crtc,
157 455 struct drm_display_mode *mode,
158 456 struct drm_display_mode *adjusted,
... ... @@ -160,8 +458,7 @@
160 458 {
161 459 struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(crtc->fb, 0);
162 460 struct tegra_dc *dc = to_tegra_dc(crtc);
163   - unsigned int h_dda, v_dda, bpp;
164   - struct tegra_dc_window win;
  461 + struct tegra_dc_window window;
165 462 unsigned long div, value;
166 463 int err;
167 464  
168 465  
169 466  
... ... @@ -192,82 +489,24 @@
192 489 tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL);
193 490  
194 491 /* setup window parameters */
195   - memset(&win, 0, sizeof(win));
196   - win.x.full = dfixed_const(0);
197   - win.y.full = dfixed_const(0);
198   - win.w.full = dfixed_const(mode->hdisplay);
199   - win.h.full = dfixed_const(mode->vdisplay);
200   - win.outx = 0;
201   - win.outy = 0;
202   - win.outw = mode->hdisplay;
203   - win.outh = mode->vdisplay;
  492 + memset(&window, 0, sizeof(window));
  493 + window.src.x = 0;
  494 + window.src.y = 0;
  495 + window.src.w = mode->hdisplay;
  496 + window.src.h = mode->vdisplay;
  497 + window.dst.x = 0;
  498 + window.dst.y = 0;
  499 + window.dst.w = mode->hdisplay;
  500 + window.dst.h = mode->vdisplay;
  501 + window.format = tegra_dc_format(crtc->fb->pixel_format);
  502 + window.bits_per_pixel = crtc->fb->bits_per_pixel;
  503 + window.stride[0] = crtc->fb->pitches[0];
  504 + window.base[0] = gem->paddr;
204 505  
205   - switch (crtc->fb->pixel_format) {
206   - case DRM_FORMAT_XRGB8888:
207   - win.fmt = WIN_COLOR_DEPTH_B8G8R8A8;
208   - break;
  506 + err = tegra_dc_setup_window(dc, 0, &window);
  507 + if (err < 0)
  508 + dev_err(dc->dev, "failed to enable root plane\n");
209 509  
210   - case DRM_FORMAT_RGB565:
211   - win.fmt = WIN_COLOR_DEPTH_B5G6R5;
212   - break;
213   -
214   - default:
215   - win.fmt = WIN_COLOR_DEPTH_B8G8R8A8;
216   - WARN_ON(1);
217   - break;
218   - }
219   -
220   - bpp = crtc->fb->bits_per_pixel / 8;
221   - win.stride = crtc->fb->pitches[0];
222   -
223   - /* program window registers */
224   - value = WINDOW_A_SELECT;
225   - tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);
226   -
227   - tegra_dc_writel(dc, win.fmt, DC_WIN_COLOR_DEPTH);
228   - tegra_dc_writel(dc, 0, DC_WIN_BYTE_SWAP);
229   -
230   - value = V_POSITION(win.outy) | H_POSITION(win.outx);
231   - tegra_dc_writel(dc, value, DC_WIN_POSITION);
232   -
233   - value = V_SIZE(win.outh) | H_SIZE(win.outw);
234   - tegra_dc_writel(dc, value, DC_WIN_SIZE);
235   -
236   - value = V_PRESCALED_SIZE(dfixed_trunc(win.h)) |
237   - H_PRESCALED_SIZE(dfixed_trunc(win.w) * bpp);
238   - tegra_dc_writel(dc, value, DC_WIN_PRESCALED_SIZE);
239   -
240   - h_dda = compute_dda_inc(win.w, win.outw, false, bpp);
241   - v_dda = compute_dda_inc(win.h, win.outh, true, bpp);
242   -
243   - value = V_DDA_INC(v_dda) | H_DDA_INC(h_dda);
244   - tegra_dc_writel(dc, value, DC_WIN_DDA_INC);
245   -
246   - h_dda = compute_initial_dda(win.x);
247   - v_dda = compute_initial_dda(win.y);
248   -
249   - tegra_dc_writel(dc, h_dda, DC_WIN_H_INITIAL_DDA);
250   - tegra_dc_writel(dc, v_dda, DC_WIN_V_INITIAL_DDA);
251   -
252   - tegra_dc_writel(dc, 0, DC_WIN_UV_BUF_STRIDE);
253   - tegra_dc_writel(dc, 0, DC_WIN_BUF_STRIDE);
254   -
255   - tegra_dc_writel(dc, fb->obj->paddr, DC_WINBUF_START_ADDR);
256   - tegra_dc_writel(dc, win.stride, DC_WIN_LINE_STRIDE);
257   - tegra_dc_writel(dc, dfixed_trunc(win.x) * bpp,
258   - DC_WINBUF_ADDR_H_OFFSET);
259   - tegra_dc_writel(dc, dfixed_trunc(win.y), DC_WINBUF_ADDR_V_OFFSET);
260   -
261   - value = WIN_ENABLE;
262   -
263   - if (bpp < 24)
264   - value |= COLOR_EXPAND;
265   -
266   - tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
267   -
268   - tegra_dc_writel(dc, 0xff00, DC_WIN_BLEND_NOKEY);
269   - tegra_dc_writel(dc, 0xff00, DC_WIN_BLEND_1WIN);
270   -
271 510 return 0;
272 511 }
273 512  
... ... @@ -347,7 +586,7 @@
347 586 }
348 587  
349 588 static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = {
350   - .dpms = tegra_crtc_dpms,
  589 + .disable = tegra_crtc_disable,
351 590 .mode_fixup = tegra_crtc_mode_fixup,
352 591 .mode_set = tegra_crtc_mode_set,
353 592 .prepare = tegra_crtc_prepare,
... ... @@ -588,7 +827,7 @@
588 827 DUMP_REG(DC_WIN_BLEND_1WIN);
589 828 DUMP_REG(DC_WIN_BLEND_2WIN_X);
590 829 DUMP_REG(DC_WIN_BLEND_2WIN_Y);
591   - DUMP_REG(DC_WIN_BLEND32WIN_XY);
  830 + DUMP_REG(DC_WIN_BLEND_3WIN_XY);
592 831 DUMP_REG(DC_WIN_HP_FETCH_CONTROL);
593 832 DUMP_REG(DC_WINBUF_START_ADDR);
594 833 DUMP_REG(DC_WINBUF_START_ADDR_NS);
... ... @@ -689,6 +928,10 @@
689 928 dev_err(dc->dev, "failed to initialize RGB output: %d\n", err);
690 929 return err;
691 930 }
  931 +
  932 + err = tegra_dc_add_planes(drm, dc);
  933 + if (err < 0)
  934 + return err;
692 935  
693 936 if (IS_ENABLED(CONFIG_DEBUG_FS)) {
694 937 err = tegra_dc_debugfs_init(dc, drm->primary);
drivers/gpu/drm/tegra/dc.h
... ... @@ -290,8 +290,18 @@
290 290 #define DC_DISP_SD_HW_K_VALUES 0x4dd
291 291 #define DC_DISP_SD_MAN_K_VALUES 0x4de
292 292  
  293 +#define DC_WIN_CSC_YOF 0x611
  294 +#define DC_WIN_CSC_KYRGB 0x612
  295 +#define DC_WIN_CSC_KUR 0x613
  296 +#define DC_WIN_CSC_KVR 0x614
  297 +#define DC_WIN_CSC_KUG 0x615
  298 +#define DC_WIN_CSC_KVG 0x616
  299 +#define DC_WIN_CSC_KUB 0x617
  300 +#define DC_WIN_CSC_KVB 0x618
  301 +
293 302 #define DC_WIN_WIN_OPTIONS 0x700
294 303 #define COLOR_EXPAND (1 << 6)
  304 +#define CSC_ENABLE (1 << 18)
295 305 #define WIN_ENABLE (1 << 30)
296 306  
297 307 #define DC_WIN_BYTE_SWAP 0x701
... ... @@ -359,7 +369,7 @@
359 369 #define DC_WIN_BLEND_1WIN 0x710
360 370 #define DC_WIN_BLEND_2WIN_X 0x711
361 371 #define DC_WIN_BLEND_2WIN_Y 0x712
362   -#define DC_WIN_BLEND32WIN_XY 0x713
  372 +#define DC_WIN_BLEND_3WIN_XY 0x713
363 373  
364 374 #define DC_WIN_HP_FETCH_CONTROL 0x714
365 375  
drivers/gpu/drm/tegra/drm.h
... ... @@ -107,6 +107,30 @@
107 107 return readl(dc->regs + (reg << 2));
108 108 }
109 109  
  110 +struct tegra_dc_window {
  111 + struct {
  112 + unsigned int x;
  113 + unsigned int y;
  114 + unsigned int w;
  115 + unsigned int h;
  116 + } src;
  117 + struct {
  118 + unsigned int x;
  119 + unsigned int y;
  120 + unsigned int w;
  121 + unsigned int h;
  122 + } dst;
  123 + unsigned int bits_per_pixel;
  124 + unsigned int format;
  125 + unsigned int stride[2];
  126 + unsigned long base[3];
  127 +};
  128 +
  129 +/* from dc.c */
  130 +extern unsigned int tegra_dc_format(uint32_t format);
  131 +extern int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
  132 + const struct tegra_dc_window *window);
  133 +
110 134 struct tegra_output_ops {
111 135 int (*enable)(struct tegra_output *output);
112 136 int (*disable)(struct tegra_output *output);