1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2014 The Linux Foundation. All rights reserved. 4 * Copyright (C) 2013 Red Hat 5 * Author: Rob Clark <robdclark@gmail.com> 6 */ 7 8 #include <drm/drm_fourcc.h> 9 #include <drm/drm_framebuffer.h> 10 11 #include "msm_drv.h" 12 #include "mdp_kms.h" 13 14 static struct csc_cfg csc_convert[CSC_MAX] = { 15 [CSC_RGB2RGB] = { 16 .type = CSC_RGB2RGB, 17 .matrix = { 18 0x0200, 0x0000, 0x0000, 19 0x0000, 0x0200, 0x0000, 20 0x0000, 0x0000, 0x0200 21 }, 22 .pre_bias = { 0x0, 0x0, 0x0 }, 23 .post_bias = { 0x0, 0x0, 0x0 }, 24 .pre_clamp = { 0x0, 0xff, 0x0, 0xff, 0x0, 0xff }, 25 .post_clamp = { 0x0, 0xff, 0x0, 0xff, 0x0, 0xff }, 26 }, 27 [CSC_YUV2RGB] = { 28 .type = CSC_YUV2RGB, 29 .matrix = { 30 0x0254, 0x0000, 0x0331, 31 0x0254, 0xff37, 0xfe60, 32 0x0254, 0x0409, 0x0000 33 }, 34 .pre_bias = { 0xfff0, 0xff80, 0xff80 }, 35 .post_bias = { 0x00, 0x00, 0x00 }, 36 .pre_clamp = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff }, 37 .post_clamp = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff }, 38 }, 39 [CSC_RGB2YUV] = { 40 .type = CSC_RGB2YUV, 41 .matrix = { 42 0x0083, 0x0102, 0x0032, 43 0x1fb5, 0x1f6c, 0x00e1, 44 0x00e1, 0x1f45, 0x1fdc 45 }, 46 .pre_bias = { 0x00, 0x00, 0x00 }, 47 .post_bias = { 0x10, 0x80, 0x80 }, 48 .pre_clamp = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff }, 49 .post_clamp = { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0 }, 50 }, 51 [CSC_YUV2YUV] = { 52 .type = CSC_YUV2YUV, 53 .matrix = { 54 0x0200, 0x0000, 0x0000, 55 0x0000, 0x0200, 0x0000, 56 0x0000, 0x0000, 0x0200 57 }, 58 .pre_bias = { 0x00, 0x00, 0x00 }, 59 .post_bias = { 0x00, 0x00, 0x00 }, 60 .pre_clamp = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff }, 61 .post_clamp = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff }, 62 }, 63 }; 64 65 #define FMT(name, a, r, g, b, e0, e1, e2, e3, alpha, tight, c, cnt, fp, cs, yuv) { \ 66 .base = { .pixel_format = DRM_FORMAT_ ## name }, \ 67 .bpc_a = BPC ## a ## A, \ 68 .bpc_r = BPC ## r, \ 69 .bpc_g = BPC ## g, \ 70 .bpc_b = BPC ## b, \ 71 .unpack = { e0, e1, e2, e3 }, \ 72 .alpha_enable = alpha, \ 73 .unpack_tight = tight, \ 74 .cpp = c, \ 75 .unpack_count = cnt, \ 76 .fetch_type = fp, \ 77 .chroma_sample = cs, \ 78 .is_yuv = yuv, \ 79 } 80 81 #define BPC0A 0 82 83 /* 84 * Note: Keep RGB formats 1st, followed by YUV formats to avoid breaking 85 * mdp_get_rgb_formats()'s implementation. 86 */ 87 static const struct mdp_format formats[] = { 88 /* name a r g b e0 e1 e2 e3 alpha tight cpp cnt ... */ 89 FMT(ARGB8888, 8, 8, 8, 8, 1, 0, 2, 3, true, true, 4, 4, 90 MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), 91 FMT(ABGR8888, 8, 8, 8, 8, 2, 0, 1, 3, true, true, 4, 4, 92 MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), 93 FMT(RGBA8888, 8, 8, 8, 8, 3, 1, 0, 2, true, true, 4, 4, 94 MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), 95 FMT(BGRA8888, 8, 8, 8, 8, 3, 2, 0, 1, true, true, 4, 4, 96 MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), 97 FMT(XRGB8888, 8, 8, 8, 8, 1, 0, 2, 3, false, true, 4, 4, 98 MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), 99 FMT(XBGR8888, 8, 8, 8, 8, 2, 0, 1, 3, false, true, 4, 4, 100 MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), 101 FMT(RGBX8888, 8, 8, 8, 8, 3, 1, 0, 2, false, true, 4, 4, 102 MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), 103 FMT(BGRX8888, 8, 8, 8, 8, 3, 2, 0, 1, false, true, 4, 4, 104 MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), 105 FMT(RGB888, 0, 8, 8, 8, 1, 0, 2, 0, false, true, 3, 3, 106 MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), 107 FMT(BGR888, 0, 8, 8, 8, 2, 0, 1, 0, false, true, 3, 3, 108 MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), 109 FMT(RGB565, 0, 5, 6, 5, 1, 0, 2, 0, false, true, 2, 3, 110 MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), 111 FMT(BGR565, 0, 5, 6, 5, 2, 0, 1, 0, false, true, 2, 3, 112 MDP_PLANE_INTERLEAVED, CHROMA_FULL, false), 113 114 /* --- RGB formats above / YUV formats below this line --- */ 115 116 /* 2 plane YUV */ 117 FMT(NV12, 0, 8, 8, 8, 1, 2, 0, 0, false, true, 2, 2, 118 MDP_PLANE_PSEUDO_PLANAR, CHROMA_420, true), 119 FMT(NV21, 0, 8, 8, 8, 2, 1, 0, 0, false, true, 2, 2, 120 MDP_PLANE_PSEUDO_PLANAR, CHROMA_420, true), 121 FMT(NV16, 0, 8, 8, 8, 1, 2, 0, 0, false, true, 2, 2, 122 MDP_PLANE_PSEUDO_PLANAR, CHROMA_H2V1, true), 123 FMT(NV61, 0, 8, 8, 8, 2, 1, 0, 0, false, true, 2, 2, 124 MDP_PLANE_PSEUDO_PLANAR, CHROMA_H2V1, true), 125 /* 1 plane YUV */ 126 FMT(VYUY, 0, 8, 8, 8, 2, 0, 1, 0, false, true, 2, 4, 127 MDP_PLANE_INTERLEAVED, CHROMA_H2V1, true), 128 FMT(UYVY, 0, 8, 8, 8, 1, 0, 2, 0, false, true, 2, 4, 129 MDP_PLANE_INTERLEAVED, CHROMA_H2V1, true), 130 FMT(YUYV, 0, 8, 8, 8, 0, 1, 0, 2, false, true, 2, 4, 131 MDP_PLANE_INTERLEAVED, CHROMA_H2V1, true), 132 FMT(YVYU, 0, 8, 8, 8, 0, 2, 0, 1, false, true, 2, 4, 133 MDP_PLANE_INTERLEAVED, CHROMA_H2V1, true), 134 /* 3 plane YUV */ 135 FMT(YUV420, 0, 8, 8, 8, 2, 1, 0, 0, false, true, 1, 1, 136 MDP_PLANE_PLANAR, CHROMA_420, true), 137 FMT(YVU420, 0, 8, 8, 8, 1, 2, 0, 0, false, true, 1, 1, 138 MDP_PLANE_PLANAR, CHROMA_420, true), 139 }; 140 141 /* 142 * Note: 143 * @rgb_only must be set to true, when requesting 144 * supported formats for RGB pipes. 145 */ 146 uint32_t mdp_get_formats(uint32_t *pixel_formats, uint32_t max_formats, 147 bool rgb_only) 148 { 149 uint32_t i; 150 for (i = 0; i < ARRAY_SIZE(formats); i++) { 151 const struct mdp_format *f = &formats[i]; 152 153 if (i == max_formats) 154 break; 155 156 if (rgb_only && MDP_FORMAT_IS_YUV(f)) 157 break; 158 159 pixel_formats[i] = f->base.pixel_format; 160 } 161 162 return i; 163 } 164 165 const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format, 166 uint64_t modifier) 167 { 168 int i; 169 for (i = 0; i < ARRAY_SIZE(formats); i++) { 170 const struct mdp_format *f = &formats[i]; 171 if (f->base.pixel_format == format) 172 return &f->base; 173 } 174 return NULL; 175 } 176 177 struct csc_cfg *mdp_get_default_csc_cfg(enum csc_type type) 178 { 179 if (WARN_ON(type >= CSC_MAX)) 180 return NULL; 181 182 return &csc_convert[type]; 183 } 184