aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/amba-clcd.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2011-01-21 09:03:28 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2011-02-19 06:09:05 -0500
commit7b4e9ced69a120e7e7446e3303d2307aa29d891c (patch)
treea39b9782e2aa4e9f7f386dade06111fe0c6c3f34 /drivers/video/amba-clcd.c
parent9c49e4ab84dd46769e7fd9773946e10c95bab680 (diff)
ARM: clcd: add method for describing display capabilities
The ARM CLCD PL110 controller in TFT mode provides two output formats based on whether the controller is in 24bpp mode or not - either 5551 or 888. PL111 augments this with a 444 and 565 modes. Some implementations provide an external MUX on the PL110 output to reassign the bits to achieve 565 mode. Provide a system of capability flags to allow the CLCD driver to work out what is supported by each panel and board, and therefore which display formats are permitted. Acked-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/video/amba-clcd.c')
-rw-r--r--drivers/video/amba-clcd.c95
1 files changed, 84 insertions, 11 deletions
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
index aedbb345f8a9..8bd370697533 100644
--- a/drivers/video/amba-clcd.c
+++ b/drivers/video/amba-clcd.c
@@ -120,8 +120,23 @@ static void clcdfb_enable(struct clcd_fb *fb, u32 cntl)
120static int 120static int
121clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var) 121clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var)
122{ 122{
123 u32 caps;
123 int ret = 0; 124 int ret = 0;
124 125
126 if (fb->panel->caps && fb->board->caps)
127 caps = fb->panel->caps & fb->board->caps;
128 else {
129 /* Old way of specifying what can be used */
130 caps = fb->panel->cntl & CNTL_BGR ?
131 CLCD_CAP_BGR : CLCD_CAP_RGB;
132 /* But mask out 444 modes as they weren't supported */
133 caps &= ~CLCD_CAP_444;
134 }
135
136 /* Only TFT panels can do RGB888/BGR888 */
137 if (!(fb->panel->cntl & CNTL_LCDTFT))
138 caps &= ~CLCD_CAP_888;
139
125 memset(&var->transp, 0, sizeof(var->transp)); 140 memset(&var->transp, 0, sizeof(var->transp));
126 141
127 var->red.msb_right = 0; 142 var->red.msb_right = 0;
@@ -133,6 +148,13 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var)
133 case 2: 148 case 2:
134 case 4: 149 case 4:
135 case 8: 150 case 8:
151 /* If we can't do 5551, reject */
152 caps &= CLCD_CAP_5551;
153 if (!caps) {
154 ret = -EINVAL;
155 break;
156 }
157
136 var->red.length = var->bits_per_pixel; 158 var->red.length = var->bits_per_pixel;
137 var->red.offset = 0; 159 var->red.offset = 0;
138 var->green.length = var->bits_per_pixel; 160 var->green.length = var->bits_per_pixel;
@@ -140,23 +162,61 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var)
140 var->blue.length = var->bits_per_pixel; 162 var->blue.length = var->bits_per_pixel;
141 var->blue.offset = 0; 163 var->blue.offset = 0;
142 break; 164 break;
165
143 case 16: 166 case 16:
144 var->red.length = 5; 167 /* If we can't do 444, 5551 or 565, reject */
145 var->blue.length = 5; 168 if (!(caps & (CLCD_CAP_444 | CLCD_CAP_5551 | CLCD_CAP_565))) {
169 ret = -EINVAL;
170 break;
171 }
172
146 /* 173 /*
147 * Green length can be 5 or 6 depending whether 174 * Green length can be 4, 5 or 6 depending whether
148 * we're operating in RGB555 or RGB565 mode. 175 * we're operating in 444, 5551 or 565 mode.
149 */ 176 */
150 if (var->green.length != 5 && var->green.length != 6) 177 if (var->green.length == 4 && caps & CLCD_CAP_444)
151 var->green.length = 6; 178 caps &= CLCD_CAP_444;
179 if (var->green.length == 5 && caps & CLCD_CAP_5551)
180 caps &= CLCD_CAP_5551;
181 else if (var->green.length == 6 && caps & CLCD_CAP_565)
182 caps &= CLCD_CAP_565;
183 else {
184 /*
185 * PL110 officially only supports RGB555,
186 * but may be wired up to allow RGB565.
187 */
188 if (caps & CLCD_CAP_565) {
189 var->green.length = 6;
190 caps &= CLCD_CAP_565;
191 } else if (caps & CLCD_CAP_5551) {
192 var->green.length = 5;
193 caps &= CLCD_CAP_5551;
194 } else {
195 var->green.length = 4;
196 caps &= CLCD_CAP_444;
197 }
198 }
199
200 if (var->green.length >= 5) {
201 var->red.length = 5;
202 var->blue.length = 5;
203 } else {
204 var->red.length = 4;
205 var->blue.length = 4;
206 }
152 break; 207 break;
153 case 32: 208 case 32:
154 if (fb->panel->cntl & CNTL_LCDTFT) { 209 /* If we can't do 888, reject */
155 var->red.length = 8; 210 caps &= CLCD_CAP_888;
156 var->green.length = 8; 211 if (!caps) {
157 var->blue.length = 8; 212 ret = -EINVAL;
158 break; 213 break;
159 } 214 }
215
216 var->red.length = 8;
217 var->green.length = 8;
218 var->blue.length = 8;
219 break;
160 default: 220 default:
161 ret = -EINVAL; 221 ret = -EINVAL;
162 break; 222 break;
@@ -168,7 +228,20 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var)
168 * the bitfield length defined above. 228 * the bitfield length defined above.
169 */ 229 */
170 if (ret == 0 && var->bits_per_pixel >= 16) { 230 if (ret == 0 && var->bits_per_pixel >= 16) {
171 if (fb->panel->cntl & CNTL_BGR) { 231 bool bgr, rgb;
232
233 bgr = caps & CLCD_CAP_BGR && var->blue.offset == 0;
234 rgb = caps & CLCD_CAP_RGB && var->red.offset == 0;
235
236 if (!bgr && !rgb)
237 /*
238 * The requested format was not possible, try just
239 * our capabilities. One of BGR or RGB must be
240 * supported.
241 */
242 bgr = caps & CLCD_CAP_BGR;
243
244 if (bgr) {
172 var->blue.offset = 0; 245 var->blue.offset = 0;
173 var->green.offset = var->blue.offset + var->blue.length; 246 var->green.offset = var->blue.offset + var->blue.length;
174 var->red.offset = var->green.offset + var->green.length; 247 var->red.offset = var->green.offset + var->green.length;